Indización de los números de Fibonacci extendidos

21

Probablemente hayas oído hablar de los números de Fibonacci. Ya sabes, esa secuencia entera que comienza con 1, 1, y luego cada nuevo número es la suma de los dos últimos.

1 1 2 3 5 8 13...

Y así. Los desafíos sobre los números de Fibonacci son bastante populares aquí . ¿Pero quién dice que los números de Fibonacci tienen que comenzar 1, 1? ¿Por qué no podían empezar 0, 1? Muy bien, redefinímoslos para comenzar en 0:

0 1 1 2 3 5 8 13...

Pero ... ¡tampoco tenemos que parar allí! Si podemos sumar los dos últimos números para obtener el siguiente, también podríamos restar el primer número del segundo número para anteponer un nuevo número. Entonces podría comenzar con 1, 0:

1 0 1 1 2 3 5 8 13...

Incluso podemos terminar con negativos:

-1 1 0 1 1 2 3 5 8 13...

Y esta serie también continúa para siempre. Creo que es interesante cómo termina reflejando los números normales de Fibonacci, solo con cualquier otro número negativo:

13 -8 5 -3 2 -1 1 0 1 1 2 3 5 8 13...

Llamemos a esta serie el "Número de Fibonacci extendido", o EFN . Como no hay realmente un número negativo obvio para comenzar esta serie, diremos que 0 aparece en 0 , los números regulares de Fibonacci se extienden a los índices positivos, y los números negativos de Fibonacci (¿medio negativos?) en los índices negativos, así:

Indices: ...-7  -6 -5  -4 -3  -2 -1  0  1  2  3  4  5  6  7 ...
Values:  ...13  -8  5  -3  2  -1  1  0  1  1  2  3  5  8  13...

Esto lleva al desafío de hoy:

Dado un número entero N , devuelve cada índice en el que aparece N en la serie EFN .

Algunas observaciones aleatorias sobre esta tarea:

  • 1 aparece más veces en el EFN que cualquier otro número: [-1, 1, 2]. Ningún número aparecerá en más de 3 lugares.

  • Cada número de Fibonacci> 1 aparecerá una vez (3, 8, 21, etc.) o dos veces (2, 5, 13, etc.)

Aclaraciones de reglas:

  • Si abs(N)no es un número de Fibonacci, nunca aparecerá en la serie EFN , por lo que no debe generar nada / una colección vacía si es posible, o si eso no es posible en su idioma, puede generar un valor no numérico constante.
  • Si N aparece en varios lugares en el EFN , su salida no necesita ser ordenada. Aunque cada índice debe aparecer exactamente una vez.
  • Aunque la mayoría de los desafíos de permiten elegir si desea usar la indexación basada en 1 o en 0, este desafío debe usar la indexación descrita (donde 0 aparece en 0).
  • Puede tomar E / S a través de cualquier formato estándar.

Casos de prueba

-13: []
-12: []
-11: []
-10: []
-9: []
-8: [-6]
-7: []
-6: []
-5: []
-4: []
-3: [-4]
-2: []
-1: [-2]
0: 0
1: [-1, 1, 2]
2: [-3, 3]
3: [4]
4: []
5: [-5, 5]
6: []
7: []
8: [6]
9: []
10: []
11: []
12: []
13: [-7, 7]

Y algunos casos de prueba más grandes:

89: [-11, 11]
1836311903: [46]
10000: []
-39088169: [-38]

Como de costumbre, ¡la respuesta más corta en bytes gana!

DJMcMayhem
fuente
Relacionado , aunque no es un duplicado, ya que no requiere el manejo de negativos o números que no son de Fibonacci.
DJMcMayhem
12
Por cierto, hay otra buena razón por la que los números de Fibonacci siempre deben indexarse ​​de manera que $ F_0 = 0 $, incluso cuando se usan solo números de Fibonacci positivos. Esa es la indexación que permite esta hermosa propiedad: si $ k $ divide $ n $, entonces $ F_k $ divide $ F_n $.
Greg Martin

Respuestas:

9

Haskell , 78 bytes

4 bytes guardados gracias a nimi

a#b=a:b#(a-b)
f 0=[0]
f a=do{(i,x)<-zip[0..a*a+1]$0#1;[-i|x==a]++[i|abs x==a]}

Pruébalo en línea!

Primero configuramos (#), (#)tomamos dos parámetros ay b, y devolvemos una lista que comienza con ay seguida por b#(a-b). Esto crea una lista infinita, pero debido a que Haskell es perezoso, no necesitamos preocuparnos de que se repita para siempre. Esto esencialmente funciona al revés creando la secuencia de Fibonacci antes de un cierto par. Por ejemplo (0#1), sería la lista de todos los números de Fibonacci con índice negativo.

Desde aquí hacemos f. ftoma un argumento aque es el número que estamos tratando de encontrar en la secuencia. Aquí usamos la donotación para hacer una lista de comprensión. Comenzamos tomando los primeros a*a+1elementos de la lista 0#11 . Dado que la función a*a+1crece más rápido que el inverso de la secuencia de Fibonacci, podemos estar seguros de que si verificamos dentro de este límite, encontraremos todos los resultados. Esto nos impide buscar en una lista infinita. Luego, para cada valor xe índice i, si x==aencontramos aen la mitad negativa de la secuencia, entonces regresamos -i, y si abs x==aregresamos itambién porque el valor absoluto de la mitad negativa es la mitad positiva, entonces lo encontramos allí.

Ya que esto hace la lista [0,0]para 0que codificar la salida correcta para que uno.

1: Este truco está tomado de la respuesta limpia Οurous ' . Las mismas aplies speedup aquí, ya que, reemplazan a*a+1con abs a+1a ahorrar mucho tiempo.

Asistente de trigo
fuente
Reemplazar ucon a#b=a:b#(a-b)plus 0#1ahorra un byte: ¡ Pruébelo en línea!
nimi
@nimi En realidad ahorra 4 bytes, su enlace tio tiene 3 espacios adicionales.
Wheat Wizard
5

Limpio , 132 120 109 bytes

import StdEnv
g n|n<2=n=g(n-1)+g(n-2)
?k=[e\\p<-[0..k*k+1],e<-if(isOdd p)([~p,p]%(0,k))[p*sign k]|g p==abs k]

Pruébalo en línea!

g :: Int -> IntEs la función de Fibonacci.
? :: Int -> [Int]solo indexa los elementos de la EFN dentro k^2+1de 0.

Para una versión que se ejecuta en un tiempo razonable, cambie k*k+1a abs k+1.

Οurous
fuente
1
¡Ese truco de comprensión de la lista es bastante bueno! Guarda mis 14 bytes en mi respuesta.
Wheat Wizard
2

JavaScript (ES6),  94  93 bytes

n=>(g=a=>a*a<n*n?g(b,b+=a,i++):a%n)(i=0,b=1)?[]:i&1?n<0?~n?[]:-2:i-1?[-i,i]:[-i,i,2]:n<0?-i:i

Pruébalo en línea!

-0 0norte=0 0

Arnauld
fuente
1

Retina 0.8.2 , 104 102 bytes

[1-9].*
$*
(-)?(\b1|(?>\3?)(\2))*(1)$|(0)?.*
$5$1$4$4$#2$*
-1(11)+$

^1(11)+$
-$&,$&
1+
$.&
^2$
-1,1,2

Pruébalo en línea! Explicación:

[1-9].*
$*

Convierta a unario, a menos que la entrada sea cero.

(-)?(\b1|(?>\3?)(\2))*(1)$|(0)?.*
$5$1$4$4$#2$*

Calcule el índice de Fibonacci del valor absoluto, pero si el número no es un número de Fibonacci, elimínelo, a menos que sea cero. Esto utiliza la expresión regular de prueba de Fibonacci de @ MartinEnder.

-1(11)+$

Eliminar números negativos cuyos valores absolutos son números impares de Fibonacci.

^1(11)+$
-$&,$&

Agregue índices negativos para números impares positivos de Fibonacci.

1+
$.&

Convierte a decimal.

^2$
-1,1,2

Agregue los índices adicionales para 1.

Neil
fuente
1

En realidad , 34 bytes

;╗3*;±kSix⌠;;AF@;1&@0>*YτD(s**╜=⌡░

La fuerza bruta salva el día

Explicación:

;╗3*;±kSix⌠;;AF@;1&@0>*YτD(s**╜=⌡░
;╗                                  save a copy of the input (let's call it N) to register 0 (the main way to get additional values into functions)
  3*;±                              -3*N, 3*N
      kSi                           push to list, sort, flatten (sort the two values on the stack so that they are in the right order for x)
         x                          range(min(-3*N, 3*N), max(-3*N, 3*N))
          ⌠;;AF@;1&@0>*YτD(s**╜=⌡░  filter (remove values where function leaves a non-truthy value on top of the stack):
           ;;                         make two copies of parameter (let's call it n)
             AF                       absolute value, Fib(|n|)
               @;                     bring a copy of n to the top of the stack and make another copy
                 1&                   0 if n is divisible by 2 else 1
                   @0>                1 if n is negative else 0 (using another copy of n)
                      *               multiply those two values (acts as logical AND: is n negative and not divisible by 2)
                       YτD            logical negate, double, decrement (maps [0, 1] to [1, -1])
                          (s          sign of n (using the last copy)
                            **        multiply Fib(|n|), sign of n, and result of complicated logic (deciding whether or not to flip the sign of the value for the extended sequence)
                              ╜=      push value from register 0, equality comparison (1 if value equals N else 0)

Pruébalo en línea!

Mego
fuente
1

Python 3 , 92 bytes

f=lambda x,l=[],i=0,a=0,b=1:i<x*x+2and f(x,l+[i][:a==x]+[-i][:i%2*2*a-a==x],i+1,b,a+b)or{*l}

Pruébalo en línea!

Devuelve un conjunto de índices.

Erik el Outgolfer
fuente
0

05AB1E , 36 bytes

x*ÝʒÅfIÄQ}Ii®šë1KIdiÐ`ÉiD(ì}ëD`Èi(ë¯

Tiene que haber un mejor enfoque ...>.> Hay seis (o siete si incluimos 0) diferentes escenarios para este desafío, y me está matando ...

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

x            # Create a list in the range [0, (implicit) input * input * 2]
   ʒ     }     # Filter this list by:
    Åf         #  Where the Fibonacci value at that index
      IÄQ      #  Is equal to the absolute value of the input
Ii             # If the input is exactly 1:
  ®š           #  Prepend -1 to the list
ë              # Else:
 1K            #  Remove all 1s (only applies to input -1)
 Idi           #  If the input is non-negative:
    Ð`Éi   }   #   If the found index in the list is odd:
        D    #    Prepend its negative index to the list
   ë           #  Else (the input is negative):
    Di       #   If the found index in the list is even:
        (      #    Negate the found index
       ë       #   Else (found index is odd):
        ¯      #    Push an empty array
               # (Output the top of the stack implicitly as result)

Algunos ejemplos paso a paso:

Input:  Filtered indices:  Path it follows (with actions) and result:

-8      [6]                NOT 1 → neg → even index → negate index: [-6]
-5      [5]                NOT 1 → neg → odd index → push empty array: []
-1      [1,2]              NOT 1 → (remove 1) neg → even remaining index: negate index: [-2]
0       [0]                NOT 1 → even index → negate index: [0]    
1       [1,2]              1 → prepend -1: [-1,1,2]
5       [5]                NOT 1 → non-neg → odd index → Prepend neg index: [-5,5]
8       [6]                NOT 1 → non-neg → even index → (nothing): [6]
Kevin Cruijssen
fuente