reset password
Author Message
rabbott
Posts: 1649
Posted 09:44 Feb 17, 2019 |

Yesterday I suggested the following for Haskell.

data FibElement = I Integer | Fib Integer | Plus deriving Show

> x = [Plus, Plus, Fib 5, Fib 4, I 3]

> x
[Plus,Plus,Fib 5,Fib 4,I 3]

> :type x
x :: [FibElement]

 

You can do something similar in Python using the __call__ and __str__ class methods. 
 

class Fib:
    
    def __init__(self, arg):
        self.arg = arg
        
    def __call__(self): 
        return fib_bottom_up_iter(self.arg) 

    def __str__(self):
        return f'Fib({self.arg})'

 

 

def fib_top_down_iter_v2(n, trace=False):
    """
    Traditional (naive) Fibonacci algorithm in a while-loop, i.e., without recursion.
    Uses two stacks. Can be traced.
    """

    (inp, stack) = ([Fib(n)], [])
    fib_top_down_iter.function_calls = 0
    while inp:
        if trace: 
            print('[' + ','.join([str(token) for token in inp]) + ']', stack)
        (inp, token) = (inp[:-1], inp[-1])
        if isinstance(token, int):
            stack = [token] + stack
        elif isinstance(token, Fib):
            n = token.arg
            fib_top_down_iter.function_calls += 1
            if n <= 2:
                inp = inp + [1]
            else:
                inp = inp + ['+', Fib(n - 1), Fib(n - 2)]
        elif token == '+':
            (n1, n2, stack) = (stack[0], stack[1], stack[2:])
            inp = inp + [n1 + n2]
        else:
            raise Exception()
    return stack[0]


fib_top_down_iter_v2(6, trace=True)


# Output #

[Fib(6)] []
[+,Fib(5),Fib(4)] []
[+,Fib(5),+,Fib(3),Fib(2)] []
[+,Fib(5),+,Fib(3),1] []
[+,Fib(5),+,Fib(3)] [1]
[+,Fib(5),+,+,Fib(2),Fib(1)] [1]
[+,Fib(5),+,+,Fib(2),1] [1]
[+,Fib(5),+,+,Fib(2)] [1, 1]
[+,Fib(5),+,+,1] [1, 1]
[+,Fib(5),+,+] [1, 1, 1]
[+,Fib(5),+,2] [1]
[+,Fib(5),+] [2, 1]
[+,Fib(5),3] []
[+,Fib(5)] [3]
[+,+,Fib(4),Fib(3)] [3]
[+,+,Fib(4),+,Fib(2),Fib(1)] [3]
[+,+,Fib(4),+,Fib(2),1] [3]
[+,+,Fib(4),+,Fib(2)] [1, 3]
[+,+,Fib(4),+,1] [1, 3]
[+,+,Fib(4),+] [1, 1, 3]
[+,+,Fib(4),2] [3]
[+,+,Fib(4)] [2, 3]
[+,+,+,Fib(3),Fib(2)] [2, 3]
[+,+,+,Fib(3),1] [2, 3]
[+,+,+,Fib(3)] [1, 2, 3]
[+,+,+,+,Fib(2),Fib(1)] [1, 2, 3]
[+,+,+,+,Fib(2),1] [1, 2, 3]
[+,+,+,+,Fib(2)] [1, 1, 2, 3]
[+,+,+,+,1] [1, 1, 2, 3]
[+,+,+,+] [1, 1, 1, 2, 3]
[+,+,+,2] [1, 2, 3]
[+,+,+] [2, 1, 2, 3]
[+,+,3] [2, 3]
[+,+] [3, 2, 3]
[+,5] [3]
[+] [5, 3]
[8] []
8

        

Last edited by rabbott at 09:50 Feb 17, 2019.
rabbott
Posts: 1649
Posted 09:56 Feb 17, 2019 |

To do what is illustrated above, you don't need the __call__ definition -- since the object is never called.  But you can call the object.

fib = Fib(6)
# Note that when you call fib, you don't give it any arguments.

# fib is a Fib object. It runs the __call__ method, which uses self.arg as the argument.
print(f'{Fib(6)} = {fib()}') # =>
 Fib(6) = 8

Last edited by rabbott at 10:05 Feb 17, 2019.