Ce numéro est-il secrètement Fibonacci?


23

Contexte

La plupart d'entre vous savent ce qu'est un numéro de Fibonacci . Certains d'entre vous savent peut-être que tous les nombres entiers positifs peuvent être représentés comme la somme d'un ou plusieurs nombres de Fibonacci distincts, selon le théorème de Zeckendorf . Si le nombre de termes dans la représentation optimale de Zeckendorf d'un entier nest lui-même un nombre de Fibonacci, nous appellerons n"secrètement" Fibonacci.

Par exemple:

139 = 89 + 34 + 13 + 3
This is a total of 4 integers. Since 4 is not a Fibonacci number, 139 is not secretly Fibonacci

140 = 89 + 34 + 13 + 3 + 1
This is a total of 5 integers. Since 5 is a Fibonacci number, 140 is secretly Fibonacci

Remarques

  • La représentation optimale de Zeckendorf peut être trouvée en utilisant un algorithme gourmand. Prenez simplement le plus grand nombre de Fibonacci <= n et soustrayez-le de n jusqu'à ce que vous atteigniez 0
  • Tous les nombres de Fibonacci peuvent être représentés comme une somme de 1 nombre de Fibonacci (lui-même). Puisque 1 est un nombre de Fibonacci, tous les nombres de Fibonacci sont également secrètement Fibonacci.

Défi

Votre défi est d'écrire un programme ou une fonction qui prend un entier et retourne si cet entier est secrètement Fibonacci.

Contribution

Vous pouvez prendre des contributions dans n'importe quel format raisonnable. Vous pouvez supposer que l'entrée sera un seul entier positif.

Sortie

Sortie l'un des deux résultats distincts pour savoir si l'entrée est secrètement Fibonacci. Les exemples incluent True/ False, 1/ 0, etc.

Notation

C'est le , donc la réponse la plus courte en octets gagne! Les failles standard sont interdites.

Cas de test

Truthy (secretly Fibonacci)
1
2
4
50
140
300099

Falsey (NOT secretly Fibonacci)
33
53
54
139
118808

6
Est-ce à dire qu'ils sont fi-curieux?
Kevin

2
Dans le cas où il est utile à quiconque: La somme optimale est la solution unique qui n'utilise pas deux nombres de Fibonacci consécutifs.
kasperd

2
@kasperd Vous avez raison, ce qui est logique si vous y réfléchissez. Si la solution avait deux numéros de Fibonacci consécutifs, ils pourraient être additionnés pour former le suivant. Si votre solution contenait 5 et 8, ce serait moins optimal que d'avoir un seul 13.
Cowabunghole

@Cowabunghole C'est l'intuition. Une preuve complète est un peu plus compliquée que ça. Si la solution contenait déjà 5, 8 et 13, vous ajouteriez 8 + 13 et non 5 + 8. Et l'autre direction doit également être prouvée.
kasperd

Réponses:



8

Python 2 , 77 octets

def f(n):z=[bin(x).count('1')for x in range(n*n+1)if x&2*x<1];print z[z[n]]<2

Essayez-le en ligne!

Cela utilise le théorème que les deux descriptions d' OEIS A003714 sont équivalentes:

Nombres fibinaires: si est la représentation de Zeckendorf de (c'est-à-dire écrire dans le système de nombres de Fibonacci) alors . Également des nombres dont la représentation binaire ne contient pas deux adjacents .n=F(i1)+F(i2)++F(ik)nna(n)=2i1+2i2++2ik 11

Nous générons suffisamment * de tels nombres, puis les utilisons zcomme mappage à partir d'entiers non négatifs sur «combien de termes sont dans la représentation de Zeckendorf de ?» En comptant 1s en binaire.n

Il reste alors à vérifier s'il z[n]s'agit d'un nombre de Fibonacci, c'est-à-dire z[z[n]] == 1.

* Au moins, semble suffisant, et expérimentalement cela semble suffisant. Je le prouverai un peu plus tard.n2+1


Vous pouvez couper deux octets en supprimant les backticks bin(x). Vous pouvez également en supprimer un en remplaçant range(n*n+1)par range(n<<n). (En supposant que 0 n'est pas valide)
nedla2004

Je ne sais pas à quoi je pensais avec les contre-coups bin(x), haha. Et, hm, 1<<nc'est déjà bien, bien plus que suffisant, mais j'aimerais garder le temps d'exécution non astronomique
Lynn

Bon point, je suppose que pouvoir exécuter le code pourrait être un attribut important. :)
nedla2004

6

Gelée , 15 octets

‘ÆḞ€fRṪạµƬL’Ɗ⁺Ị

Un lien monadique acceptant un entier non négatif qui donne 1si "Secretly Fibonacci" et 0autrement.

Essayez-le en ligne! (trop inefficace pour les cas de test plus importants)

Comment?

‘ÆḞ€fRṪạµƬL’Ɗ⁺Ị - Link: integer, I
        µƬ      - perform the monadic link to the left as a function of the current I,
                - collecting up all the inputs until the results are no longer unique:
‘               -   increment I -> I+1
 ÆḞ€            -   nth Fibonacci number for €ach n in [1,I+1]
     R          -   range from 1 to I
    f           -   filter discard (discard Fibonacci numbers not in the range, i.e. > I)
      Ṫ         -   tail (get the largest)
       ạ        -   absolute difference with I
                - This gives us a list from I decreasing by Fibonacci numbers to 0
                - e.g. for 88 we get [88,33,12,4,1,0]
                -      because (88-33)+(33-12)+(12-4)+(4-1)+(1-0)=55+21+8+3+1=88 
          L     - length (the number of Fibonacci numbers required plus one)
           ’    - decrement (the number of Fibonacci numbers required)
            Ɗ   - treat the last three links (which is everything to the left) as a monad:
             ⁺  - ...and repeat it
                - i.e. get the number of Fibonacci numbers required for the number of
                -      Fibonacci numbers required to represent I.
                -      This is 1 if I is Secretly Fibonacci, and greater if not)
              Ị - insignificant? (is the absolute value of that <= 1?)


5

C # (.NET de base) , 124 115 98 bytes

a=>{int n=0,b,c;for(;a>0;a-=b,n++)for(b=c=1;c<=a;b=c-b)c+=b;for(b=c=1;c<n;c+=b)b=c-b;return c==n;}

Essayez-le en ligne!

-3 octets: changé pendant la boucle en for (grâce à Olivier Grégoire )
-6 octets: les retours commutés utilisent une variable, b et c initialisés en dehors des boucles (merci à Kevin Cruijssen )
-17 octets: condition changée dans la deuxième boucle pour se déplacer si hors boucle et combiner avec retour, variables b et c réutilisées dans la dernière boucle (merci à raznagul )

Non golfé:

a => {
    int n = 0, b, c;                        // initialize variables

    for(; a > 0; a -= b, n++)               // increase n until a is 0
        for(b = c = 1; c <= a; b = c - b)   // set b and c to 1 for each a; set second largest Fibonacci number until largest Fibonacci number reaches a
            c += b;                         // set largest Fibonacci number of current sequence

    for(b = c = 1; c < n; c += b)           // while e is less than or equal to n, continue incrementing largest (e) Fibonacci number in the sequence
        b = c - b;                          // increment second-largest (d) Fibonacci number

    return c == n;                          // if c equals n, a is a secret Fibonacci number
}

1
for(;c<=a;b=c-b)c+=b;vous fera économiser 3 octets.
Olivier Grégoire

1
115 octets . J'ai supprimé tous les {}crochets de vos boucles et mis tout en for-loops. De plus, j'ai ajouté une variable rque nous avons définie 1dans votre if(e==n)et revenons à la fin, donc vous n'en avez qu'une return.
Kevin Cruijssen

Bon appel aux deux. J'avais essayé de changer la boucle while en for et en quelque sorte manqué le moyen facile de le faire. Il est également préférable d'avoir une variable distincte pour le retour.
Meerkat

1
En changeant la condition dans la seconde boucle e<nvous pouvez déplacer le ifà après la boucle et combiner consequentlly avec le returnpour 101 octets .
raznagul

1
Vous pouvez enregistrer encore 3 octets en réutilisant bet cdans la dernière boucle et en supprimant det e.
raznagul

4

Perl 6 , 58 octets

{(1,&[+]...*>$_)∋($_,{$^n-(1,&[+]...^*>$n).tail}...0)-1}

Essayez-le en ligne!

1, &[+] ... * > $_ n'est que la séquence de Fibonacci, arrêtée à un endroit non infini pratique (le numéro d'entrée).

$_, { $^n - (1, &[+] ...^ * > $n).tail } ... 0est une séquence de nombres, en commençant par le numéro d'entrée, et chaque élément successif obtenu en soustrayant le plus grand nombre de Fibonacci inférieur ou égal à l'élément précédent de l'élément précédent. La séquence se termine quand 0est atteinte. Par exemple, si $_est 140, alors cette séquence est 140, 51, 17, 4, 1, 0.

Soustraire un de cette séquence le traite comme un nombre, sa longueur et la différence est le nombre de nombres de Fibonacci qui, additionnés, donnent le numéro d'entrée. Ensuite, ce numéro est vérifié pour l'appartenance à la première séquence de Fibonacci.


Je n'ai pas vu ce truc avec &[+]avant! Belle économie sur le fait de ne pas avoir à définir deux termes initiaux
Jo King

1
51 octets en affectant la séquence de Fibonacci à une fonction et quelques autres changements
Jo King

Réponse JavaScript du port de l4m2, 50 octets
nwellnhof

@nwellnhof Ha, j'ai eu à peu près la même chose, sauf une petite différence
Jo King

3

Perl 6 , 48 octets

{4>($_,{$_,{$_-(1,&[+]...*>$_)[*-2]}...^0}...1)}

Essayez-le en ligne!

Transforme l'entrée en une liste de représentations Zeckendorf à plusieurs reprises jusqu'à ce qu'elle atteigne un seul nombre, puis vérifie si la longueur de la séquence était inférieure à 4.

La fonction Zenckendorf au milieu provient principalement de la réponse de Sean avec quelques améliorations.

Explication:

{4>($_,{$_,{$_-(1,&[+]...*>$_)[*-2]}...^0}...1)}
{                                              } # Anonymous code block
                                          ...     # Define a sequence:
    $_  # That starts at the input
      ,{                                 }  # Each element is defined by:
                                   ... # Another sequence that:
        $_,   # Starts at the previous element
            $_-   # The previous element minus
                1,&[+]...*     # The Fibonacci sequence
                          >$_  # Ending when it is larger than the previous element
               (             )[*-2]  # The second from last element
          {                        }...^0  # Run until 0, discarding the last element
         # This returns the length of the Zeckendorf Representation
                                         ...1  # Run this until it is length 1
 4>(                                         )  # Return true if the length of the sequence is smaller than 4

Par exemple, la séquence de 2est 2 1puisque 2est déjà un nombre de Fibonacci. La séquence de 140est 140 5 1et puisque 5 est un nombre de Fibonacci, cela renvoie vrai. La séquence de 33est 33 4 2 1, et comme ce 4n'est pas un nombre de Fibonacci, la séquence est de longueur 4.


3

05AB1E , 14 octets

ΔDÅFθ-¼}¾ÅF¾<å

Essayez-le en ligne . Pas de suite de tests pour tous les cas de test, car le counter_variablene peut pas être réinitialisé à 0 .. J'ai tout vérifié à la main et ils sont corrects.

Explication:

Δ      }          # Loop until the top of the stack no longer changes
 D                #  Duplicate the top of the stack
                  #  (implicitly the input in the first iteration)
  ÅF              #  Get a list of all Fibonacci numbers lower than this number
    θ             #  Get the last item (largest one)
     -            #  Subtract it from the number
      ¼           #  Increase the counter_variable by 1 every iteration
        ¾         # After the loop, push the counter_variable
         ÅF       # Get all Fibonacci numbers below this counter_variable
           ¾<     # Push the counter_variable again, and subtract 1
             å    # Check if this value is in the list of Fibonacci numbers
                  # (and output implicitly)

REMARQUE: le counter_variableserait 5pour l'entrée 139et 6pour l'entrée 140, car pour que la Δboucle vérifie la pile reste la même, elle fait bien sûr une itération supplémentaire.



2

Retina 0.8.2 , 61 octets

.+
$*
M`((?>\2?)(\1|\G.))*..|.
.+
$*
^(((?>\3?)(\2|^.))*.)?.$

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

.+
$*

Convertissez en unaire.

M`((?>\2?)(\1|\G.))*..|.

Comptez le nombre de numéros de Fibonacci nécessaires.

La première alternance concerne les nombres de Fibonacci qui sont au moins 2. Lors de la première passe, \2n'existe pas encore, mais heureusement c'est facultatif, donc nous n'avons pas à le faire correspondre. \1n'existe pas non plus, mais heureusement, nous avons l'alternative \G.qui correspond à un seul caractère au début du match. Les deux \2et \1donc prendre la valeur 1.

Lors des passes suivantes, \2existe, nous essayons donc de le faire correspondre. Cette fois, si elle échoue, elle échoue \1également (car elle est plus grande que \2), mais si elle réussit, elle (?>)empêche le retour en arrière, donc si elle \2correspond, mais \1pas, nous n'essayons pas simplement \1. ( \G1échoue toujours depuis que nous avons avancé après le début du patch.) Finalement \2prend la valeur précédente de \1while \1prend la somme des deux valeurs.

Nous faisons donc correspondre autant de numéros de Fibonacci que possible, en ajoutant au fur et à mesure. Puisque les sommes partielles de la séquence 1, 2, 3, 5...sont à 0, 1, 3, 6, 11...savoir 2 de moins que les nombres de Fibonacci, nous terminons en faisant correspondre 2 à la fin.

Cela ne correspond évidemment pas à 1 lui-même, donc une alternance gère ce cas.

.+
$*

Convertissez en unaire.

^(((?>\3?)(\2|^.))*.)?.$

Testez s'il s'agit d'un numéro de Fibonacci. Cela utilise la même idée que le premier test, mais il utilise à la ^place de \Get nous devons également correspondre exactement, donc il utilise une capture facultative au lieu d'une alternance car c'est golfier (mais cela augmente les nombres de capture de 1).

Rétine , 35 octets

.+
*
2}C`((?>\2?)(\1|\G.))*..|.
^1$

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

.+
*

Convertissez en unaire.

C`((?>\2?)(\1|\G.))*..|.

Comptez le nombre de numéros de Fibonacci nécessaires. (En bouclant à la fois la conversion et le nombre, vous économisez un octet entier au lieu d'obtenir le nombre en unaire en premier lieu.)

2}

Effectuez les étapes précédentes deux fois au total. Cela prend le nombre de nombres de Fibonacci nécessaires pour additionner le nombre de nombres de Fibonacci.

^1$

Si le nombre était secrètement Fibonacci, le résultat est 1.


1

Python 2 , 146 137 octets

lambda a:len(g(len(g(a))))<2
f=lambda n:n<3or f(n-2)+f(n-1)
def g(a,n=1):j=f(n-1);return[j]if a-j<1else[j]+g(a-j)if a-f(n)<0else g(a,n+1)

Essayez-le en ligne!

f () est une fonction récursive qui renvoie la valeur du nième nombre de Fibonacci. Tiré de cette réponse .

g () est une fonction récursive qui renvoie la représentation de Zeckendorf du nombre donné sous la forme d'une liste d'entiers.

Étant donné que tous les nombres de Fibonacci auront une longueur de retour d'un élément de g (), h () vérifie si la longueur de g () de g (n) == 1.

EDIT: 9 octets enregistrés grâce à nedla2004 . J'oublie toujours que les lambdas ne sont pas toujours la meilleure solution ...


1
138 octets . J'ai principalement créé gune fonction pour pouvoir définir f(n-1)une variable. Couple d' autres changements de ==la <où ils sont les mêmes.
nedla2004
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.