I am supposed to show that two algorithms execute identical statements in identical order. One is a tail recursive version of the other. They are written in Eiffel.
tail_rec(x:instance_type):result_type is
local
y:instance_type;
do
if b(x) then
Result :=c(x)
else
y:=d(x);
Result:=tail_rec(y)
end
end
Then the non-tail recursive version.
non_rec(x:instance_type):result_type is
do
from until b(x) loop
x:= d(x)
end;
Result:= c(x)
end
where b(x), c(x), and d(x) are any functions of type BOOLEAN, result_type, and instance_type respectively.
How are these two algorithms similar and how do they execute identical statements in identical order?
By substituting all flow-of-control constructs with gotos, (essentially turning the code from Eiffel into pseudocode,) and allowing if statements to execute only gotos, it can be shown that both functions end up consisting of the exact same set of instructions.
Let me begin by copying the original tail_rec here for convenience:
tail_rec(x:instance_type):result_type is
local
y:instance_type;
do
if b(x) then
Result := c(x)
else
y := d(x);
Result := tail_rec(y)
end
end
First, get rid of Eiffel's silly Result := construct and replace it with return for convenience. (Otherwise, we are going to have to add more gotos, and frankly, the fewer the better.)
tail_rec(x:instance_type):result_type is
local
y:instance_type;
do
if b(x) then
return c(x)
end
y := d(x);
return tail_rec(y)
end
Substitute the if-then-end with if-then goto:
tail_rec(x:instance_type):result_type is
local
y:instance_type;
do
if not b(x) then goto label1
return c(x)
label1:
y := d(x);
return tail_rec(y)
end
Replace tail recursion with another goto:
tail_rec(x:instance_type):result_type is
do
label0:
if not b(x) then goto label1
return c(x)
label1:
x := d(x);
goto label0
end
Replace if not b(x) with if b(x):
tail_rec(x:instance_type):result_type is
do
label0:
if b(x) then goto label1
x := d(x);
goto label0
label1:
return c(x)
end
Similar transformations to tail_rec should turn it into the exact same thing.
Related
Just the title, really.
Compiling
fnx {a:t#ype} repeat {n:nat} .<n>.
( x: a
, t: int n
, f: a -> a
) : a =
if t = 0 then x
else repeat (f x, t - 1, f)
gives
warning(2): [fnx] is treated as [fun] for initiating function templates!
Am i supposed to take it on faith that I didnt screw up the definition and accidentally made a non-tail-recursive function? Is there some standard way to circumvent this?
Note that 'fnx' is only meaningful for defining mutually recursive functions.
In your example, using 'fun' is just fine: the compiler can recognize the tail-recursive
call in the body of 'repeat' and turn it into a local jump.
I want to create a program in Fortran that multiplies vectors from a .dat file that has the following format:
x1 y1 z1
x2 y2 z2
The index 1 and 2 refer to the vector 1 and 2, respectively. First I want do identify the vectors, so far I have
program ex2
implicit none
real*8 x
integer i
write(6,*) "Insert the vectors from vet_in.dat"
open (10, file ="vet_in.dat")
read (10,*) x(i), i=1,3
end program ex2
The line of the read(10,*) was sugested to me, I don't quite get it, I thought fortran identified the ij matrix index. And then I wanted to multiply x1.x2, y1.y2 and z1.z2, maybe the loop and de if could be used. Can you help me to proceed?
First, you need to declare x and also y as an array of rank 1 and size 3:
real*8 x(3), y(3)
And also a scalar variable for the result
real*8 result
Don't write to unit 6, but use *:
write(*,*) "Insert..."
but I wouldn't write anything at all.
Now you can read the vectors. If they are stored in rows you can read them in one go
read(10,*) x
or
read(10,*) (x(i), i=1, 3)
(read about implied do in any textbook).
and then the same for y.
Then you can make a scalar product of them:
result = dot_product(x, y)
(see https://gcc.gnu.org/onlinedocs/gfortran/DOT_005fPRODUCT.html)
or
result = sum(x*y)
or
result = 0
do i = 1, 3
result = result + x(i) * y(i)
end do
Note that real*8 is not legal standard Fortran, just a non-standard extension. You can use double precision instead until you learn kinds.
Is there a program (may-halt? p) that can tell whether there exists an input so that (p input) halts?
I tried simple diagonalization, but it only tells me that (may-halt? diag-may-halt) must be true. It doesn't help proving whether the program exists or not.
Does such a program exist?
Nope, may-halt? doesn't exist.
(I don't think a direct proof by diagonalization would be less complex than the proof that the Halting problem is undecidable; otherwise that would be the standard example. Instead, let's reduce your problem to the Halting problem:)
Suppose there was a program may-halt? p, that decides if program p halts for some input. Then define:
halt? p x := may-halt? (\y -> if y==x then p x else ⊥)
where the thing in braces is a derived program. Lets break it down:
halt? p x := may-halt? p'
where p' is the program that (i) on input x computes p x, (ii) on any other input just loops around without terminating:
p' y := if y==x then p x else ⊥
Then may-halt? p' outputs true if and only if p x terminates.
Thus, for any program p and input x, halt? p x would decide if p x terminates. But we know that that isn't possible, so may-halt? doesn't exist.
I have a nested loop as follows :
xl = yl = [a for a in range(1,12)]
ll = [a for a in range(0,6)]
c = 0;
output = []
for x in xl:
for y in yl:
if (y > x):
for l in ll :
output.append("{0}-{1}-{2}".format(x,y,l));
c+=1;
Given a value of c which is the position of a certain term, I need to get the value of that term.
For example if c = 10, I need the 10th element of output.
it would be awesome if someone told could give me a generic formula for all nested loops.
I tried googling, but I don't even know what terms to google.
Well you have put the output into an array, so you can simply look at output[10].
As for the bigger problem that you are trying to solve, I believe that you want to learn about generators. Here is how you work with them. First you put your loop in a function, and call yield where you want and no return statement. Like so.
def loop_generator ():
xl = yl = [a for a in range(1,12)]
ll = [a for a in range(0,6)]
for x in xl:
for y in yl:
if (y > x):
for l in ll :
yield (x, y, 1)
Now x = loop_generator() will return a generator. This is an object that, every time you call next on it, will start running code in the function and will return the next point yield would be called. If you run out of yields it will raise the StopIteration exception.
So your code now can be finished off with:
my_generator = loop_generator()
# Throw away 9 values
for i in range(9):
next(my_generator)
# Get the one I want
x, y, l = next(my_generator)
# Show what I got.
print "{0}-{1}-{2}".format(x,y,l)
This strategy can be used to turn any nested loop into something that you can step through and pull values out of.
Incidentally Python's native looping constructs all know to call next and terminate cleanly on StopIteration so that the following works as you might hope:
for x, y, l in loop_generator():
print "{0}-{1}-{2}".format(x,y,l)
I have been trying to learn Erlang and have been running into some problems with ending lines in functions and case statements.
When do I use a semicolon (;), comma (,), or period inside my functions or case statements?
I like to read semicolon as OR, comma as AND, full stop as END. So
foo(X) when X > 0; X < 7 ->
Y = X * 2,
case Y of
12 -> bar;
_ -> ook
end;
foo(0) -> zero.
reads as
foo(X) when X > 0 *OR* X < 7 ->
Y = X * 2 *AND*
case Y of
12 -> bar *OR*
_ -> ok
end *OR*
foo(0) -> zero *END*
This should make it clear why there is no ; after the last clause of a case.
Comma at the end of a line of normal code.
Semicolon at the end of case statement, or if statement, etc.
The last case or if statement doesn't have anything at the end.
A period at the end of a function.
example (sorry for the random variable names, clearly this doesn't do anything, but illustrates a point):
case Something of
ok ->
R = 1, %% comma, end of a line inside a case
T = 2; %% semi colon, end of a case, but not the end of the last
error ->
P = 1, %% comma, end of a line inside a case
M = 2 %% nothing, end of the last case
end. %% period, assuming this is the end of the function, comma if not the end of the function
Period (.)
In modules, the period is used to terminate module attributes and function declarations (a.k.a. 'forms'). You can remember this because forms aren't expressions (no value is returned from them), and therefore the period represents the end of a statement.
Keep in mind that definitions of functions with different arities are considered separate statements, so each would be terminated by a period.
For example, the function definitions for hello/0 and hello/1:
hello() -> hello_world.
hello(Greeting) -> Greeting.
(Note that in the erlang shell the period is used to terminate and evaluate expressions, but that is an anomaly.)
Semicolon (;)
The semicolon acts as a clause separator, both for function clauses and expression branches.
Example 1, function clauses:
factorial(0) -> 1;
factorial(N) -> N * fac(N-1).
Example 2, expression branches:
if X < 0 -> negative;
X > 0 -> positive;
X == 0 -> zero
end
Comma (,)
The comma is an expression separator. If a comma follows an expression, it means there's another expression after it in the clause.
hello(Greeting, Name) ->
FullGreeting = Greeting ++ ", " ++ Name,
FullGreeting.
You can think of it like english punctuation. Commas are used to separate things in a series, semicolons are used to separate two very closely related independent clauses[1] (e.g. the different cases of the case statement, function clauses of the same name and arity that match different patterns), and periods are used to end a sentence (complete thought).
Or to prove you went to college. "Do not use semicolons. They are transvestite hermaphrodites representing absolutely nothing. All they do is show you've been to college." -- Kurt Vonnegut
The comma separates expressions, or arguments, or elements of a list/tuple or binary. It is overworked.