Les nombres initiaux les plus bas dans une séquence de type Fibonacci

22

Étant donné une entrée entière positive N , sortez les deux nombres non négatifs, a et b , où a <b , avec la valeur moyenne la plus faible possible, ce qui fera que le nombre N fera partie de la séquence de relations récurrentes:

f(0) = a
f(1) = b
f(n) = f(n-2)+f(n-1)

Dans le cas où il y a plus d'une solution où la moyenne de a et b est minimale, alors vous devriez sortir celle avec le b le plus bas .

Vous pouvez supposer que N est dans la plage représentative des entiers dans votre langue / système.

Cas de test

N = 1
a = 0, b = 1

N = 15
a = 0, b = 3

N = 21
a = 0, b = 1

N = 27
a = 0, b = 9   <- Tricky test case. [3, 7] is not optimal and [4, 3] is not valid

N = 100
a = 4, b = 10

N = 101
a = 1, b = 12

N = 102
a = 0, b = 3

N = 1000
a = 2, b = 10
Stewie Griffin
la source
Si a>=0et a<by a-t-il déjà plusieurs solutions?
Jonathan Allan
Je ne peux pas garantir qu'il existe ou non plusieurs solutions. Les deux 1,4et 2,3donneraient 5, et ils ont la même moyenne. Je suppose qu'il est possible de trouver des cas similaires à celui-ci, où ce sont les valeurs moyennes les plus faibles. Si vous pouvez montrer / prouver qu'il n'y a pas plusieurs solutions, vous n'avez pas besoin de vérifier cette condition.
Stewie Griffin
2
totalement inspiré par codegolf.stackexchange.com/q/147200/67961
J42161217
3
La séquence OEIS correspondante pour la moyenne la plus basse possible, A249783 , a un graphique d'aspect sauvage .
Peter Kagey
1
@ ØrjanJohansen J'ai ajouté une preuve à ma réponse qu'il n'y a pas de solutions en double (puisque ma réponse en dépendait).
cardboard_box

Réponses:

8

Husk , 19 18 16 14 13 15 octets

Merci Zgarb d'avoir enregistré 1 octet.

ḟö£⁰ƒẊ++ÖΣṖ2Θḣ⁰

Essayez-le en ligne!

Explication:

Avertissement: je ne comprends vraiment pas la ȯƒẊ++section du code.

Modifier: Il semble se traduire par le Haskell fix.(mapad2(+).).(++), où mapad2est la fonction Appliquer à toutes les paires adjacentes dans une liste. (Bien que, connaissant Husk, dans le contexte de ce programme, cela puisse signifier autre chose)

            Θḣ⁰    Create the list [0..input]
          Ṗ2       Generate all possible sublists of length 2
        ÖΣ         Sort them on their sums
ḟ                  Find the first element that satisfies the following predicate.
    ƒẊ++             Given [a,b], magically generate the infinite Fibonacci-like
                     sequence from [a,b] without [a,b] at the start.
 ö£⁰                 Is the input in that list (given that it is in sorted order)?
H.PWiz
la source
Je suis sûr que j'ai essayé ça ...
H.PWiz
8

JavaScript (Node.js) , 92 90 89 91 83 82 octets

-3 octets -1 octet grâce à ThePirateBay

-8 -9 octets grâce à Neil.

f=(n,a=1,b=0,c=(a,b)=>b<n?c(a+b,a):b>n)=>c(a,b)?b+2<a?f(n,a-1,b+1):f(n,b-~a):[b,a]

Essayez-le en ligne!

Remarque: cette solution repose sur le fait qu'il n'y a jamais plusieurs solutions minimales.

Preuve qu'il n'y a jamais de solutions multiples:

Soit FIB(a,b,k)la séquence de Fibonacci commençant par a,b:

FIB(a,b,0) = a
FIB(a,b,1) = b
FIB(a,b,k) = FIB(a,b,k-1) + FIB(a,b,k-2)

Lemme 1

La différence entre les séquences de type Fibonacci est elle-même de type Fibonacci, c'est-à-dire FIB(a1,b1,k) - FIB(a0,b0,k) = FIB(a1-a0,b1-b0,k). La preuve est laissée au lecteur.

Lemme 2

Car n >= 5, il a,bexiste une solution satisfaisante a+b < n:

si nc'est pair,FIB(0,n/2,3) = n

si nc'est étrange,FIB(1,(n-1)/2,3) = n

Preuve

Cas où n < 5peuvent être vérifiés de manière exhaustive.

Supposons que nous ayons deux solutions minimales pour n >= 5, a0,b0et a1,b1avec a0 + b0 = a1 + b1et a0 != a1.

Il existe alors k0,k1tel FIB(a0,b0,k0) = FIB(a1,b1,k1) = n.

  • Cas 1: k0 = k1

    WLOG suppose b0 < b1(et donc a0 > a1)

    Soit DIFF(k)la différence entre les séquences de type Fibonnaci commençant par a1,b1et a0,b0:

    DIFF(k) = FIB(a1,b1,k) - FIB(a0,b0,k) = FIB(a1-a0,b1-b0,k) (Lemme 1)

    DIFF(0) = a1 - a0 < 0

    DIFF(1) = b1 - b0 > 0

    DIFF(2) = (a1+b1) - (a0+b0) = 0

    DIFF(3) = DIFF(1) + DIFF(2) = DIFF(1) > 0

    DIFF(4) = DIFF(2) + DIFF(3) = DIFF(3) > 0

    Une fois qu'une séquence de type Fibonnaci a 2 termes positifs, tous les termes suivants sont positifs.

    Ainsi, le seul moment DIFF(k) = 0est le moment k = 2, donc le seul choix k0 = k1est 2.

    Par conséquent n = FIB(a0,b0,2) = a0 + b0 = a1 + b1

    La minimalité de ces solutions contredit le lemme 2.

  • Cas 2 k0 != k1::

    WLOG suppose k0 < k1.

    On a FIB(a1,b1,k1) = n

    Laisser a2 = FIB(a1,b1,k1-k0)

    Laisser b2 = FIB(a1,b1,k1-k0+1)

    Ensuite FIB(a2,b2,k0) = FIB(a1,b1,k1) = FIB(a0,b0,k0)(exercice pour le lecteur)

    Puisque FIB(a1,b1,k)est non négatif pour k >= 0, il est également non décroissant.

    Cela nous donne a2 >= b1 > a0et b2 >= a1+b1 = a0+b0.

    Soit ensuite DIFF(k) = FIB(a2,b2,k) - FIB(a0,b0,k) = FIB(a2-a0,b2-b0,k)(Lemme 1)

    DIFF(0) = a2 - a0 > 0

    DIFF(1) = b2 - b0 >= (a0 + b0) - b0 = a0 >= 0

    DIFF(2) = DIFF(0) + DIFF(1) >= DIFF(0) > 0

    DIFF(3) = DIFF(1) + DIFF(2) >= DIFF(2) > 0

    Encore une fois, DIFFa 2 termes positifs et donc tous les termes suivants sont positifs.

    Ainsi, le seul moment où il est possible que DIFF(k) = 0est k = 1, donc le seul choix pour k0est 1.

    FIB(a0,b0,1) = n

    b0 = n

    Cela contredit le lemme 2.

boîte en carton
la source
1
77 octets
Neil
@Neil Qui minimise bau lieu de minimiser a+b, et donc votre solution donne f(27) = [3,7]mais la solution optimale est f(27)=[0,9]. Après avoir annulé les changements de rupture, nous sommes tombés à 83 octets.
cardboard_box
1
Je pense que vous pouvez enregistrer un autre octet en utilisant b-~aau lieu de a+b+1.
Neil
1
Il y a une petite erreur dans votre deuxième cas: a2 >= a1 + b1n'est pas correct quand k1-k0=1. Au lieu de cela, vous pouvez utiliser a2 >= b1 > a0et b2 >= a1+b1 = a0+b0, puis le reste suit.
Ørjan Johansen
8

Haskell , 76 72 74 octets

MODIFIER:

  • -4 octets: @ H.PWiz a suggéré d'utiliser à la /place de div, bien que cela nécessite l'utilisation d'un type de nombre fractionnaire.
  • +2 octets: correction d'un bug avec les Enumplages en ajoutant -1.

fprend une valeur de Doubleou Rationaltapez et renvoie un tuple de même. Doubledevrait suffire pour toutes les valeurs qui ne sont pas assez grandes pour provoquer des erreurs d'arrondi, alors qu'il Rationalest théoriquement illimité.

f n|let a?b=b==n||b<n&&b?(a+b)=[(a,s-a)|s<-[1..],a<-[0..s/2-1],a?(s-a)]!!0

Essayez-le en ligne! (avec les ajustements d'en-tête de H.PWiz aux entrées / sorties Rationalau format entier)

Comment ça marche

  • ?est un opérateur imbriqué localement dans le cadre de f. a?bparcourt récursivement la séquence de Fibonacci en commençant par a,bjusqu'à ce que b>=n, revenant Truessi elle frappe nexactement.
  • Dans la liste de compréhension:
    • sitère tous les nombres de 1haut en haut, représentant la somme de aet b.
    • aitère à travers les nombres de 0à s/2-1. (Si sest impair, la fin de la plage est arrondie.)
    • a?(s-a)teste si la séquence commençant par des a,s-ahits n. Si c'est le cas, la compréhension de la liste comprend le tuple (a,s-a). (C'est-à-dire b=s-a, bien qu'il soit trop court pour mériter d'être nommé.)
    • !!0 sélectionne le premier élément (hit) dans la compréhension.
Ørjan Johansen
la source
8

APL (Dyalog) , 75 71 64 59 53 48 44 43 octets

2 octets économisés grâce à @ Adám

12 octets économisés grâce à @ngn

o/⍨k∊¨+\∘⌽⍣{k≤⊃⍺}¨oa/⍨</¨a←,⍉|-21+k←⎕

Essayez-le en ligne!

Utilise ⎕IO←0.

Comment? C'était devenu vraiment fou.

k←⎕ - attribuer une entrée à k

⍳2⍴1+k←⎕- Produit cartésien de la gamme 0à ksoi

|-\¨ - soustraire chaque élément de la paire droite de la gauche et obtenir des valeurs absolues

a←,⍉ - transposer, aplatir et assigner à a

o←a/⍨</¨a - ne conserver que les paires dont l'élément gauche est plus petit que l'élément droit, et attribuer à o

ocontient maintenant la liste de toutes les paires avec a < b, ordonnées par leur moyenne arithématique

+\∘⌽⍣{k≤⊃⍺}¨o- pour chaque paire o, appliquer des fibonacci (inverser la paire et le sperme) jusqu'à ce que le kterme ou plus soit atteint

k∊¨- puis décider si kest ce dernier terme (ce qui signifie qu'il est contenu dans la séquence)

o/⍨- et conservez les paires olà où s'applique la vérification précédente

- retourner le premier résultat.

Uriel
la source
5

Python 2 , 127 109 107 107 octets

-2 octets grâce aux ovs (passage andà *)

g=lambda x,a,b:a<=b<x and g(x,b,a+b)or b==x
f=lambda n,s=1,a=0:g(n,a,s-a)*(a,s-a)or f(n,s+(a==s),a%s+(a<s))

Essayez-le en ligne!

Des points bonus pour n,a,s-a?

Explication:

  • La première ligne déclare un lambda récursif g, qui vérifie si a, bdéveloppé comme une séquence de Fibonacci atteindra x. Il vérifie également cela a <= b, l'un des critères de la question. (Cela permettrait des cas où a == b, mais dans un tel cas 0, aaurait déjà été découvert et retourné).
    • L'inégalité enchaînée a<=b<xeffectue deux tâches pratiques à la fois: vérifier a <= b, et cela b < x.
    • Si les b < xrendements True, la fonction elle - même appelle à nouveau les deux numéros dans la séquence de Fibonacci: b, a+b. Cela signifie que la fonction continuera d'élaborer de nouveaux termes jusqu'à ce que ...
    • Si les b < xrendements False, alors nous avons atteint le point où nous devons vérifier si b==x. Si c'est le cas, cela reviendra True, ce qui signifie que la paire initiale a, batteindra finalement x. Sinon, si b > x, la paire n'est pas valide.
  • La deuxième ligne déclare un autre lambda récursif f, qui trouve la solution pour une valeur donnée n. Il essaie récursivement de nouvelles paires initiales,, a, bjusqu'à ce qu'il g(n, a, b)donne True. Cette solution est ensuite retournée.
    • La fonction compte récursivement les paires de Fibonacci initiales à l'aide de deux variables s(initialement 1) et a(initialement 0). À chaque itération, aest incrémenté et a, s-aest utilisé comme première paire. Cependant, lorsqu'il est aatteint s, il est remis à 0 et sincrémenté. Cela signifie que les paires sont comptées selon le modèle suivant:
      s = 1 (0, 1) (1, 0)
      s = 2 (0, 2) (1, 1) (2, 0)
      s = 3 (0, 3) (1, 2), (2, 1), (3, 0)
      
      Évidemment, cela contient des paires invalides, mais celles-ci sont éliminées instantanément lors de leur passage à g(voir le premier point).
    • Lorsque des valeurs aet ssont trouvées telles que g(n, a, s-a) == True, cette valeur est renvoyée. Comme les solutions possibles sont comptées par ordre de «taille» (triées par moyenne, puis valeur min), la première solution trouvée sera toujours la plus petite, comme le demande le défi.
FlipTack
la source
3

R , 183 octets 160 octets

n=scan();e=expand.grid(n:0,n:0);e=e[e[,2]>e[,1],];r=e[mapply(h<-function(n,a,b,r=a+b)switch(sign(n-r)+2,F,T,h(n,b,r)),n,e[,1],e[,2]),];r[which.min(rowSums(r)),]

Essayez-le en ligne!

Merci à Giuseppe d'avoir joué au golf 23 octets

Explication du code

n=scan()                        #STDIO input
e=expand.grid(n:0,n:0)          #full outer join of integer vector n to 0
e=e[e[,2]>e[,1],]               #filter so b > a
r=e[mapply(
  h<-function(n,a,b,r=a+b)switch(sign(n-r)+2,F,T,h(n,b,r)),
                                #create a named recursive function mid-call 
                                #(requires using <- vs = to denote local variable creation 
                                #rather than argument assignment
  n,e[,1],e[,2]),]              #map n, a and b to h() which returns a logical
                                #which is used to filter the possibilities
r[which.min(rowSums(r)),]       #calculate sum for each possibility, 
                                #get index of the minimum and return
                                #because each possibility has 2 values, the mean and 
                                #sum will sort identically.
marque
la source
1
160 octets - en général, vous devez enregistrer des octets partout où vous le pouvez, donc économiser 4 octets en supprimant un joli nom est non seulement acceptable ou encouragé, mais dans un certain sens requis par code-golf . Même ainsi, belle réponse, +1.
Giuseppe
1

Mathematica, 117 octets

If[#==1,{0,1},#&@@SortBy[(S=Select)[S[Range[0,s=#]~Tuples~2,Less@@#&],!FreeQ[LinearRecurrence[{1,1},#,s],s]&],Mean]]&


Essayez-le en ligne!

J42161217
la source
1

Gelée , 19 octets

ṫ-Sṭµ¡³e
0rŒcÇÐfSÐṂ

Essayez-le en ligne!

-1 octet grâce à la preuve par cardboard_box . Dans le cas contraire, vous pouvez ajouter UṂṚà la fin de la deuxième ligne pour 22 octets au total.

Erik le Outgolfer
la source
... un incrément de tête devrait résoudre l'observation de @ StewieGriffin.
Jonathan Allan
J'ai le sentiment que vous pouvez laisser tomber le
Jonathan Allan
1
Il nous suffit de trouver la graine qui fait que l'entrée,, xapparaît en dernier. Si x ont été trouvés au troisième index pour plusieurs, cela fonctionne pour 0,xet fonctionnerait donc également à 1,(x-1)/2( ximpair) ou 2,x/2-1( xpair), après quoi xapparaîtrait plus tard dans le résultat, de sorte que cela ne se produise pas. Pour une collision ultérieure, la moyenne ne peut être la même que si les troisièmes termes sont également les mêmes, mais alors il faut avoir une différence plus faible entre les termes initiaux (sinon ils seraient les mêmes) et donc ils auront xtrouvé à un indice ultérieur . En tant que tel, nous pouvons ṫ-Sṭµ¡i³¶ḶŒcÇÐṀéconomiser quatre octets.
Jonathan Allan
... oups, plus l'incrément:ṫ-Sṭµ¡i³¶‘ḶŒcÇÐṀ
Jonathan Allan
@StewieGriffin Ce cas de test n'existait pas quand j'ai répondu: p
Erik the Outgolfer
1

GolfScript - 88 77 octets

~:N[,{1+:a,{[.;a]}/}/][{[.~{.N<}{.@+}while\;N=]}/]{)1=\;},{(\;~+}$(\;);~~' '\

Je n'ai pas vérifié plusieurs solutions, grâce à cardboard_box!

Explication

~:N                           # Reads input
[,{1+:a,{[.;a]}/}/]           # Creates an array of pairs [a b]
[{[.~{.N<}{.@+}while\;N=]}/]  # Compute solutions
{)1=\;},         # Pairs that are not solutions are discarded
{(\;~+}$         # Sorts by mean
(\;);~~' '\      # Formats output
FedeWar
la source
Essayez-le en ligne!
Ørjan Johansen
0

Batch, 160 158 bytes

@set/aa=b=0
:g
@if %a% geq %b% set/ab-=~a,a=0
@set/ac=a,d=b
:l
@if %c% lss %1 set/ad+=c,c=d-c&goto l
@if %c% gtr %1 set/aa+=1,b-=1&goto g
@echo %a% %b%
Neil
la source
Cela donne (également) une 3 7entrée 27. La bonne solution est 0 9.
cardboard_box
@cardboard_box Vous ne voyez toujours pas où la question exige que ...
Neil
Dans la première phrase: "avec la valeur moyenne la plus faible possible".
cardboard_box
@cardboard_box Ah, désolé, c'était trop facile à ignorer.
Neil
1
@cardboard_box OK devrait être corrigé maintenant.
Neil