Q, 47 octets
m:{*/1_-':|(0<){y-x x bin y}[*+60(|+\)\1 0]\x}
Tester
+(i;m'i:1 2 3 4 5 6 7 8 9 42 1000 12345)
le lire sous forme de paires (i, map (m, i)), où m est la fonction de calcul et i les différents arguments
écrit
1 1
2 2
3 3
4 3
5 5
6 5
7 10
8 8
9 8
42 272
1000 12831
12345 138481852236
Explication
n funtion\arg
applique la fonction (fonction (fonction (fonction (... fonction (args)))) n fois (utilise en interne la récursion tal) et renvoie la séquence de résultats. Nous calculons les 60 premiers éléments de la série fibonnaci comme *+60(|+\)\1 0
. Dans ce cas, la fonction est ( | +): + \ appliqué sur une séquence calcule des sommes partielles (ex + \ 1 2 3 est 1 3 6), et | inverse la suite. Ainsi, à chaque 'itération', nous calculons des sommes partielles des deux nombres de fibonacci précédents et retournons la partie les sommes inversées 60(|+\)\1 0
génèrent des séquences 1 0, 1 1, 2 1, 3 2, 5 3, 8 5, 13 8, 21 13, ...*+
appliquées sur ce résultat retournez-les (transposez) et prenez la première. Le résultat est la séquence 1 1 2 3 5 8 13 21 34 55 ..
(cond)function\args
applique la fonction (fonction (.. fonction (args))) tandis que cond true, et renvoie la séquence de résultats partiels
function[arg]
appliqué sur une fonction de plusieurs arguments crée une projection (application partielle)
Nous pouvons donner un nom aux arguments, mais les noms implicites sont x, y, z
{y-x x bin y}[*+60(|+\)\1 0]
déclare un lambda avec args x, y avec projection partielle (arg x est une série de fibonacci, calcule comme * + 60 (| +) \ 1 0). x représente les valeurs de fibonacci, et y le nombre à traiter. La recherche binaire (bin) est utilisée pour localiser l'indice du plus grand nombre de fibonacci <= y ( x bin y
), et soustraire la valeur correspondante de x.
Pour calculer le produit à partir de résuls partiels, nous les inversons et calculons la différence de chaque paire ( -':|
), supprimons la première ( 1_
car est 0) et multiplions sur ( */
).
Si nous sommes intéressés par la somme accumulée, le code est le même, mais avec +/
au lieu de */
. Nous pouvons également utiliser n'importe quel autre opérateur diadique au lieu de + ou *
À propos de l'efficacité d'exécution
Je sais que dans ce concours, l'efficacité n'est pas un problème. Mais dans ce problème, nous pouvons aller du coût linéaire au coût exponentiel, donc je suis curieux de le savoir.
J'ai développé une deuxième version (longueur 48 octets hors commentaire) et répété des tests de batterie 1000 fois sur les deux versions.
f:*+60(|+\)\1 0;m:{*/1_-':|(0<){x-f f bin x}\x} /new version
le temps d'exécution est: version originale 0'212 seg, nouvelle version 0'037 seg
La version originale calcule la série fibbonaci une fois par application de fonction; nouvelle version calcule fibonacci un seul.
Dans les deux cas, le calcul des séries de fibonacci utilise la récursivité de la queue
2
peut être décomposé en-1 + 3
. L'énoncé correct du théorème de Zeckendorf est qu'un nombre de Fibonacci positif peut être décomposé de manière unique comme une somme de nombres de Fibonacci non consécutifs avec un indice positif.