Q, 47 bytes
m:{*/1_-':|(0<){y-x x bin y}[*+60(|+\)\1 0]\x}
Teste
+(i;m'i:1 2 3 4 5 6 7 8 9 42 1000 12345)
leia-o como pares (i, mapa (m, i)), onde m é a função de cálculo ei os diferentes argumentos
escreve
1 1
2 2
3 3
4 3
5 5
6 5
7 10
8 8
9 8
42 272
1000 12831
12345 138481852236
Explicação
n funtion\arg aplica function (function (function (... function (args))) n times (usa internamente tal recursão) e retorna a sequência de resultados. Calculamos os 60 primeiros itens da série fibonnaci como *+60(|+\)\1 0. Nesse caso, a função é ( | +): + \ aplicado sobre uma sequência calcula somas parciais (ex + \ 1 2 3 é 1 3 6) e | inverte a seq. Portanto, cada 'iteração' calculamos somas parciais dos dois números anteriores de fibonacci e retornamos o parcial soma invertida 60(|+\)\1 0gera as seqüências 1 0, 1 1, 2 1, 3 2, 5 3, 8 5, 13 8, 21 13, ...*+ aplicado sobre esse resultado flip (traspose) e pega o primeiro. 1 2 3 5 8 13 21 34 55 ..
(cond)function\args aplica function (function (.. function (args))) enquanto cond true e retorna a sequência de resultados parciais
function[arg] aplicado sobre uma função de mais de um argumento cria uma projeção (aplicação parcial)
Podemos dar um nome aos argumentos, mas os nomes implícitos são x, y, z
{y-x x bin y}[*+60(|+\)\1 0]declara um lambda com args x, y com projeção parcial (arg x é uma série de fibonacci, calcula como * + 60 (| +) \ 1 0). x representam valores de fibonacci e y o número a processar. A pesquisa binária (bin) é usada para localizar o índice do maior número de fibonacci <= y ( x bin y) e subtrair o valor correspondente de x.
Para calcular o produto a partir de resultados parciais, nós os revertemos e calculamos a diferença de cada par ( -':|), descartamos o primeiro ( 1_porque é 0) e multiplicamos por ( */).
Se estamos interessados na soma acumulada, o código é o mesmo, mas com em +/vez de */. Também podemos usar qualquer outro operador diádico em vez de + ou *
Sobre eficiência de execução
Eu sei que neste concurso a eficiência não é um problema. Mas neste problema, podemos variar de custo linear a custo exponencial, por isso estou curioso.
Eu desenvolvi uma segunda versão (comprimento de 48 bytes, excluindo comentários) e repeti os casos de teste de bateria 1000 vezes nas duas versões.
f:*+60(|+\)\1 0;m:{*/1_-':|(0<){x-f f bin x}\x} /new version
o tempo de execução é: versão original 0'212 seg, nova versão 0'037 seg
A versão original calcula a série fibbonaci uma vez por aplicativo de função; nova versão calcula fibonacci apenas um.
Em ambos os casos, o cálculo da série de fibonacci usa recursão da cauda
2pode ser decomposto como-1 + 3. A afirmação correta do teorema de Zeckendorf é que um número de Fibonacci positivo pode ser decomposto exclusivamente como uma soma de números de Fibonacci não consecutivos com índice positivo.