Q, 47 Bytes
m:{*/1_-':|(0<){y-x x bin y}[*+60(|+\)\1 0]\x}
Prüfung
+(i;m'i:1 2 3 4 5 6 7 8 9 42 1000 12345)
Lies es als Paare (i, map (m, i)), wobei m die Rechenfunktion ist und i die verschiedenen Argumente
schreibt
1 1
2 2
3 3
4 3
5 5
6 5
7 10
8 8
9 8
42 272
1000 12831
12345 138481852236
Erläuterung
n funtion\arg
Wendet die Funktion (function (function (... function (args))) n-mal an (verwendet intern die tal-Rekursion) und gibt die Folge der Ergebnisse zurück. Wir berechnen die 60 ersten Elemente der fibonnaci-Reihe als *+60(|+\)\1 0
. In diesem Fall lautet die Funktion ( | +): + \, das über eine Sequenz angewendet wird, berechnet Teilsummen (ex + \ 1 2 3 ist 1 3 6) und kehrt die Sequenz um. Bei jeder 'Iteration' berechnen wir Teilsummen der beiden vorherigen Fibonacci-Zahlen und geben die Teilsummen zurück sums reverse 60(|+\)\1 0
generiert Sequenzen 1 0, 1 1, 2 1, 3 2, 5 3, 8 5, 13 8, 21 13, ..., *+
die über dieses Ergebnis angewendet werden, kippen (traspose) und nehmen das erste. Ergebnis ist Sequenz 1 1 2 3 5 8 13 21 34 55 ..
(cond)function\args
Wendet function (function (.. function (args))) an, während cond true ist, und gibt die Folge der Teilergebnisse zurück
function[arg]
angewendet über eine Funktion von mehr als einem Argument erzeugt eine Projektion (Teilanwendung)
Wir können den Argumenten Namen geben, aber die impliziten Namen sind x, y, z
{y-x x bin y}[*+60(|+\)\1 0]
deklariert ein Lambda mit args x, y mit partieller Projektion (arg x ist eine Fibonacci-Reihe, berechnet als * + 60 (| +) \ 1 0). x steht für Fibonacci-Werte und y für die zu verarbeitende Zahl. Die binäre Suche (bin) wird verwendet, um den Index der größeren Fibonacci-Zahl <= y ( x bin y
) zu lokalisieren und den entsprechenden Wert von x zu subtrahieren.
Um das Produkt aus Teilergebnissen zu berechnen, kehren wir diese um und berechnen die Differenz jedes Paares ( -':|
). Lassen Sie das erste ( 1_
weil 0) fallen und multiplizieren Sie es mit ( */
).
Wenn wir an akkumulierter Summe interessiert sind, ist der Code derselbe, aber mit +/
statt */
. Anstelle von + oder * können wir auch jeden anderen diadischen Operator verwenden.
Über die Effizienz der Ausführung
Ich weiß, dass Effizienz in diesem Wettbewerb kein Thema ist. Aber in diesem Problem können wir von linearen Kosten bis zu exponentiellen Kosten reichen, also bin ich neugierig.
Ich entwickelte eine zweite Version (Länge 48 Bytes ohne Kommentar) und wiederholte 1000-mal Testfälle Batterie auf beiden Versionen.
f:*+60(|+\)\1 0;m:{*/1_-':|(0<){x-f f bin x}\x} /new version
Ausführungszeit ist: Originalversion 0'212 seg, neue Version 0'037 seg
Die Originalversion berechnet die Fibbonaci-Serie einmal pro Funktionsanwendung. Neue Version berechnet Fibonacci nur eine.
In beiden Fällen verwendet die Berechnung der Fibonacci-Reihe die Schwanzrekursion
2
kann zerlegt werden als-1 + 3
. Die korrekte Aussage des Satzes von Zeckendorf lautet, dass eine positive Fibonacci-Zahl eindeutig als Summe nicht aufeinanderfolgender Fibonacci-Zahlen mit positivem Index zerlegt werden kann.