Fibonacci invertido!


42

Introdução

Todos nós conhecemos e amamos nossa sequência de Fibonacci e já vimos uma infinidade de desafios aqui. No entanto, ainda não temos um caso muito simples que esta resposta forneça: Fibonacci invertido! Então, dado o F_nseu trabalho é encontrar n.

Especificação

Entrada

Sua entrada será um número inteiro não negativo, que é garantido como parte da sequência de fibonacci.

Saída

A saída também deve ser um número inteiro não negativo.

O que fazer?

A introdução já dizia: Dado um número de fibonacci, produza seu índice. O número de Fiboancci é definido como F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)e você recebe F(n)e deve retornar n.

Casos de canto em potencial

0 é uma entrada e saída válida.
Se for fornecido "1" como entrada, você poderá enviar "1" ou "2", como preferir.
Você sempre pode assumir que sua entrada é realmente um número de fibonacci.
Você pode assumir que a entrada é representável como um número inteiro assinado de 32 bits.

Quem ganha?

Isso é código-golfe, então a resposta mais curta em bytes vence!
Regras padrão se aplicam, é claro.

Casos de teste

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

39
Ligeira nit-escolher: não deve este ser considerado inversa fibonacci en.m.wikipedia.org/wiki/Inverse_function
Michael

19
Então, iccanobiF ?!

6
@ Michael isto não é inversa Fibonacci, porque não há nenhuma inversa à função de Fibonacci porque é não injective (porque o "1" aparece duas vezes). O inverso originou-se originalmente da idéia de "pesquisas reversas na tabela", que é o que eu esperava que as pessoas fizessem aqui (por exemplo, eu esperava que elas fizessem isso para resolver o problema).
SEJPM 18/07/19

9
A função aqui pode ser considerada um inverso à direita da "função Fibonacci" dos números inteiros não negativos ao conjunto de números de Fibonacci. A existência de um inverso correto não implica injetividade.
Dennis

1
@SEJPM: Eu meio que esperava uma tarefa como "escrever um programa que explique a sequência de fibonacci ao contrário".
Bergi

Respostas:


58

Na verdade, 1 byte

f

Sim, existe um construído para isso, desde 16 de novembro de 2015 .

Experimente online


Por diversão, sem o builtin, são 9 bytes:

╗1`F╜=`╓i

Experimente online!

Explicação:

╗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
Eu tenho um pensamento e um só pensava quando eu ver isto: ಠ_ಠ
Addison Crump

37
Eu realmente não entendo por que você iria "perder" um símbolo para tal um propósito específico ridiculamente
Fatalize

19
@Fatalize As funções de Fibonacci e inversa de Fibonacci estavam entre as primeiras que adicionei. Mesmo agora, existem 39 comandos de byte único não utilizados (e quem sabe quantas sobrecargas que poderiam ser utilizadas). Os 256 símbolos, combinados com o fato de que existem 5 tipos em Actually (Inteiro, Real, String, Iterável, Função), significa que existem até 1280 possíveis funções unárias e 6400 possíveis funções binárias. Há muito espaço para comandos aparentemente inúteis.
Mego

23
@Mego Você está apenas tentando competir com o Mathematica pelos mais embutidos?
Gcampbell

13
Na verdade, é apenas um byte ... lol, adoro esse nome de idioma.
Nicael 18/07

42

Mathematica, 25 bytes

InverseFunction@Fibonacci

Função. Bastante auto-explicativo, se você me perguntar.


31

Python, 36 34 32 bytes

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

Versões prévias:

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

Explicação

A idéia central é inverter a fórmula

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

o que nos diz que

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

para obter

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

As otimizações de golfe são:

  • Use len(str(n))para calcular a base de log 10 sem importar log(versão antiga usada .bit_length()para calcular a base de log 2)
  • Levantar n a um poder, para que a aproximação do logaritmo possa distinguir entre números sucessivos de Fibonacci
  • A multiplicação por uma constante aumenta os valores para colocá-los no intervalo correto

Em seguida, o divisor foi truncado com a menor precisão possível e o multiplicador escolhido para fornecer os resultados corretos para todos os números de fibonacci de 32 bits.


deve ter 32 bytes, porque f=não é contado.
Leaky Nun

2
Como o comentário acima já disse, funções anônimas / lambdas sem nome são permitidas por padrão . Além disso, se você restringir sua resposta ao Python 2 e precisar de um longo argumento, lambda n:~-len(`66*n**6`)//1.24deve funcionar.
Dennis

19

05AB1E , 3 bytes

Código:

ÅFg

Explicação:

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

Usa a codificação CP-1252 . Experimente online! .


10

Geléia, 14 11 bytes

5½×lØp+.Ḟ»0

Experimente online!

Esta é a minha primeira resposta Jelly! Isso usa o algoritmo da resposta MATL . Agradecimentos a Dennis por eliminar 3 bytes!

Explicação:

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

Esta é a resposta certa, agora só precisamos lidar com o caso especial de '0'. Com '0' como argumento, obtemos -infinity, então retornamos

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

7
+1 porque os comentários na explicação são o fim de uma limerick.
187 Daniel

10

Julia, 27 26 18 bytes

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

Isso usa o inverso da fórmula de Binet , com precisão suficiente para números inteiros de 32 bits; na verdade, funciona até F (153) = 42.230.279.526.998.466.217.810.220.532.898> 2 105 .

Experimente online!

Como funciona

A fórmula de Binet afirma o seguinte.

Fórmula de Binet

Restringindo F ao conjunto de Fibonacci, o mapa n → F n tem um inverso direito F → n F .

Nós temos isso

inverso à direita da fórmula de Binet

e tudo o que resta a fazer é lidar com o caso 0 .

Como a entrada é restrita a números inteiros de 32 bits, podemos usar literais decimais curtos em vez das constantes na fórmula.

  • log φ = 0,481211825059603447… ≈ 0,48

    Infelizmente, 0,5 não é suficientemente preciso.

  • √5 = 2,2360679774997896964… ≈ 3

    Pode parecer uma aproximação terrível à primeira vista, mas estamos usando logaritmos e, como log 3 - log √5 = 0,29389333245105… , o resultado antes do arredondamento será desativado por um pequeno fator constante.

  • 0,5 ± 0,7

    Devido ao excesso da aproximação anterior, poderíamos realmente omitir esse termo completamente e ainda assim obter resultados corretos para F> 0 . No entanto, se F = 0 , o logaritmo será indefinido. 0,7 acabou sendo o menor valor que estende nossa fórmula para F = 0 .


8

JavaScript, 54 50 69 50 42 bytes

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

Certamente não vai ganhar, apenas por diversão :)

Ok, verificar zero consome 19 bytes. WTF? Estúpido-eu.


Demo! Para ver o último caso de teste, você precisa rolar um pouco o 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));

Obrigado @edc pela redução de 8 bytes.


simple 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 17/07/2016

1
@edc Uau, isso é inteligente, obrigado <3
nicael

8

Perl 6  33 30  27 bytes

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

Tente

Explicação:

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

Teste:

#! /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
Você pode substituir first *==$_por just first $_, porque um número é um correspondente inteligente válido.
smls 27/02

24 bytes usando o ...operador em vez defirst
Jo King

7

Geléia , 8 bytes

1+С0
¢i

Experimente online! Observe que essa abordagem é muito ineficiente para o último caso de teste.

Como funciona

¢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 bytes

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

Divide recursivamente a entrada pela proporção áurea 1,61 até ficar abaixo de 0,7 e gera o número de divisões.

Para 0, o código gera False, igual a 0 em Python . Isso pode ser evitado por 2 bytes

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

4

JavaScript (ES6), 39 33 bytes

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

Mesmo com o ES7, a fórmula inversa do Binet leva 47 bytes:

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

Apenas distribuir o loge precompute todas as constantes ...
charlie

IMHO, se você chamar recursivamente o lambda pelo nome, f(n,k,j+k)inclua a atribuição f=e conte-a como +2 bytes . A regra para lambdas sem nome não deve se aplicar aqui.
22416

@ charlie Desculpe, eu sempre esqueci disso. Fixo.
Neil

4

Sábio, 49 bytes

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

Agradecemos a TuukkaX pela sugestão sobre sqrt(5)como economizar salguns bytes.

Experimente online .

Essa abordagem usando uma inversa da fórmula de Binet oferece várias melhorias em relação à abordagem anterior: é mais rápida (tempo constante versus tempo quadrático), na verdade funciona para entradas maiores e é mais curta!

Os usuários de Python podem se perguntar por que estou usando, e sqrt(5)não o menor 5**.5- é porque 5**.5é calculado com a powfunção de C e perde precisão devido a problemas de ponto flutuante. Muitas funções matemáticas (incluindo sqrte log) são sobrecarregadas no Sage para retornar um valor simbólico exato, que não perde precisão.


Eu não conheço o Sage, mas você poderia salvar bytes mantendo o sqrt(5)em uma variável e usá-lo duas vezes, em vez de digitar sqrt(5)duas vezes?
Yytsi 18/07/19

4

MATL , 14 bytes

t?5X^*17L&YlYo

Experimente online!

Isso usa uma inversa da fórmula de Binet e, portanto, é muito rápido.

Seja F denotado o n- ésimo número de Fibonacci e φ a proporção áurea . Então

insira a descrição da imagem aqui

O código usa essa fórmula com duas modificações:

  • Em vez de adicionar 1/2 e arredondar para baixo, o código simplesmente arredonda para o número inteiro mais próximo, que ocupa menos bytes.
  • A entrada F = 0 precisa ser tratada como um caso especial.

Como isso é feito

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
Abordagem alternativa:O1G:"yy+]vGmfq
DJMcMayhem


@ jimmy23013 Boa abordagem! Você deve definiely postá-lo como uma resposta separada
Luis Mendo

Eu não acho que vale a pena outra resposta, pois é apenas uma maneira de remover o 5X^*. ( Eu já fiz isso antes .) E não conheço o MATL o suficiente para continuar melhorando.
jimmy23013


3

JavaScript, 22 bytes

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

Não achei que isso funcionaria quando o vi, mas aparentemente -Infinity|0está 0em JavaScript. Vai saber.
Dennis

@ Dennis: No JS, os operadores bit a bit levam apenas os últimos 32 bits e -Infinity = FFF00000 00000000. Fiquei feliz em descobrir, ele poupa 3 bytes por não ter que preceder um teste de zero explícito como n&&. Além disso, o principal objetivo de |0é um substituto para Math.trunc()(como ÷em Julia).
charlie

3

C, 62 58 bytes

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

Detalhado

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 bytes

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
Bem-vindo ao PPCG, boa primeira resposta!
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;}(não testada)
gotejante Nun

int c(int n){int a=0,b=1,c=0;while(a<n){c++;b+=a;a=b-a;}return c;}(não testada)
gotejante Nun

2
int c(int n){int a=0,b=1,c=0;for(;a<n;b+=a,a=b-a)c++;return c;}(não testada)
gotejante Nun

2

TSQL, 143 bytes

A entrada entra @ncomo emDECLARE @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 bytes

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

2

Sesos , 28 bytes

Hexdump:

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

Experimente online!

(Tempo exponencial porque, no Sesos, a cópia de um número precisa de tempo exponencial.)

Assembly usado para gerar o arquivo binário:

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 bytes

O mesmo que a resposta @dainichi foi reduzida, usando o Java 8 lambdas. A resposta é uma expressão válida de rvalue.

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

Pitão, 13 bytes

J1tf>=Z+~JZZQ

Suíte de teste.

Aproximação em 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)

abordagem alternativa, 18 bytes

L?<b2bsyMtBtbs.IyG

Suíte de teste.

Isso usa .Ipara inverso.


1

Java 7, 89 bytes

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

Inspirado pela explicação da @Adnan resposta 05AB1E 's .

Casos não testados e de teste:

Experimente aqui. (O limite de tempo foi excedido para o último caso de teste, mas funciona em cerca de 30 a 45 segundos no meu 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));
  }
}

Saída:

0
3
4
5
6
46

1

Perl 5.10, 48 bytes

Basicamente, procurando o certo npara isso F(n) = input.

-a switch adiciona um byte.

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

Experimente aqui!


1

J, 32 27 17 bytes

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

Calcula os primeiros n números de Fibonacci e localiza o índice de n nessa lista.

Uso

Comandos extras são usados ​​para formatar várias entradas / saídas. O último caso de teste é omitido, pois exigirá muito mais tempo para calcular.

   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

Explicação

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 bytes

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

Função pura; retorna 2 se a entrada for 1.

Não supera a outra entrada do Mathematica, mas mostra um método incomum: é um fato (muito legal) que o número N-ésimo de Fibonacci seja o número inteiro mais próximo de [1 / sqrt (5) vezes a N-ésima potência da proporção áurea] (" Fórmula de Binet ").

Portanto, a função inversa será o logaritmo base- [proporção áurea] de [sqrt (5) vezes o número de Fibonacci em questão]. O .8+é um truque para garantir que não aceitemos o logaritmo de 0, sem estragar os outros valores.


1

Japonês , 10 bytes

Lo æ@U¥MgX

Experimente online!

Explicação

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

Braquilog , 14 bytes

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

Experimente online!

Leva a entrada através da variável de saída e sai através da variável de entrada.

≜                 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.

Não sei ao certo por que é necessário.


0

Javascript (usando biblioteca externa) (84 bytes)

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 para lib: https://github.com/mvegh1/Enumerable

Explicação do código: A biblioteca possui um método estático que cria uma sequência até o predicado ter um valor de retorno indefinido. O predicado possui uma assinatura de ("i" ndex, corrente interna "a" gerada). A cada iteração, verificamos se o último elemento da matriz interna é igual à entrada, n. Caso contrário, retorne o próximo valor na sequência fib. Caso contrário, o predicado terá um resultado indefinido que encerra a geração da sequência. Em seguida, retornamos o comprimento da sequência (e subtraímos 1 para cumprir com a base 0, como visto no OP

insira a descrição da imagem aqui


53 bytes usando o código daqui n=>{a=c=t=0,b=1;while(a<n){c++;t=b;b+=a;a=t}return c} Experimente online!
pixma140 29/08
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.