from linked_list_Wed import LinkedListNode

def recursive_append(b: LinkedListNode, data: object) -> None:
    """
    recursively append a node with data to linked list headed by b
    """
    if b.next_ is None:
        b.next_= LinkedListNode(data)
    else:
        recursive_append(b.next_,data)

def fibonacci(n: int) -> int:
    """
    Return the nth fibonacci number, that is n if n < 2,
    or fibonacci(n-2) + fibonacci(n-1) otherwise.

    >>> fibonacci(0)
    0
    >>> fibonacci(1)
    1
    >>> fibonacci(3)
    2
    """
    if n < 2:
        return n
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

def fib_memo(n: int, seen: dict) -> int:
    """
    Return the nth fibonacci number (n) reasonably quickly.
    uses seen to store already-seen results

    """
    if n not in seen:
        if n < 2:
            seen[n]  = n
        else:
            seen[n]  = fib_memo(n - 2, seen) + fib_memo(n - 1 , seen)
    # print(seen)
    return seen[n]


if __name__ == '__main__':
    import doctest
    doctest.testmod()

# b = LinkedListNode(1)
# print(b)
# recursive_append(b,2)
# print(b)
# for i in range(3,950):
#     recursive_append(b, i)
# print(b)
#
# for i in range(950,998):
#     recursive_append(b, i)
# print(b)

# print(fibonacci(50))
# print(fibonacci(300))

print(fib_memo(500,{}))

# print(fib_memo(300,{}))
# print(fibonacci(10))
#
# print(fibonacci(34))
# print(fibonacci(39))
