Questo numero è segretamente Fibonacci?


23

sfondo

Molti di voi sanno cos'è un numero di Fibonacci . Alcuni di voi potrebbero sapere che tutti gli interi positivi possono essere rappresentati come una somma di uno o più numeri Fibonacci distinti, secondo il Teorema di Zeckendorf . Se il numero di termini nella rappresentazione ottimale di Zeckendorf di un numero intero nè esso stesso un numero di Fibonacci, chiameremo n"segretamente" Fibonacci.

Per esempio:

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

Gli appunti

  • La rappresentazione Zeckendorf ottimale può essere trovata usando un algoritmo goloso. Prendi semplicemente il più grande numero di Fibonacci <= n e sottralo da n fino a raggiungere 0
  • Tutti i numeri di Fibonacci possono essere rappresentati come una somma di 1 numero di Fibonacci (stesso). Poiché 1 è un numero di Fibonacci, anche tutti i numeri di Fibonacci sono segretamente Fibonacci.

Sfida

La tua sfida è scrivere un programma o una funzione che accetta un numero intero e restituisce se quel numero intero è segretamente Fibonacci.

Ingresso

È possibile accettare input in qualsiasi formato ragionevole. Si può presumere che l'input sarà un singolo numero intero positivo.

Produzione

Stampa uno dei due risultati distinti per sapere se l'input è segretamente Fibonacci. Gli esempi includono True/ False, 1/ 0, ecc.

punteggio

Questo è , quindi vince la risposta più breve in byte! Sono vietate le scappatoie standard.

Casi test

Truthy (secretly Fibonacci)
1
2
4
50
140
300099

Falsey (NOT secretly Fibonacci)
33
53
54
139
118808

6
Questo significa che sono curiosi?
Kevin

2
Nel caso in cui sia utile a nessuno: la somma ottimale è la soluzione unica che non utilizza due numeri consecutivi di Fibonacci.
Kasperd,

2
@kasperd Hai ragione, il che ha senso se ci pensi. Se la soluzione avesse due numeri consecutivi di Fibonacci, potrebbero essere sommati per formare il successivo. Se la soluzione contenesse 5 e 8, sarebbe meno ottimale che avere un singolo 13.
Cowabunghole

@Cowabunghole Questa è l'intuizione. Una prova completa è un po 'più complicata di così. Se la soluzione contenesse già 5, 8 e 13 aggiungeresti 8 + 13 e non 5 + 8. E anche l'altra direzione deve essere dimostrata.
Kasperd,

Risposte:



8

Python 2 , 77 byte

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

Provalo online!

Questo fa uso del teorema secondo cui le due descrizioni di OEIS A003714 sono equivalenti:

Numeri fibbinari: se è la rappresentazione Zeckendorf di (cioè, scrivi nel sistema numerico di Fibonacci) quindi . Inoltre numeri la cui rappresentazione binaria non contiene due adiacenti .n=F(i1)+F(i2)++F(ik)nna(n)=2i1+2i2++2ik 11

Generiamo abbastanza * tali numeri, e quindi usiamo zcome mappatura da numeri interi non negativi a "quanti termini ci sono nella rappresentazione di Zeckendorf di ?" Contando 1s in binario.n

Quindi resta da verificare se si z[n]tratta di un numero di Fibonacci, ovvero z[z[n]] == 1.

* Almeno, sembra abbastanza, e sperimentalmente sembra essere abbastanza. Lo dimostrerò qualche tempo dopo.n2+1


È possibile tagliare due byte rimuovendo i backtick in giro bin(x). Puoi anche rimuoverne uno cambiando range(n*n+1)in range(n<<n). (Supponendo che 0 non sia valido)
nedla2004,

Non so cosa stavo pensando con i bastoncini in giro bin(x), ahah. E, hm, 1<<nè già molto, molto più che sufficiente, ma mi piacerebbe mantenere l'autonomia non astronomica
Lynn,

Punto giusto, immagino che essere in grado di eseguire il codice potrebbe essere un attributo importante. :)
nedla2004,

6

Gelatina , 15 byte

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

Un collegamento monadico che accetta un numero intero non negativo che produce 1"Secretly Fibonacci" e in 0altro modo.

Provalo online! (troppo inefficiente per i casi di test più grandi)

Come?

‘ÆḞ€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 Core) , 124 115 98 byte

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;}

Provalo online!

-3 byte: modificato durante il ciclo in per (grazie a Olivier Grégoire )
-6 byte: commutato ritorna per usare la variabile, inizializzata bec all'esterno dei loop (grazie a Kevin Cruijssen )
-17 byte: cambiata condizione nel secondo ciclo per spostarsi se out of loop e si combinano con return, riutilizzate variabili bec nell'ultimo loop (grazie a raznagul )

Ungolfed:

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;ti farà risparmiare 3 byte.
Olivier Grégoire,

1
115 byte . Ho rimosso tutte le {}staffe dei tuoi loop e forho inserito tutto in -loops. Inoltre, ho aggiunto una variabile rche abbiamo impostato 1nel tuo if(e==n)e restituito alla fine, quindi ne hai solo una return.
Kevin Cruijssen,

Buona chiamata ad entrambi. Avevo provato a cambiare il ciclo while in a for e in qualche modo mi mancava il modo semplice per farlo. Avere una variabile separata per il ritorno è decisamente meglio.
Meerkat,

1
Modificando la condizione nel secondo loop, e<nè possibile spostare ifil ciclo after after e di conseguenza combinarlo con il returnper 101 byte .
raznagul,

1
È possibile salvare altri 3 byte riutilizzando be cnell'ultimo ciclo e rimuovendo de e.
raznagul,

4

Perl 6 , 58 byte

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

Provalo online!

1, &[+] ... * > $_ è solo la sequenza di Fibonacci, ferma in un comodo punto non infinito (il numero di input).

$_, { $^n - (1, &[+] ...^ * > $n).tail } ... 0è una sequenza di numeri, a partire dal numero di input, e ogni elemento successivo ottenuto sottraendo il numero di Fibonacci più grande minore o uguale all'elemento precedente dall'elemento precedente. La sequenza termina quando 0viene raggiunta. Ad esempio, se lo $_è 140, allora questa sequenza è 140, 51, 17, 4, 1, 0.

Sottraendone uno da questa sequenza viene trattato come un numero, la sua lunghezza e la differenza è il numero di numeri di Fibonacci che, sommati, danno il numero di input. Quindi questo numero viene verificato per l'appartenenza alla prima sequenza di Fibonacci.


Non ho visto quel trucco con il &[+]prima! Bello salvo non dover definire due termini iniziali
Jo King,

1
51 byte assegnando la sequenza di Fibonacci a una funzione e un paio di altre modifiche
Jo King

Porta della risposta JavaScript di l4m2, 50 byte
nwellnhof

@nwellnhof Ha, avevo praticamente la stessa cosa, tranne una piccola differenza
Jo King,

3

Perl 6 , 48 byte

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

Provalo online!

Trasforma l'input in un elenco di rappresentazioni Zeckendorf ripetutamente fino a quando non raggiunge un singolo numero e quindi controlla se la lunghezza della sequenza è inferiore a 4.

La funzione Zenckendorf nel mezzo è principalmente dalla risposta di Sean con un paio di miglioramenti.

Spiegazione:

{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

Ad esempio, la sequenza per 2è 2 1poiché 2è già un numero di Fibonacci. La sequenza per 140è 140 5 1, e poiché 5 è un numero di Fibonacci questo ritorna vero. La sequenza per 33è 33 4 2 1, e poiché 4non è un numero di Fibonacci, la sequenza è di lunghezza 4.


3

05AB1E , 14 byte

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

Provalo online . Nessuna suite di test per tutti i casi di test, perché counter_variablenon è possibile reimpostare su 0 .. Tuttavia, ho verificato tutti a mano e sono corretti.

Spiegazione:

Δ      }          # 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)

NOTA: counter_variablesarebbe 5per l'input 139e 6per l'input 140, perché per fare in modo che Δ-loop verifichi che lo stack rimanga lo stesso, ovviamente esegue un'iterazione aggiuntiva.



2

Retina 0.8.2 , 61 byte

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

Provalo online! Il link include casi di test. Spiegazione:

.+
$*

Converti in unario.

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

Conta il numero di numeri di Fibonacci necessari.

La prima alternanza riguarda i numeri di Fibonacci che sono almeno 2. Al primo passaggio, \2non esiste ancora, ma per fortuna è facoltativo, quindi non dobbiamo abbinarlo. \1non esiste neanche, ma fortunatamente abbiamo l'alternativa di \G.cui corrisponde un singolo personaggio all'inizio della partita. Entrambi \2e \1quindi assumono il valore 1.

Sui passaggi successivi, \2esiste, quindi proviamo ad abbinarlo. Questa volta, se fallisce, fallisce \1anche (dal momento che è più grande di \2), ma se riesce, (?>)impedisce il backtracking, quindi se \2corrisponde, ma \1non lo facciamo, non ci proviamo solo \1. ( \G1fallisce sempre da quando siamo passati oltre l'inizio della patch.) Infine \2assume il valore precedente di \1while \1assume la somma dei due valori.

Pertanto abbiniamo il maggior numero possibile di numeri di Fibonacci, aggiungendo mentre procediamo. Poiché le somme parziali della sequenza 1, 2, 3, 5...sono 0, 1, 3, 6, 11...cioè 2 in meno rispetto ai numeri di Fibonacci, finiamo abbinando 2 alla fine.

Questo ovviamente non riesce a eguagliare 1 stesso, quindi un'alternativa gestisce quel caso.

.+
$*

Converti in unario.

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

Verifica se si tratta di un numero di Fibonacci. Questo utilizza la stessa idea del primo test ma usa ^invece di \Ge dobbiamo anche abbinare esattamente, quindi usa un'acquisizione opzionale invece di un'alternativa poiché è più golfista (ma aumenta i numeri di acquisizione di 1).

Retina , 35 byte

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

Provalo online! Il link include casi di test. Spiegazione:

.+
*

Converti in unario.

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

Conta il numero di numeri di Fibonacci necessari. (Il ciclo sia della conversione che del conteggio salva un intero byte oltre a ottenere il conteggio unario in primo luogo.)

2}

Eseguire i passaggi precedenti due volte in totale. Questo prende il conteggio dei numeri di Fibonacci necessari per sommare al conteggio dei numeri di Fibonacci.

^1$

Se il numero era segretamente Fibonacci, il risultato è 1.


1

Python 2 , 146 137 byte

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)

Provalo online!

f () è una funzione ricorsiva che restituisce il valore dell'ennesimo numero di Fibonacci. Tratto da questa risposta .

g () è una funzione ricorsiva che restituisce la rappresentazione Zeckendorf del numero dato come un elenco di numeri interi.

Poiché tutti i numeri di Fibonacci avranno una lunghezza di ritorno di un elemento da g (), h () controlla se la lunghezza di g () di g (n) == 1.

EDIT: salvato 9 byte grazie a nedla2004 . Continuo a dimenticare che le lambda non sono sempre la soluzione migliore ...


1
138 byte . Per lo più ho appena fatto guna funzione in modo da poter definire f(n-1)una variabile. Coppia altri cambiamenti da ==a <dove sono le stesse.
nedla2004,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.