Q, 47 byte
m:{*/1_-':|(0<){y-x x bin y}[*+60(|+\)\1 0]\x}
Test
+(i;m'i:1 2 3 4 5 6 7 8 9 42 1000 12345)
leggilo come coppie (i, map (m, i)), dove m è la funzione di calcolo e i diversi argomenti
scrive
1 1
2 2
3 3
4 3
5 5
6 5
7 10
8 8
9 8
42 272
1000 12831
12345 138481852236
Spiegazione
n funtion\arg
applica la funzione (funzione (funzione (... funzione (args))) n volte (usa internamente la ricorsione tal) e restituisce la sequenza dei risultati. Calcoliamo i primi 60 elementi delle serie fibonnaci come *+60(|+\)\1 0
. In quel caso la funzione è ( | +): + \ applicato su una sequenza calcola somme parziali (ex + \ 1 2 3 è 1 3 6) e | inverte il seq. Quindi ogni 'iterazione' calcoliamo somme parziali dei due precedenti numeri di fibonacci e restituiamo il parziale somme invertite 60(|+\)\1 0
genera sequenze 1 0, 1 1, 2 1, 3 2, 5 3, 8 5, 13 8, 21 13, ... *+
applicate su questo risultato capovolgile (trasponi) e prende la prima. Il risultato è la sequenza 1 1 2 3 5 8 13 21 34 55 ..
(cond)function\args
applica la funzione (funzione (.. funzione (args))) mentre cond true e restituisce la sequenza di risultati parziali
function[arg]
applicato su una funzione di più di un argomento crea una proiezione (applicazione parziale)
Possiamo dare un nome agli arg, ma i nomi impliciti sono x, y, z
{y-x x bin y}[*+60(|+\)\1 0]
dichiara un lambda con args x, y con proiezione parziale (arg x è una serie di fibonacci, calcola come * + 60 (| +) \ 1 0). x rappresentano i valori di fibonacci e y il numero da elaborare. La ricerca binaria (bin) viene utilizzata per individuare l'indice del numero maggiore di fibonacci <= y ( x bin y
) e sottrarre il valore corrispondente di x.
Per calcolare il prodotto dai risultati parziali, li invertiamo e calcoliamo la differenza di ogni coppia ( -':|
), rilasciamo il primo ( 1_
perché è 0) e moltiplichiamo (*/
).
Se siamo interessati alla somma accumulata, il codice è lo stesso, ma con +/
invece di*/
. Possiamo anche usare qualsiasi altro operatore diadico invece di + o *
Informazioni sull'efficienza dell'esecuzione
So che in questo concorso l'efficienza non è un problema. Ma in questo problema possiamo variare dal costo lineare al costo esponenziale, quindi ne sono curioso.
Ho sviluppato una seconda versione (lunghezza 48 byte escluso il commento) e ripetuto test case batteria 1000 volte su entrambe le versioni.
f:*+60(|+\)\1 0;m:{*/1_-':|(0<){x-f f bin x}\x} /new version
il tempo di esecuzione è: versione originale 0'212 seg, nuova versione 0'037 seg
La versione originale calcola la serie fibbonaci una volta per applicazione di funzione; la nuova versione calcola fibonacci solo uno.
In entrambi i casi il calcolo della serie fibonacci utilizza la ricorsione della coda
2
può essere scomposto come-1 + 3
. L'affermazione corretta del teorema di Zeckendorf è che un numero di Fibonacci positivo può essere scomposto in modo univoco come una somma di numeri di Fibonacci non consecutivi con indice positivo.