Fibonacci invertido!


42

Introducción

Todos conocemos y amamos nuestra secuencia de Fibonacci y ya hemos visto innumerables desafíos aquí. Sin embargo, todavía nos falta un caso muy simple que esta respuesta proporcionará: ¡Fibonacci invertida! Así que dado F_ntu trabajo es encontrar n.

Especificación

Entrada

Su entrada será un número entero no negativo, que se garantiza que formará parte de la secuencia de Fibonacci.

Salida

La salida también debe ser un número entero no negativo.

¿Qué hacer?

La introducción ya decía: dado un número de Fibonacci, genera su índice. El número de Fiboancci se define como F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)y se le da F(n)y debe devolver n.

Casos de esquina potenciales

0 es una entrada y salida válida.
Si se le da "1" como entrada, puede enviar "1" o "2", como prefiera.
Siempre puede suponer que su entrada en realidad es un número de Fibonacci.
Puede suponer que la entrada es representable como un entero con signo de 32 bits.

¿Quién gana?

Este es el código de golf, por lo que gana la respuesta más corta en bytes.
Se aplican reglas estándar, por supuesto.

Casos de prueba

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

39
Ligero error: ¿no debería considerarse esto fibonacci inverso en.m.wikipedia.org/wiki/Inverse_function?
Michael

19
Entonces, iccanobiF ?!

66
@ Michael esto no es inversa de Fibonacci, porque no hay inversa a la función de Fibonacci porque es no inyectiva (debido a que el "1" aparece dos veces). El reverso originalmente surgió de la idea de "búsquedas en la tabla inversa", que es lo que esperaba que la gente hiciera aquí (por ejemplo, esperaba que lo hicieran para resolver el problema).
SEJPM

99
La función aquí podría considerarse un inverso derecho de la "función de Fibonacci" desde los enteros no negativos hasta el conjunto de números de Fibonacci. La existencia de un inverso derecho no implica inyectividad.
Dennis

1
@SEJPM: Sin embargo, esperaba una tarea como "escribir un programa que explica la secuencia de Fibonacci al revés".
Bergi

Respuestas:


58

En realidad, 1 byte

f

Sí, hay algo incorporado para esto, desde el 16 de noviembre de 2015 .

Pruébalo en línea


Por diversión, sin el incorporado, son 9 bytes:

╗1`F╜=`╓i

Pruébalo en línea!

Explicación:

╗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
Tengo un pensamiento y un pensamiento solo cuando veo esto: ಠ_ಠ
Addison Crump

37
Realmente no entiendo por qué "desperdiciarías" un símbolo para un propósito tan ridículamente específico
Fatalize

19
@Fatalize Las funciones de Fibonacci y Fibonacci inversa fueron de las primeras que agregué. Incluso ahora, hay 39 comandos de un solo byte completamente no utilizados (y quién sabe cuántas sobrecargas podrían utilizarse). Los 256 símbolos, combinados con el hecho de que hay 5 tipos en Actually (Integer, Real, String, Iterable, Function), significa que hay hasta 1280 posibles funciones unarias y 6400 posibles funciones binarias. Hay mucho espacio para comandos aparentemente inútiles.
Mego

23
@Mego ¿Estás tratando de competir con Mathematica por la mayoría de los integrantes?
gcampbell

13
En realidad, es solo un byte ... jajaja, me encanta este nombre de idioma.
nicael

42

Mathematica, 25 bytes

InverseFunction@Fibonacci

Función. Bastante claro si me preguntas.


31

Python, 36 34 32 bytes

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

Versión anterior:

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

Explicación

La idea central es invertir la fórmula

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

que nos dice que

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

Llegar

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

Las optimizaciones de golf son:

  • Se usa len(str(n))para calcular la base de registro 10 sin importar log(la versión anterior se usaba .bit_length()para calcular la base de registro 2)
  • Elevar na una potencia, para que la aproximación del logaritmo pueda distinguir entre números sucesivos de Fibonacci
  • Multiplicar por una constante escala los valores para colocarlos en el rango correcto

Luego, el divisor se truncó con la menor precisión posible y el multiplicador elegido para dar los resultados correctos para todos los números de Fibonacci de 32 bits.


debe ser de 32 bytes, porque f=no se cuenta.
Leaky Nun

2
Como ya se dijo en el comentario anterior, las funciones anónimas / lambdas sin nombre están permitidas por defecto . Además, si restringe su respuesta a Python 2 y requiere un argumento largo , lambda n:~-len(`66*n**6`)//1.24debería funcionar.
Dennis

19

05AB1E , 3 bytes

Código:

ÅFg

Explicación:

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

Utiliza la codificación CP-1252 . Pruébalo en línea! .


10

Jalea, 14 11 bytes

5½×lØp+.Ḟ»0

Pruébalo en línea!

Esta es mi primera respuesta Jelly! Esto usa el algoritmo de la respuesta MATL . ¡Gracias a Dennis por reducir 3 bytes!

Explicación:

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

Esta es la respuesta correcta, ahora solo tenemos que manejar el caso especial de '0'. Con '0' como argumento, obtenemos -infinity, así que volvemos

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

77
+1 porque los comentarios sobre la explicación son el final de un limerick.
Daniel

10

Julia, 27 26 18 bytes

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

Utiliza el inverso de la fórmula de Binet , con la precisión suficiente para enteros de 32 bits; en realidad funciona hasta F (153) = 42,230,279,526,998,466,217,810,220,532,898> 2 105 .

Pruébalo en línea!

Cómo funciona

La fórmula de Binet establece lo siguiente.

Fórmula de Binet

La restricción de F a la serie de Fibonacci, el mapa N → M n tiene un derecho inversa M → N F .

Tenemos eso

derecho inverso de la fórmula de Binet

y todo lo que queda por hacer es lidiar con el caso límite 0 .

Como la entrada está restringida a enteros de 32 bits, podemos usar literales decimales cortos en lugar de las constantes en la fórmula.

  • log φ = 0.481211825059603447… ≈ 0.48

    Desafortunadamente, 0.5 no es lo suficientemente preciso.

  • √5 = 2.2360679774997896964… ≈ 3

    Eso puede parecer una aproximación horrible a primera vista, pero estamos tomando logaritmos y desde log 3 - log √5 = 0.29389333245105 ... , el resultado antes del redondeo será un factor constante pequeño.

  • 0.5 ≈ 0.7

    Debido al exceso de la aproximación anterior, podríamos omitir este término por completo y aún así obtener resultados correctos para F> 0 . Sin embargo, si F = 0 , el logaritmo será indefinido. 0.7 resultó ser el valor más corto que extiende nuestra fórmula a 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

Seguramente no va a ganar, solo por diversión :)

Ok, la comprobación de cero consume 19 bytes. WTF? Estúpido yo.


¡Manifestación! Para ver el último caso de prueba, debe desplazarse un poco por la consola.

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

Gracias @edc por acortar en 8 bytes.


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

1
@edc Wow, eso es inteligente, gracias <3
nicael

8

Perl 6  33 30  27 bytes

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

Intentalo

Explicación:

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

Prueba:

#! /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
Puede reemplazar first *==$_con just first $_, porque un número es un emparejador inteligente válido.
sonríe

24 bytes utilizando el ...operador en lugar defirst
Jo King

7

Jalea , 8 bytes

1+С0
¢i

Pruébalo en línea! Tenga en cuenta que este enfoque es demasiado ineficiente para el último caso de prueba.

Cómo 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 la entrada por la aproximación de la proporción áurea 1.61 hasta que esté por debajo de 0.7, y genera el número de divisiones.

Para 0, sale el código False, que es igual a 0 en Python . Esto se puede evitar para 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

Incluso con ES7, la fórmula inversa de Binet toma 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

Simplemente distribuya logy precalcule todas las constantes ...
charlie

En mi humilde opinión, si llama recursivamente a la lambda por su nombre, f(n,k,j+k)debe incluir la asignación f=y contarla como +2 bytes . La regla para lambdas sin nombre no debería aplicarse aquí.
charlie

@charlie Lo siento, siempre me olvidé de eso. Fijo.
Neil

4

Sabio, 49 bytes

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

Gracias a TuukkaX por la sugerencia acerca de cómo guardar sqrt(5)como spara cortar unos pocos bytes.

Pruébalo en línea .

Este enfoque que usa un inverso de la fórmula de Binet ofrece varias mejoras con respecto al enfoque anterior: es más rápido (tiempo constante versus tiempo cuadrático), en realidad funciona para entradas más grandes, ¡y es más corto!

Los usuarios de Python pueden preguntarse por qué estoy usando en sqrt(5)lugar del más corto 5**.5: es porque 5**.5se calcula con la powfunción de C y pierde precisión debido a problemas de coma flotante. Muchas funciones matemáticas (incluyendo sqrty log) se sobrecargan en Sage para devolver un valor simbólico exacto, que no pierde precisión.


No conozco a Sage en absoluto, pero ¿podría guardar bytes manteniendo sqrt(5)una variable y usarla dos veces, en lugar de escribir sqrt(5)dos veces?
Yytsi

4

MATL , 14 bytes

t?5X^*17L&YlYo

Pruébalo en línea!

Esto usa un inverso de la fórmula de Binet , por lo que es muy rápido.

Sea F denota el n -ésimo número de Fibonacci, y phi de la proporción áurea . Luego

ingrese la descripción de la imagen aquí

El código usa esta fórmula con dos modificaciones:

  • En lugar de agregar 1/2 y luego redondear hacia abajo, el código simplemente se redondea hacia el entero más cercano, que ocupa menos bytes.
  • La entrada F = 0 debe tratarse como un caso especial.

Cómo está hecho

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

1
11 bytes:t?17L&YlXkQ
jimmy23013

@ jimmy23013 ¡Buen enfoque! Definitivamente deberías publicar eso como una respuesta separada
Luis Mendo

No creo que valga la pena otra respuesta, ya que es solo una forma de eliminar el 5X^*. ( He hecho esto antes ). Y no sé MATL lo suficiente como para seguir mejorando.
jimmy23013


3

JavaScript, 22 bytes

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

No pensé que esto funcionaría cuando lo vi, pero aparentemente -Infinity|0está 0en JavaScript. Imagínate.
Dennis

@Dennis: en JS, los operadores bit a bit solo toman los últimos 32 bits y -Infinity = FFF00000 00000000. Me alegró descubrirlo, ahorra 3 bytes por no tener que anteponer una prueba explícita de cero como n&&. Aparte de eso, el propósito principal de |0es un sustituto de Math.trunc()(como ÷en 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);}

Detallado

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
Bienvenido a PPCG, buena primera respuesta!
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;}(no probado)
Leaky Nun

int c(int n){int a=0,b=1,c=0;while(a<n){c++;b+=a;a=b-a;}return c;}(no probado)
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;}(no probado)
Leaky Nun

2

TSQL, 143 bytes

La entrada entra @ncomo enDECLARE @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                                  .....?.

Pruébalo en línea!

(Tiempo exponencial porque en Sesos copiar un número necesita tiempo exponencial).

Ensamblaje utilizado para generar el archivo 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 bytes

Igual que la respuesta de @dainichi solo se acortó usando Java 8 lambdas. La respuesta es una expresión de valor válida.

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

Sin golf:

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

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 por la explicación de @Adnan respuesta 05AB1E 's .

Sin golf y casos de prueba:

Pruébalo aquí (Límite de tiempo excedido para el último caso de prueba, pero funciona en aproximadamente 30-45 segundos en mi 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));
  }
}

Salida:

0
3
4
5
6
46

1

Perl 5.10, 48 bytes

Básicamente buscando el derecho npara que F(n) = input.

-a el interruptor agrega un byte.

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

Pruébalo aquí!


1

J, 32 27 17 bytes

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

Calcula los primeros n números de Fibonacci y luego encuentra el índice de n en esa lista.

Uso

Se utilizan comandos adicionales para formatear múltiples entradas / salidas. Se omite el último caso de prueba, ya que requerirá mucho más tiempo 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

Explicación

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#]&

Función pura; devuelve 2 si la entrada es 1.

No supera la otra entrada de Mathematica, pero muestra un método inusual: es un hecho (muy bueno) que el enésimo número de Fibonacci es el entero más cercano a [1 / sqrt (5) veces la enésima potencia de la proporción áurea] (" Fórmula de Binet ").

Por lo tanto, la función inversa será el logaritmo base- [proporción áurea] de [sqrt (5) veces el número de Fibonacci en cuestión]. El .8+es un truco para asegurarse de que no tomamos el logaritmo de 0, sin atornillar los otros valores.


1

Japt , 10 bytes

Lo æ@U¥MgX

Pruébalo en línea!

Explicación

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 bytes

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

Pruébalo en línea!

Toma la entrada a través de la variable de salida y las salidas a través de la variable 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.

No estoy completamente seguro de por qué es necesario.


0

Javascript (usando una 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

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

Explicación del código: la biblioteca tiene un método estático que crea una secuencia hasta que el predicado tenga un valor de retorno indefinido. El predicado tiene una firma de ("i" ndex, actual "a" matriz interna generada). En cada iteración, verificamos si el último elemento de la matriz interna es igual a la entrada, n. Si no, devuelve el siguiente valor en la secuencia fib. De lo contrario, el predicado tiene un resultado indefinido que termina la generación de la secuencia. Luego, devolvemos la longitud de la secuencia (y restamos 1 para cumplir con la base 0 como se ve en el OP

ingrese la descripción de la imagen aquí


53 bytes usando el código de aquí ¡ n=>{a=c=t=0,b=1;while(a<n){c++;t=b;b+=a;a=t}return c} Pruébelo en línea!
pixma140
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.