with ada.text_io; use ada.text_io; with ada.integer_text_io; use ada.integer_text_io;
procedure fibs2 is
    type memo_t is array(natural range <>) of integer range -1 .. natural'last;
    -- For holding solutions to smaller problems

    -- TOP DOWN: RECURSIVE Solution: Elegant, but slow! ----------------
    function fib_rec(n: Natural) return natural is
        (if n in 0 .. 1 then 1 else fib_rec(n-1) + fib_rec(n-2));


    -- TOP DOWN: MEMOIZED HELPER ---------------------------------------------
    function fib_memo_helper(n: Natural; m: in out memo_t) return Natural is
        fmnm2: Natural;  -- allows doing recursive calls separately
    begin
        if m(n) < 0 then
            fmnm2 := fib_memo_helper(n - 2, m);
            m(n) := fib_memo_helper(n - 1, m) + fmnm2;
        end if;
        return m(n);
    end fib_memo_helper;

    -- TOP DOWN: MEMOIZED: Recursion, with a memo ---------------------
    -- Smaller problems solved once and solutions stored in memo m
    function fib_memo(n: Natural) return Natural is
        m: memo_t(0 .. n) := (0 | 1 => 1, others => -1);
    begin
        return fib_memo_helper(n, m);
    end fib_memo;


    -- BOTTOM UP: (SIMPLE) DYNAMIC PROGRAMMING (no optimization) --------------
    -- Who needs recursion!
    function fib_bottom_up(n: Natural) return Natural is
        m: memo_t(0 .. n) := (0 | 1 => 1, others => -1);
    begin
        for i in 2 .. n loop
            m(i) := m(i - 1) + m(i - 2);
        end loop;
        return m(n);
    end fib_bottom_up;

begin
    for i in 1 .. 15 loop
        put(i);
        put(fib_rec(i));

        put(fib_memo(i));

        put(fib_bottom_up(i));
        new_line;
    end loop;
end fibs2;
-- OUTPUT:
--            1          1          1          1
--            2          2          2          2
--            3          3          3          3
--            4          5          5          5
--            5          8          8          8
--            6         13         13         13
--            7         21         21         21
--            8         34         34         34
--            9         55         55         55
--           10         89         89         89
--           11        144        144        144
--           12        233        233        233
--           13        377        377        377
--           14        610        610        610
--           15        987        987        987