For my theory of computing languages class, we got a homework assignment to implement a piece of code in a language that only has while statements for flow control (no if statements). This is mainly to prove that you can write a Turing-complete language with only a while loop.
For those of you who can understand language grammars, here are the language rules:
S -> S;S | while C do S od | id := E
E -> E + T | T | E - T
T -> T * F | F | F / T
F -> id | cons | (E)
C -> E = E | E > E | E < E | E >= E | E <= E | E != E | C and C | C or C | not(C)
This is copied from my class notes, so don't blame me if something is missing or incorrect!
The piece of code to implement is this:
if d = 0 do
x := 1
else
x := a / d
At any rate, if you want to go ahead and write that using the language rules above, go ahead. Otherwise, go ahead and write it in whatever language you're most comfortable in. But there are a few caveats!
No if statements or any other kind of flow control other than while loops.
No cheating: the grammar above doesn't include any break statements, return statements, or exceptions. Don't use them.
I've got my piece of code written for this (which I'll post just to prove this isn't a show me teh codez post). I'm kinda curious what anyone else can come up with though.
It can be done with a single while loop, but it is not that clear:
while d == 0 do
d := 1;
a := 1
od
x := a / d;
Explanation, if d = 0, then d will be 1, also a will be 1. This ends the loop.
Now x is set to a / d which is fine, because if d was 0, a / d evaluates to 1.
Here's my code:
continue := True
while d = 0 and continue do
x := 1
continue := False
od
while d != 0 and continue do
x := a/d
continue := False
od
Would this work?
td := d
x := 1
while td != 0 do
x := a / d
td := 0
od
To be Turing Complete, you need to support both selection and iteration. While loops obviously iterate. Selection can be accomplished by making it go through the loop once if the condition is true, and not at all otherwise.
So worst case you can do everything you need to by applying those techniques. I'd imagine some complicated control flows would get ugly fast though. :-)
Without using details of the true or false branches, and without repeating the predicate:
statementIncomplete := True
while d = 0 and statementIncomplete do
x := 1
statementIncomplete := False
od
while statementIncomplete do
x := a/d
statementIncomplete := False
od
This is an expansion of Eamon's answer.
The semantics of if <condition> then <stmt> else <stmt> fi is the following:
evaluate <condition>;
if it was true, execute the statement between then and else;
otherwise, execute the statement between else and fi.
The semantics of while <condition> do <stmt> od is the following:
evaluate <condition>;
if false, the while statement is done executing;
otherwise, execute the statement between do and od, and execute the while statement again.
To express if A then B else C in terms of while, perform the following transformation:
Let gensymN be a name not used for any other variable; then emit the following code
gensymN := 0;
while gensymN = 0 and A do B; gensymN = 1; od;
while gensymN = 0 do C; gensymN = 1; od
The semantics of this program is:
Assign 0 to gensymN.
Evaluate gensymN = 0 and A (it's true iff A is true)
If true, then:
execute B
execute gensymN = 1
evaluate gensymN = 0 and A (it's false)
evaluate gensymN = 0 (it's false)
else (if gensymN = 0 and A was false):
evaluate gensymN = 0 (it's true)
execute C
execute gensymN := 1
evaluate gensymN = 0 (it's false)
Observe the following substructure of the above:
It (effectively) evaluates A;
If true, it executes B, otherwise C.
Apart from A, B and C, the program (fragment) only fiddles with gensymN, which is not present in the input program.
Hence this program has the same semantics as
if A then B else C fi; gensymN := 1
One footnote: if A is true when evaluated, it will be evaluated once again (unless and is short-circuiting). If the language allows storing booleans in variables, one can introduce one more dummy variable and do dummy := A; <insert the above program here, with dummy instead of A>. Then the two evaluations of dummy are essentially just a load. If evaluating boolean expressions cannot have side effects, preventing the second evaluation is not necessary for correctness; it may (or may not) be an optimization.
Take the above as a "soft proof", with the provisos of the preceding paragraph, that this is a correct fully general translation of if to while. The full generality sets this (= Eamon's) answer apart from the others, in my view.
Related
I have written the following assign statement:
assign F = (BCD == 4'd1 | BCD == 4'd2 | BCD == 4'd3 | BCD == 4'd4 | BCD == 4'd5) ? 1'b1 : 1'b0;
where if the BCD input (4-bits) is 1-5, the function returns a 1 and otherwise returns a 0. This works perfectly how I intended, but I'm looking for a more efficient way to write the "OR" parts. Is there a more efficient way to write this?
There's no need for the ternary operator here. The result of each equality(==) is 1-bit, and you are doing a bit-wise OR (|). You probably should be using a logical OR (||) whose result is also 1-bit.
assign F = (BCD == 4'd1 || BCD == 4'd2 || BCD == 4'd3 || BCD == 4'd4 || BCD == 4'd5);
In SystemVerilog which most tools are supporting, you can use the inside operator
assign F = BCD inside {[1:5]}; // contiguous range
assign F = BCD inside {[1:3],5, [7:10]}; // noncontiguous values
No, one should use each complete expressions separated by |. However, in this particular situation, you can use (BCD >= 4'd1) & (BCD <= 4'd5).
Since your values are in a continuous range, this can be simplified as:
assign F = ((BCD >= 4'd1) && (BCD <= 4'd5));
If your tool set supports SystemVerilog syntax, you could also use the inside operator. Refer to IEEE Std 1800-2017, section 11.4.13 Set membership operator.
There are several ways to do this:
a) Boundary check.
assign F = (BCD > 4'd0) & (BCD < 4'd6);
b) OR reduction and a high limit check.
assign F = |BCD & (BCD < 4'd6);
c) This is a behavioural hardware description, it would be optimized by the synthesis tool. It is parameterized, though.
localparam LOW = 1;
localparam HIGH = 5;
integer i;
reg F;
always # (*) begin
F = 1'b0;
for(i = LOW; i <= HIGH; i = i + 1) begin: val_check
if(BCD == i[3:0]) F = 1'b1;
end
end
**{a^i b^j c^k d^m | i+j=k+m | i<m}**
The grammar should allow the language in order abbccd not cbbcda. First should be the a's then b's and so on.
I know that you must "count" the number of a's and b's you are adding to make sure there are an equivalent number of c's and d's. I just can't seem to figure out how to make sure there are more c's than a's in the language. I appreciate any help anyone can give. I've been working on this for many hours now.
Edit:
The grammar should be Context Free
I have only got these two currently because all others turned out to be very wrong:
S -> C A D
| B
B -> C B D
|
C -> a
| b
D -> c
| d
and
S -> a S d
| A
A -> b A c
|
(which is close but doesn't satisfy the i < k part)
EDIT: This is for when i < k, not i < m. OP changed the problem, but I figure this answer may still be useful.
This is not a context free grammar, and this can be proven with the pumping lemma which states that if the grammar is context free, there exists an integer p > 0, such that all strings in the language of length >= p can be split into a substring uvwxy, where len(vx) >= 1, len(vwx) <= p, and uvnwxny is a member of the language for all n >= 0.
Suppose that a value of p exists. We can create a string such that:
k = i + 1
j = m + 1
j > p
k > p
v and x cannot contain more than one type of character or be both on the left side or both on the right side, because then raising them to powers would break the grammar immediately. They cannot be the same character as each other, because then multiplying them would break the rule that i + j = k + m. v cannot be a if x is d, because then w contains the bs and cs, which makes len(vwx) > p. By the same reasoning, v cannot be as if x is cs, and v cannot be bs if x is ds. The only remaining option is bs and cs, but setting n to 0 would make i >= k and j >= m, breaking the grammar.
Therefore, it is not a context free grammar.
There has to be at least one d because i < m, so there has to be a b somewhere to offset it. T and V guarantee this criterion before moving to S, the accepted state.
T ::= bd | bTd
U ::= bc | bUc
V ::= bUd | bVd
S ::= T | V | aSd
I have a method to calculate the exponent, but it doesnt like the c := c * a. If i do something like c := a. it works and im unsure why its behaving this way when i try and do c := c *a.. Im new to Smalltalk, so maybe its just something im missing. Im using Pharo as my implementaton.
testPow: i1 exp: i2
"Testing exponent. i1 and i2 are integers, we calculate and then return the value as a Church numeral"
| a b c |
a := i1.
b := i2.
1 to: b do: [ :i |
c:= c*a.
].
^c.
You need to initialise c before using it. With your statement:
c := a
it works because a has a value. With:
c := c * a
it won't work because the first time through the loop, c will not be initialised to anything useful.
Just change your initialisation section to:
a := i1.
b := i2.
c := 1.
In the sample c is pointing to nil because c was not initialized. And nil (which is an object) doesn't understand the message *. Look at the values in the debugger when the exception is thrown.
I keep getting that error. Here's the code (it's for GCD):
Euc := proc (a, b)
if b = 0 then a;
else c := b;
d := a mod b;
b := d; a := c;
end if;
end proc;
I never use Maple because it gives me a headache and the documentation is a nightmare, but this assignment has to be done all in Maple... if I'm having trouble with simple GCD, I don't see me writing RSA and El Gamal by Wednesday :s
edit: Fixed it with
Euc := proc (a, b)
if b = 0 then a;
else c := b;
d := a mod b;
Euc(c,d);
end if;
end proc;
But any I'd still like to know what the problem was, in case I have to do something similar again.
Your first version attempted to assign to the formal parameters of the procedure. That was the problem.
Suppose you call your original Euc and pass in 12 for parameter a and 8 for parameter b. Inside the body of Euc, as it runs in this instance, a evaluates to 12 and a does not evaluate to a name to which you can make an assignment. When you try and make an assignment to a or b inside Euc then you see that error.
Lua is currently the fastest scripting language out there, and its not so much slower than C/C++ for some sort of programs (on par when doing pidgits 1:1), however Lua scores really bad in a few benchmarks against C/C++.
One of those is the fannkuch test (Indexed-access to tiny integer-sequence), where it scores a horrible 1:148
-- The Computer Language Benchmarks Game
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall
local function fannkuch(n)
local p, q, s, odd, check, maxflips = {}, {}, {}, true, 0, 0
for i=1,n do p[i] = i; q[i] = i; s[i] = i end
repeat
-- Print max. 30 permutations.
if check < 30 then
if not p[n] then return maxflips end -- Catch n = 0, 1, 2.
io.write(unpack(p)); io.write("\n")
check = check + 1
end
-- Copy and flip.
local q1 = p[1] -- Cache 1st element.
if p[n] ~= n and q1 ~= 1 then -- Avoid useless work.
for i=2,n do q[i] = p[i] end -- Work on a copy.
for flips=1,1000000 do -- Flip ...
local qq = q[q1]
if qq == 1 then -- ... until 1st element is 1.
if flips > maxflips then maxflips = flips end -- New maximum?
break
end
q[q1] = q1
if q1 >= 4 then
local i, j = 2, q1 - 1
repeat q[i], q[j] = q[j], q[i]; i = i + 1; j = j - 1; until i >= j
end
q1 = qq
end
end
-- Permute.
if odd then
p[2], p[1] = p[1], p[2]; odd = false -- Rotate 1<-2.
else
p[2], p[3] = p[3], p[2]; odd = true -- Rotate 1<-2 and 1<-2<-3.
for i=3,n do
local sx = s[i]
if sx ~= 1 then s[i] = sx-1; break end
if i == n then return maxflips end -- Out of permutations.
s[i] = i
-- Rotate 1<-...<-i+1.
local t = p[1]; for j=1,i do p[j] = p[j+1] end; p[i+1] = t
end
end
until false
end
local n = tonumber(arg and arg[1]) or 1
io.write("Pfannkuchen(", n, ") = ", fannkuch(n), "\n")
So how could this be optimized (of course as with any optimization you have to measure your implementation to be sure its faster). And you aren't allowed to alter the C-core of Lua for this, or use LuaJit, its about finding ways to optimizing one of Lua's weak weak points.
Robert Gould > One of those is the fannkuch test (Indexed-access to tiny integer-sequence), where it scores a horrible 1:148
When you quote numbers from the benchmarks game please show where those numbers come from so readers have some context.
In this case you seem to have taken numbers measured on the quadcore machine where the fastest programs have been re-written to exploit multiple cores. Instead of looking at elapsed time sort by CPU time and you'll see the ratio drop to 1:43.
Or look at the median and quartiles to get a better impression of how the set of C++ measurements compares to the set of Lua measurements.
Or there's a whole set of measurements where programs are forced to use just one core - Lua compared with C++ - and if you take a look at those Lua pi-digits programs you'll see that they use the C language GNU GMP library.