Fibonacci al contrario!


42

introduzione

Conosciamo e amiamo tutti la nostra sequenza di Fibonacci e abbiamo già visto una miriade di sfide. Tuttavia, ci manca ancora un caso molto semplice che questa risposta fornirà: fibonacci invertiti! Quindi, dato che il F_ntuo lavoro è trovare n.

specificazione

Ingresso

Il tuo input sarà un numero intero non negativo, che è garantito per far parte della sequenza fibonacci.

Produzione

L'output deve essere anche un numero intero non negativo.

Cosa fare?

L'introduzione ha già detto: dato un numero di fibonacci, produce il suo indice. Il numero Fiboancci è definito come F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)e ti viene dato F(n)e deve essere restituito n.

Casi d'angolo potenziali

0 è un ingresso e un'uscita validi.
Se viene dato "1" come input, puoi emettere "1" o "2", come preferisci.
Puoi sempre presumere che il tuo input sia in realtà un numero di fibonacci.
Si può presumere che l'input sia rappresentabile come intero con segno a 32 bit.

Chi vince?

Questo è code-golf quindi vince la risposta più breve in byte!
Ovviamente si applicano le regole standard.

Casi test

0 -> 0
2 -> 3
3 -> 4
5 -> 5
8 -> 6
13 -> 7
1836311903 -> 46

39
Leggero nit-pick: questo non dovrebbe essere considerato fibonacci inverso en.m.wikipedia.org/wiki/Inverse_function
Michael

19
Quindi, iccanobiF ?!

6
@ Michael non si tratta inversa Fibonacci, perché non c'è inversa per la funzione di Fibonacci, perché è non è iniettiva (perché il "1" appare due volte). Il contrario originariamente è nato dall'idea di "lookup table reverse" che è quello che mi aspettavo che la gente facesse qui (ad esempio, mi aspettavo che lo facessero per risolvere il problema).
SEJPM,

9
La funzione qui potrebbe essere considerata un inverso destro della "funzione di Fibonacci" dagli interi non negativi all'insieme dei numeri di Fibonacci. L'esistenza di un inverso destro non implica iniettività.
Dennis,

1
@SEJPM: Mi aspettavo un compito come "scrivere un programma che spieghi la sequenza di fibonacci al contrario".
Bergi,

Risposte:


58

In realtà, 1 byte

f

Sì, c'è una soluzione per questo, dal 16 novembre 2015 .

Provalo online


Per divertimento, senza il built-in, è di 9 byte:

╗1`F╜=`╓i

Provalo online!

Spiegazione:

╗1`F╜=`╓i
╗          push input to register 0
 1`F╜=`╓   push list containing first value x (starting with x = 0) where:
   F         fib(x)
    ╜=       is equal to the input
        i  flatten the list

15
Ho un pensiero e un pensiero solo quando vedo questo: ಠ_ಠ
Addison Crump,

37
Non capisco davvero perché dovresti "sprecare" un simbolo per uno scopo così ridicolmente specifico
Fatalizza il

19
@Fatalize Le funzioni Fibonacci e inverse di Fibonacci sono state tra le prime che ho aggiunto. Anche ora, ci sono 39 comandi a byte singolo completamente inutilizzati (e chissà quanti sovraccarichi potrebbero essere utilizzati). I 256 simboli, combinati con il fatto che ci sono 5 tipi in Actual (Integer, Real, String, Iterable, Function), significano che ci sono fino a 1280 possibili funzioni unarie e 6400 possibili funzioni binarie. C'è molto spazio per comandi apparentemente inutili.
Mego

23
@Mego Stai solo cercando di competere con Mathematica per la maggior parte dei builtin?
gcampbell,

13
In realtà, è solo un byte ... lol, adoro questo nome di lingua.
nicael,

42

Mathematica, 25 byte

InverseFunction@Fibonacci

Funzione. Abbastanza autoesplicativo se me lo chiedi.


31

Python, 36 34 32 byte

lambda n:len(str(66*n**6))//1.24

Versione precedente:

f=lambda n:len(str(66*n**6))//1.24
f=lambda n:(n*n*7).bit_length()//1.4

Spiegazione

L'idea principale è di invertire la formula

fibonacci(n) ~ ( (1 + sqrt(5)) / 2)**n / sqrt(5)

che ci dice questo

log fibonacci(n) ~ n log((1 + sqrt(5)) / 2) - log(sqrt(5))

ottenere

f(n) ~ (log(n) + log(sqrt(5))) / log((1 + sqrt(5))/2)

Le ottimizzazioni del golf sono:

  • Utilizzare len(str(n))per calcolare la base di registro 10 senza importare log(versione precedente utilizzata .bit_length()per calcolare la base di registro 2)
  • Aumenta nfino a una potenza, in modo che l'approssimazione del logaritmo possa distinguere tra i successivi numeri di Fibonacci
  • Moltiplicando per una costante si aumentano i valori per portarli nell'intervallo corretto

Quindi il divisore è stato troncato con la minor precisione possibile e il moltiplicatore ha scelto di dare i risultati corretti per tutti i numeri di fibonacci a 32 bit.


dovrebbe essere di 32 byte, perché f=non viene conteggiato.
Leaky Nun,

2
Come già detto nel commento sopra, le funzioni anonime / lambda senza nome sono consentite per impostazione predefinita . Inoltre, se limiti la tua risposta a Python 2 e richiedi un lungo argomento, lambda n:~-len(`66*n**6`)//1.24dovrebbe funzionare.
Dennis,

19

05AB1E , 3 byte

Codice:

ÅFg

Spiegazione:

ÅF   # Generate all Fibonacci numbers <= input.
  g  # Get the length of this list.

Utilizza la codifica CP-1252 . Provalo online! .


10

Gelatina, 14 11 byte

5½×lØp+.Ḟ»0

Provalo online!

Questa è la mia prima risposta in assoluto Jelly! Questo utilizza l'algoritmo dalla risposta MATL . Grazie a Dennis per la rasatura di 3 byte!

Spiegazione:

   lØp      # Log Base phi
5½          # Of the square root of 5
  ×         # Times the input
      +     # Plus
       .    # 0.5
        Ḟ   # Floored

Questa ottiene la risposta giusta, ora dobbiamo solo gestire il caso speciale di "0". Con '0' come arg, otteniamo -infinity, quindi torniamo

»      # The maximum of 
 0     # Zero
       # And the previous calculated value.

7
+1 perché i commenti sulla spiegazione sono la fine di un limerick.
Daniel,

10

Julia, 27 26 18 byte

!n=log(3n+.7)÷.48

Questo utilizza l'inverso della formula di Binet , con la precisione sufficiente per numeri interi a 32 bit; funziona fino a F (153) = 42.230.279.526.998.466.217.810.220.532.898> 2 105 .

Provalo online!

Come funziona

La formula di Binet afferma quanto segue.

Formula di Binet

Limitare F alla serie di Fibonacci, la mappa n → F n ha un diritto inversa F → n F .

Abbiamo quello

inverso destro della formula di Binet

e tutto ciò che resta da fare è occuparsi del caso limite 0 .

Poiché l'input è limitato a numeri interi a 32 bit, possiamo usare letterali decimali brevi anziché le costanti nella formula.

  • log φ = 0.481211825059603447… ≈ 0.48

    Sfortunatamente, 0,5 non è abbastanza preciso.

  • √5 = 2.2360679774997896964… ≈ 3

    A prima vista potrebbe sembrare una terribile approssimazione, ma stiamo prendendo logaritmi e dato che log 3 - log √5 = 0,29389333245105 ... , il risultato prima dell'arrotondamento sarà spento da un piccolo fattore costante.

  • 0,5 ≈ 0,7

    A causa dell'eccesso dell'approssimazione precedente, potremmo effettivamente omettere del tutto questo termine e ottenere comunque risultati corretti per F> 0 . Tuttavia, se F = 0 , il logaritmo non sarà definito. 0.7 si è rivelato essere il valore più breve che estende la nostra formula a F = 0 .


8

JavaScript, 54 50 69 50 42 byte

b=>(j=>{for(i=c=0;b-i;c++)i=j+(j=i)})(1)|c

Sicuramente non vincerà, solo per divertimento :)

Ok, il controllo di zero consuma 19 byte. WTF? Che stupido.


Demo! Per vedere l'ultimo caso di test, è necessario scorrere un po 'la console.

a=b=>(j=>{for(i=c=0;b-i;c++)i=j+(j=i)})(1)|c;
console.log('0: '+a(0));
console.log('2: '+a(2));
console.log('3: '+a(3));
console.log('5: '+a(5));
console.log('8: '+a(8));
console.log('13: '+a(13));
console.log('1836311903: '+a(1836311903));

Grazie @edc per l'accorciamento di 8 byte.


semplice b=>{for(j=1,i=c=0;b-i;c++)i=j+(j=i);return c}45, golfed b=>(j=>{for(i=c=0;b-i;c++)i=j+(j=i)})(1)|c42.
edc65,

1
@edc Wow, è intelligente, grazie <3
nicael

8

Perl 6  33 30  27 byte

{first *==$_,:k,(0,1,*+*...*>$_)}
{first *==$_,:k,(0,1,*+*...*)}
{first $_,:k,(0,1,*+*...*)}

Provalo

Spiegazione:

# lambda with implicit 「$_」 parameter
{
  first           # find the first element
    $_,           # where something is equal to the block's argument
    :k,           # return the key rather than the value

    # of the Fibonacci sequence
    ( 0, 1, * + * ... * )
    # ^--^ first two values
    #       ^---^ lambda used to generate the next in the series
    #             ^-^ generate until
    #                 ^ Whatever
}

Test:

#! /usr/bin/env perl6
use v6.c;
use Test;

# using the safer version that stops generating
# values bigger than the input
my &fib-index = {first $_,:k,(0,1,*+*...*>$_)}

my @tests = (
  0 => 0,
  2 => 3,
  3 => 4,
  5 => 5,
  8 => 6,
  13 => 7,
  1836311903 => 46,
  1836311904 => Nil, # this is why the safe version is used here
  12200160415121876738 => 93,
  19740274219868223167 => 94,
  354224848179261915075 => 100,
);

plan +@tests + 1;

for @tests -> $_ ( :key($input), :value($expected) ) {
  cmp-ok fib-index($input), &[eqv], $expected, .gist
}

cmp-ok fib-index((0,1,*+*...*)[1000]), &[eqv], 1000, 'works up to 1000th element of Fibonacci sequence'
1..13
ok 1 - 0 => 0
ok 2 - 2 => 3
ok 3 - 3 => 4
ok 4 - 5 => 5
ok 5 - 8 => 6
ok 6 - 13 => 7
ok 7 - 1836311903 => 46
ok 8 - 1836311904 => Nil
ok 9 - 12200160415121876738 => 93
ok 10 - 19740274219868223167 => 94
ok 11 - 354224848179261915075 => 100
ok 12 - works up to 1000th element of Fibonacci sequence

1
Puoi sostituirlo first *==$_con just first $_, perché un numero è uno smart matcher valido.
smls

24 byte utilizzando l' ...operatore anzichéfirst
Jo King il

7

Gelatina , 8 byte

1+С0
¢i

Provalo online! Si noti che questo approccio è troppo inefficiente per l'ultimo caso di test.

Come funziona

¢i     Main link. Argument: n

¢      Call the helper link niladically (i.e., without arguments).
       This yields the sequence of the first n positive Fibonacci numbers, i.e.,
       [1, 1, 2, 3, 5, ...].
 i     Find the first index of n (1-based, 0 if not found).


1+С0  Helper link. No arguments.

1      Set the left argument to 1.
    0  Yield 0.
 +С   Add both arguments, replacing the left argument with the sum and the right
       argument with the previous value of the left argument.
       Yield the array of all intermediate values of the left argument.


5

Python, 29 byte

g=lambda n:n>.7and-~g(n/1.61)

Divide ricorsivamente l'input per l'approssimazione del rapporto aureo 1,61 fino a quando non è inferiore a 0,7 e genera il numero di divisioni.

Per 0, il codice genera False, che equivale a 0 in Python . Questo può essere evitato per 2 byte

g=lambda n:n//.7and 1+g(n/1.61)

4

JavaScript (ES6), 39 33 byte

f=(n,j=0,k=1)=>n>j?f(n,k,j+k)+1:0

Anche con ES7, la formula inversa di Binet richiede 47 byte:

x=>Math.log(x*5**.5)/Math.log(.5+1.25**.5)+.5|0
x=>Math.log(x*5**.5)/Math.log((1+5**.5)/2)+.5|0
x=>Math.log(x*(p=5**.5))/Math.log((1+p)/2)+.5|0

Distribuisci loge precompila tutte le costanti ...
Charlie

IMHO, se si chiama ricorsivamente il lambda per nome f(n,k,j+k), è necessario includere il compito f=e contarlo come +2 byte . La regola per lambda senza nome non dovrebbe applicarsi qui.
Charlie

@charlie Scusa, me ne sono sempre dimenticato. Fisso.
Neil,

4

Salvia, 49 byte

lambda x,s=sqrt(5):x and int(log(x*s,(1+s)/2)+.5)

Grazie a TuukkaX per il suggerimento sul salvataggio sqrt(5) come sa radersi pochi byte.

Provalo online .

Questo approccio che utilizza un inverso della formula di Binet offre diversi miglioramenti rispetto all'approccio precedente: è più veloce (tempo costante contro tempo quadratico), in realtà funziona per input più grandi ed è più breve!

Gli utenti di Python potrebbero chiedersi perché sto usando al sqrt(5)posto del più corto 5**.5- è perché 5**.5è calcolato con la powfunzione di C e perde precisione a causa di problemi in virgola mobile. Molte funzioni matematiche (incluso sqrte log) sono sovraccaricate in Sage per restituire un valore simbolico esatto, che non perde precisione.


Non conosco affatto Sage ma potresti salvare i byte tenendo premuto sqrt(5)in una variabile e usarlo due volte, invece di digitare sqrt(5)due volte?
Yytsi,

4

MATL , 14 byte

t?5X^*17L&YlYo

Provalo online!

Questo utilizza un inverso della formula di Binet , quindi è molto veloce.

Lascia che F indichi l' n -esimo numero di Fibonacci e φ il rapporto aureo . Poi

inserisci qui la descrizione dell'immagine

Il codice utilizza questa formula con due modifiche:

  • Invece di aggiungere 1/2 e quindi arrotondare per difetto, il codice arrotonda semplicemente verso il numero intero più vicino, che occupa meno byte.
  • L'ingresso F = 0 deve essere trattato come un caso speciale.

Come è fatto

t         % Take input F implicitly. Make a copy
?         % If (copy of) F is positive
  5X^     %   Push sqrt(5)
  *       %   Multiply by F
  17L     %   Push phi (predefined literal)
  &Yl     %   Two-input logarithm: first input is argument, second is base
  Yo      %   Round towards nearest integer
          % Else the input, which is 0, is left on the stack
          % End if implicitly
          % Display implicitly

1
Approccio alternativo:O1G:"yy+]vGmfq
DJMcMayhem


@ jimmy23013 Bel approccio! Dovresti sicuramente pubblicarlo come risposta separata
Luis Mendo,

Non penso che valga la pena un'altra risposta, in quanto è solo un modo per rimuovere il 5X^*. (L' ho già fatto in precedenza .) E non conosco abbastanza MATL per continuare a migliorarlo.
jimmy23013,


3

JavaScript, 22 byte

n=>Math.log(n)/.48+2|0

Non pensavo che avrebbe funzionato quando l'ho visto, ma a quanto pare -Infinity|0è 0in JavaScript. Vai a capire.
Dennis,

@Dennis: in JS, gli operatori bit a bit prendono solo gli ultimi 32 bit e -Infinity = FFF00000 00000000. Mi ha fatto piacere scoprirlo, risparmia 3 byte per non dover anteporre un test zero esplicito come n&&. A parte questo, lo scopo principale di |0è un sostituto Math.trunc()(come ÷in Julia).
Charlie

3

C, 62 58 byte

g(c,a,b){return c-a?g(c,b,a+b)+1:0;}f(c){return g(c,0,1);}

dettagliata

int g(int c, int a, int b)
{
    if (c == a)
    {
        return 0;
    }
    else
    {
        return g(c, b, a+b) + 1;
    }
}

int f(c)
{
    return g(c, 0, 1);
}

3

Java 7, 70 byte

int c(int n){int a=0,b=1,c=0,t;while(a<n){c++;t=b;b+=a;a=t;}return c;}

https://ideone.com/I4rUC5


2
Benvenuto in PPCG, bella prima risposta!
Leaky Nun,

int c(int n){int a=0,b=1,c=0,t;for(;a<n;t=b,b+=a,a=t)c++;return c;}(non testato)
Leaky Nun

int c(int n){int a=0,b=1,c=0;while(a<n){c++;b+=a;a=b-a;}return c;}(non testato)
Leaky Nun

2
int c(int n){int a=0,b=1,c=0;for(;a<n;b+=a,a=b-a)c++;return c;}(non testato)
Leaky Nun

2

TSQL, 143 byte

L'ingresso entra @ncome inDECLARE @n INT = 1836311903;

DECLARE @O BIGINT=0;WITH F(R,P,N)AS(SELECT @O,@O,@O+1 UNION ALL SELECT R+1,N,P+N FROM F WHERE N<=@n)SELECT MAX(R)FROM F OPTION(MAXRECURSION 0);

2

Haskell, 45 byte

f x=round$log(sqrt 5*x+0.9)/log((sqrt 5+1)/2)

2

sesos , 28 byte

hexdump:

0000000: 16f8be 766ef7 ae6d80 f90bde b563f0 7ded18 3ceffa  ...vn..m.....c.}..<..
0000015: b1c1bb af9f3f ff                                  .....?.

Provalo online!

(Tempo esponenziale perché in Sesos la copia di un numero richiede tempo esponenziale.)

Assembly utilizzato per generare il file binario:

set numin
set numout
get
jmp
sub 1
fwd 1
add 1
fwd 1
add 1
rwd 2
jnz    ;input input
fwd 4
add 1  ;input input 0 1
fwd 2
add 1  ;input input 0 1 0 1
rwd 4
jmp
jmp    ;input input-curr curr next iterations
sub 1
jnz    ;input 0 curr next iterations
fwd 3
add 1
jmp
sub 1
fwd 2
add 1
rwd 2
jnz    ;input 0 curr next 0 0 iterations+1
rwd 1
jmp
sub 1
fwd 1
add 1
fwd 1
add 1
rwd 2
jnz    ;input 0 curr 0 next next iterations+1
rwd 1
jmp
sub 1
fwd 1
sub 1
fwd 2
add 1
rwd 3
jnz    ;input 0 0 -curr next curr+next iterations+1
rwd 2
jmp
sub 1
fwd 2
add 1
fwd 1
add 1
rwd 3
jnz    ;0 0 input input-curr next curr+next iterations+1
fwd 3
jnz
fwd 3
put

2

Java 8 61 byte

Come la risposta @dainichi resa più breve solo usando lambda Java 8. La risposta è un'espressione di valore valida.

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

Ungolfed:

interface F
{
    int c(int n);
}

public class Main
{

    public static void main(String[] args)
    {
        F f = n->{int a=0,b=1,c=0,t;while(a<n){c++;t=b;b+=a;a=t;}return c;};
    }
}

1

Pyth, 13 byte

J1tf>=Z+~JZZQ

Suite di test.

Approssimazione in Python 2:

Z=0;J=1;T=1;Q=input()
while not J+Z>Q:
    temp=J
    J=Z
    Z=temp+J
    T += 1
print(T-1)

approccio alternativo, 18 byte

L?<b2bsyMtBtbs.IyG

Suite di test.

Questo utilizza .Iper inverso.


1

Java 7, 89 byte

int c(int n){int i=-1;while(f(++i)<n);return i;}int f(int n){return n<2?n:f(n-1)+f(n-2);}

Ispirato dalla spiegazione di @Adnan risposta 05AB1E s' .

Casi non testati e test:

Provalo qui. (Il limite di tempo è stato superato per l'ultimo caso di test, ma funziona in circa 30-45 secondi sul mio PC.)

class Main{
  static int c(int n){
    int i = -1;
    while(f(++i) < n);
    return i;
  }

  static int f(int n){
    return n < 2
             ? n
             : f(n - 1) + f(n - 2);
  }

  public static void main(String[] a){
    System.out.println(c(0));
    System.out.println(c(2));
    System.out.println(c(3));
    System.out.println(c(5));
    System.out.println(c(8));
    System.out.println(c(1836311903));
  }
}

Produzione:

0
3
4
5
6
46

1

Perl 5,10, 48 byte

Fondamentalmente cercando il giusto in nmodo che F(n) = input.

-a switch aggiunge un byte.

$b++;while($_>$a){$c=$a;$a+=$b;$b=$c;$n++}say$n

Provalo qui!


1

J, 32 27 17 byte

i.~0,+/@(!|.)\@i.

Calcola i primi n numeri di Fibonacci e quindi trova l'indice di n in quell'elenco.

uso

I comandi extra vengono utilizzati per la formattazione di più input / output. L'ultimo caso di test viene omesso poiché richiederà molto più tempo per il calcolo.

   f =: i.~0,+/@(!|.)\@i.
   (,.f"0) 0 1 2 3 5 8 13
 0 0
 1 1
 2 3
 3 4
 5 5
 8 6
13 7

Spiegazione

i.~0,+/@(!|.)\@i.  Input: n
               i.  Get the range [0, 1, ..., n-1]
             \@    For each prefix of that range
          |.         Reverse the prefix
         !           Find the binomial coefficient between each value in the original
                     prefix and the reversed prefix
     +/@             Sum those binomial coefficients
                   This will create the Fibonacci numbers from 1 to n
   0,              Prepend a 0 to the list of Fibonacci numbers
i.~                Find the index of n in that list and return

1

Mathematica, 30 byte

Round@Log[5^.5/2+.5,.8+5^.5#]&

Funzione pura; restituisce 2 se l'ingresso è 1.

Non batte l'altra voce di Mathematica, ma mostra un metodo insolito: è un fatto (molto interessante) che l'ennesimo numero di Fibonacci sia il numero intero più vicino a [1 / sqrt (5) volte l'ennesimo potere del rapporto aureo] (" Formula di Binet ").

Pertanto la funzione inversa sarà il logaritmo base [rapporto aureo] di [sqrt (5) volte il numero di Fibonacci in questione]. Il .8+è un hack per assicurarsi che non ci prendiamo il logaritmo di 0, senza rovinare gli altri valori.


1

Japt , 10 byte

Lo æ@U¥MgX

Provalo online!

Spiegazione

Lo æ@U¥MgX
Lo           // Creates a range from 0 to 99
   æ@        // Iterates through the range. Returns the first item X where:
     U¥      //   Input ==
       MgX   //   Xth Fibonacci number

1

Brachylog , 14 byte

≜∧0;1⟨t≡+⟩ⁱ↖?h

Provalo online!

Riceve input tramite la variabile di output e output tramite la variabile di input.

≜                 Label the input variable, trying 0, 1, -1, 2...,
  0               then starting with 0
 ∧                (which is not necessarily the input variable)
   ;1             paired with 1,
     ⟨t≡ ⟩        replace the first element of the pair with the last element
     ⟨ ≡+⟩        and the last element of the pair with the sum of the elements
          ⁱ↖?     a number of times equal to the input variable,
             h    such that the first element of the pair is the output variable.

Non sono del tutto sicuro del perché sia necessario.


0

Javascript (utilizzando una libreria esterna) (84 byte)

n=>_.Until((i,a)=>{l=a.length;if(a[l-1]!=n){return i<=1?i:a[l-1]+a[l-2]}}).Count()-1

Link a lib: https://github.com/mvegh1/Enumerable

Spiegazione del codice: la libreria ha un metodo statico che crea una sequenza fino a quando il predicato ha un valore di ritorno non definito. Il predicato ha una firma di ("i" ndex, corrente interna "a" rray generato). Ad ogni iterazione, controlliamo se l'ultimo elemento dell'array interno è uguale all'input, n. In caso contrario, restituisce il valore successivo nella sequenza fib. Altrimenti, il predicato ha un risultato indefinito che termina la generazione della sequenza. Quindi, restituiamo la lunghezza della sequenza (e sottraggiamo 1 al fine di rispettare la base 0 come visto nel PO

inserisci qui la descrizione dell'immagine


53 byte utilizzando il codice da qui n=>{a=c=t=0,b=1;while(a<n){c++;t=b;b+=a;a=t}return c} Provalo online!
pixma140,
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.