def recorrência_linear(valores_base,coeficientes,fun=lambda _:0,até=20):
    """
    recorrência_linear([base_0,base_1,...,base_{k-1}],[a_1,a_2,...,a_k], até)
    é a função dada pela recorrência

    n = 0   => F(n) = base_0
    n = 1   => F(n) = base_1
    ...
    n = k-1 => F(n) = base_{k-1}
    n >= k  => F(n) = [(a_1 * F(n-1)) + (a_2 * F(n-2)) + ... + (a_k * F(n-k))] + fun(n)

    Os resultados de F(0), F(1), ... , F(até) são impressos.
    """
    assert len(coeficientes) == len(valores_base), "Forneça uma quantidade de casos bases igual à ordem da recorrência!"
    contagem = len(coeficientes)-1
    calculados = valores_base.copy()
    L = {
        'E':[],
        'S':[],
        'R':[]
    }
    for i,val in enumerate(calculados[:até]):
        # print(f'{i} -> {val}\t\t[base]')
        L['E'].append(str(i))
        L['S'].append(str(val))
        L['R'].append('base')
    calculados = list(reversed(calculados))
    while contagem < até:
        val_antigo = calculados[0]
        contagem += 1
        val_novo = fun(contagem)
        for coef,val in zip(coeficientes,calculados):
            val_novo += coef*val
        calculados[0], calculados[1:] = val_novo, calculados[:-1]
        # print(f'{contagem} -> {calculados[0]}',end='\t\t')
        L['E'].append(str(contagem))
        L['S'].append(str(val_novo))
        if val_antigo != 0:
            L['R'].append(str(val_novo/val_antigo))
            # print(f'[{val_novo/val_antigo}]',end='')
        else:
            L['R'].append('-')
        # print()
    M = {
        k:max(len(x) for x in v)
        for k,v in L.items()
    }

    M['E'] = max(len('n'),M['E'])
    M['S'] = max(len('F(n)'),M['S'])
    M['R'] = max(len('Razão'),M['R'])
    
    print(f"╔{'═'*(2+M['E'])}╦{'═'*(2+M['S'])}╦{'═'*(2+M['R'])}╗")
    print(f"║ {'n':^{M['E']}} ║ {'F(n)':^{M['S']}} ║ {'Razão':^{M['R']}} ║")
    print(f"╠{'═'*(2+M['E'])}╬{'═'*(2+M['S'])}╬{'═'*(2+M['R'])}╣")

    sep = f"╟{'─'*(2+M['E'])}╫{'─'*(2+M['S'])}╫{'─'*(2+M['R'])}╢"
    for i in range(len(L['E'])):
        if i > 0:
            print(sep)
        print(f"║ {L['E'][i]:>{M['E']}} ║ {L['S'][i]:>{M['S']}} ║ {L['R'][i]:>{M['R']}} ║")

    print(f"╚{'═'*(2+M['E'])}╩{'═'*(2+M['S'])}╩{'═'*(2+M['R'])}╝")
