Task: Padovan sequence


C++: #include <iostream>
#include <map>
#include <cmath>



int pRec(int n) {
    static std::map<int,int> memo;
    auto it = memo.find(n);
    if (it != memo.end()) return it->second;

    if (n <= 2) memo[n] = 1;
    else memo[n] = pRec(n-2) + pRec(n-3);
    return memo[n];
}



int pFloor(int n) {
    long const double p = 1.324717957244746025960908854;
    long const double s = 1.0453567932525329623;
    return std::pow(p, n-1)/s + 0.5;
}


std::string& lSystem(int n) {
    static std::map<int,std::string> memo;
    auto it = memo.find(n);
    if (it != memo.end()) return it->second;
    
    if (n == 0) memo[n] = "A";
    else {
        memo[n] = "";
        for (char ch : memo[n-1]) {
            switch(ch) {
                case 'A': memo[n].push_back('B'); break;
                case 'B': memo[n].push_back('C'); break;
                case 'C': memo[n].append("AB"); break;
            }
        }
    }
    return memo[n];
}


using pFn = int(*)(int);
void compare(pFn f1, pFn f2, const char* descr, int stop) {
    std::cout << "The " << descr << " functions ";
    int i;
    for (i=0; i<stop; i++) {
        int n1 = f1(i);
        int n2 = f2(i);
        if (n1 != n2) {
            std::cout << "do not match at " << i
                      << ": " << n1 << " != " << n2 << ".\n";
            break;
        }
    }
    if (i == stop) {
        std::cout << "match from P_0 to P_" << stop << ".\n";
    }
}

int main() {
    
    std::cout << "P_0 .. P_19: ";
    for (int i=0; i<20; i++) std::cout << pRec(i) << " ";
    std::cout << "\n";
    
    
    compare(pFloor, pRec, "floor- and recurrence-based", 64);
    
    
    std::cout << "\nThe first 10 L-system strings are:\n";
    for (int i=0; i<10; i++) std::cout << lSystem(i) << "\n";
    std::cout << "\n";
    
    
    compare(pFloor, [](int n){return (int)lSystem(n).length();}, 
                            "floor- and L-system-based", 32);
    return 0;
}






Python: from math import floor
from collections import deque
from typing import Dict, Generator


def padovan_r() -> Generator[int, None, None]:
    last = deque([1, 1, 1], 4)
    while True:
        last.append(last[-2] + last[-3])
        yield last.popleft()

_p, _s = 1.324717957244746025960908854, 1.0453567932525329623

def padovan_f(n: int) -> int:
    return floor(_p**(n-1) / _s + .5)

def padovan_l(start: str='A',
             rules: Dict[str, str]=dict(A='B', B='C', C='AB')
             ) -> Generator[str, None, None]:
    axiom = start
    while True:
        yield axiom
        axiom = ''.join(rules[ch] for ch in axiom)


if __name__ == "__main__":
    from itertools import islice

    print("The first twenty terms of the sequence.")
    print(str([padovan_f(n) for n in range(20)])[1:-1])

    r_generator = padovan_r()
    if all(next(r_generator) == padovan_f(n) for n in range(64)):
        print("\nThe recurrence and floor based algorithms match to n=63 .")
    else:
        print("\nThe recurrence and floor based algorithms DIFFER!")

    print("\nThe first 10 L-system string-lengths and strings")
    l_generator = padovan_l(start='A', rules=dict(A='B', B='C', C='AB'))
    print('\n'.join(f"  {len(string):3} {repr(string)}"
                    for string in islice(l_generator, 10)))

    r_generator = padovan_r()
    l_generator = padovan_l(start='A', rules=dict(A='B', B='C', C='AB'))
    if all(len(next(l_generator)) == padovan_f(n) == next(r_generator)
           for n in range(32)):
        print("\nThe L-system, recurrence and floor based algorithms match to n=31 .")
    else:
        print("\nThe L-system, recurrence and floor based algorithms DIFFER!")