212 lines
5.1 KiB
Python
212 lines
5.1 KiB
Python
from lang import *
|
|
|
|
|
|
def print_instructions(instructions):
|
|
for inst in instructions:
|
|
print(inst)
|
|
|
|
|
|
def test_min(m, n):
|
|
"""
|
|
Stores in the variable 'answer' the minimum of 'm' and 'n'
|
|
|
|
Examples:
|
|
>>> test_min(3, 4)
|
|
3
|
|
|
|
>>> test_min(4, 3)
|
|
3
|
|
"""
|
|
env = Env({"m": m, "n": n, "x0": m, "zero": 0})
|
|
p = Lth("p", "n", "x0")
|
|
x1 = Add("x1", "n", "zero")
|
|
answer = Phi("answer", ["x0", "x1"])
|
|
b = Bt("p", x1, answer)
|
|
p.add_next(b)
|
|
x1.add_next(answer)
|
|
interp(p, env)
|
|
return env.get("answer")
|
|
|
|
|
|
def test_min3(x, y, z):
|
|
"""
|
|
Stores in the variable 'answer' the minimum of 'x', 'y' and 'z'
|
|
|
|
Examples:
|
|
>>> test_min3(3, 4, 5)
|
|
3
|
|
|
|
>>> test_min3(5, 4, 3)
|
|
3
|
|
"""
|
|
env = Env({"min0": x, "y": y, "z": z, "zero": 0})
|
|
p0 = Lth("p0", "y", "min0")
|
|
min1 = Add("min1", "y", "zero")
|
|
min2 = Phi("min2", ["min1", "min0"])
|
|
p1 = Lth("p1", "z", "min2")
|
|
min3 = Add("min3", "z", "zero")
|
|
answer = Phi("answer", ["min3", "min2"])
|
|
b0 = Bt("p0", min1, min2)
|
|
p0.add_next(b0)
|
|
min1.add_next(min2)
|
|
min2.add_next(p1)
|
|
b1 = Bt("p1", min3, answer)
|
|
p1.add_next(b1)
|
|
min3.add_next(answer)
|
|
interp(p0, env)
|
|
return env.get("answer")
|
|
|
|
|
|
def test_div(m, n):
|
|
"""
|
|
Stores in the variable 'answer' the integer division of 'm' and 'n'.
|
|
|
|
Examples:
|
|
>>> test_div(30, 4)
|
|
7
|
|
|
|
>>> test_div(4, 3)
|
|
1
|
|
|
|
>>> test_div(1, 3)
|
|
0
|
|
"""
|
|
env = Env({"d0": 0, "m0": m, "one": 1, "n": n, "minus_n": -n, "zero": 0})
|
|
d1 = Phi("d1", ["d0", "d2"])
|
|
m1 = Phi("m1", ["m0", "m2"])
|
|
p = Geq("p", "m1", "n")
|
|
m2 = Add("m2", "m1", "minus_n")
|
|
d2 = Add("d2", "d1", "one")
|
|
answer = Add("answer", "d1", "zero")
|
|
b = Bt("p", m2, answer)
|
|
d1.add_next(m1)
|
|
m1.add_next(p)
|
|
p.add_next(b)
|
|
m2.add_next(d2)
|
|
d2.add_next(d1)
|
|
interp(d1, env)
|
|
return env.get("answer")
|
|
|
|
|
|
def test_fact(n):
|
|
"""
|
|
Stores in the variable 'answer' the factorial of 'n'.
|
|
|
|
Examples:
|
|
>>> test_fact(3)
|
|
6
|
|
"""
|
|
env = Env({"two": 2, "n0": n, "f0": 1, "m_one": -1, "zero": 0})
|
|
n1 = Phi("n1", ["n0", "n2"])
|
|
f1 = Phi("f1", ["f0", "f2"])
|
|
p = Geq("p", "n1", "two")
|
|
f2 = Mul("f2", "f1", "n1")
|
|
n2 = Add("n2", "n1", "m_one")
|
|
answer = Add("answer", "f1", "zero")
|
|
b = Bt("p", f2, answer)
|
|
n1.add_next(f1)
|
|
f1.add_next(p)
|
|
p.add_next(b)
|
|
f2.add_next(n2)
|
|
n2.add_next(n1)
|
|
interp(n1, env)
|
|
return env.get("answer")
|
|
|
|
|
|
def test_fib(n):
|
|
"""
|
|
Stores in the variable 'answer' the n-th number of the Fibonacci sequence,
|
|
considering that the sequence is 0, 1, 1, 2, 3, 5, ...
|
|
|
|
Examples:
|
|
>>> test_fib(2)
|
|
1
|
|
>>> test_fib(3)
|
|
2
|
|
>>> test_fib(6)
|
|
8
|
|
"""
|
|
env = Env({"N": n, "zero": 0, "one": 1})
|
|
a = Phi("a", ["zero", "b"])
|
|
b = Phi("b", ["one", "sum"])
|
|
c1 = Phi("c1", ["zero", "c2"])
|
|
p = Lth("p", "c1", "N")
|
|
answer = Add("answer", "a", "zero")
|
|
sum_ = Add("sum", "a", "b")
|
|
c2 = Add("c2", "c1", "one")
|
|
b_aux = Add("b_aux", "b", "zero")
|
|
branch = Bt("p", sum_, answer)
|
|
a.add_next(b)
|
|
b.add_next(c1)
|
|
c1.add_next(p)
|
|
p.add_next(branch)
|
|
sum_.add_next(c2)
|
|
c2.add_next(b_aux)
|
|
b_aux.add_next(a)
|
|
interp(a, env)
|
|
return env.get("answer")
|
|
|
|
|
|
def test_fib_swap_problem(n):
|
|
"""
|
|
This implementation of the Fibonacci Sequence illustrates the so-called
|
|
swap problem. If we do not evaluate the phi-functions in blocks, then we
|
|
might get wrong results.
|
|
|
|
Examples:
|
|
>>> test_fib_swap_problem(2)
|
|
4
|
|
>>> test_fib_swap_problem(3)
|
|
8
|
|
>>> test_fib_swap_problem(6)
|
|
64
|
|
"""
|
|
env = Env({"N": n, "zero": 0, "one": 1})
|
|
b = Phi("b", ["one", "sum"])
|
|
a = Phi("a", ["zero", "b"])
|
|
c1 = Phi("c1", ["zero", "c2"])
|
|
p = Lth("p", "c1", "N")
|
|
answer = Add("answer", "a", "zero")
|
|
sum_ = Add("sum", "a", "b")
|
|
c2 = Add("c2", "c1", "one")
|
|
branch = Bt("p", sum_, answer)
|
|
b.add_next(a)
|
|
a.add_next(c1)
|
|
c1.add_next(p)
|
|
p.add_next(branch)
|
|
sum_.add_next(c2)
|
|
c2.add_next(b)
|
|
interp(b, env)
|
|
return env.get("answer")
|
|
|
|
|
|
def test_fib_swap_problem_fixed_with_phi_blocks(n):
|
|
"""
|
|
This implementation of the Fibonacci Sequence illustrates the so-called
|
|
swap problem. If we do not evaluate the phi-functions in blocks, then we
|
|
might get wrong results.
|
|
|
|
Examples:
|
|
>>> test_fib_swap_problem_fixed_with_phi_blocks(2)
|
|
1
|
|
>>> test_fib_swap_problem_fixed_with_phi_blocks(3)
|
|
2
|
|
>>> test_fib_swap_problem_fixed_with_phi_blocks(6)
|
|
8
|
|
"""
|
|
env = Env({"N": n, "zero": 0, "one": 1})
|
|
b = Phi("b", ["one", "sum"])
|
|
a = Phi("a", ["zero", "b"])
|
|
c1 = Phi("c1", ["zero", "c2"])
|
|
p = Lth("p", "c1", "N")
|
|
answer = Add("answer", "a", "zero")
|
|
sum_ = Add("sum", "a", "b")
|
|
c2 = Add("c2", "c1", "one")
|
|
branch = Bt("p", sum_, answer)
|
|
phi_block = PhiBlock([b, a, c1], [0, c2.ID])
|
|
phi_block.add_next(p)
|
|
p.add_next(branch)
|
|
sum_.add_next(c2)
|
|
c2.add_next(phi_block)
|
|
interp(phi_block, env)
|
|
return env.get("answer") |