Indexando os números estendidos de Fibonacci

21

Você provavelmente já ouviu falar dos números de Fibonacci. Você sabe, aquela sequência inteira que começa com 1, 1, e então cada novo número é a soma dos dois últimos?

1 1 2 3 5 8 13...

E assim por diante. Os desafios sobre os números de Fibonacci são bastante populares por aqui . Mas quem disse que os números de Fibonacci precisam começar 1, 1? Por que eles não podiam começar 0, 1? Tudo bem, vamos redefini-los para começar em 0:

0 1 1 2 3 5 8 13...

Mas ... Nós também não temos que parar por aí! Se pudermos adicionar os dois últimos números para obter o próximo, também podemos subtrair o primeiro número do segundo número para adicionar um novo número. Então, pode começar com 1, 0:

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

Podemos até acabar com negativos:

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

E esta série também continua para sempre. Eu acho interessante como isso acaba refletindo os números regulares de Fibonacci, apenas com todos os outros números negativos:

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

Vamos chamar essa série de "Número Estendido de Fibonacci", ou EFN . Como não há realmente um número negativo óbvio para iniciar esta série, diremos que 0 aparece em 0 , os números regulares de Fibonacci se estendem aos índices positivos e os números negativos (meio-negativos?) De Fibonacci se estendem para os índices negativos, assim:

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

Isso leva ao desafio de hoje:

Dado um número inteiro N , retorne todos os índices nos quais N aparece na série EFN .

Algumas observações aleatórias sobre esta tarefa:

  • 1 aparece mais vezes no EFN do que qualquer outro número: [-1, 1, 2]. Nenhum número aparecerá em mais de 3 lugares.

  • Todo número de Fibonacci> 1 será exibido uma vez (3, 8, 21 etc.) ou duas vezes (2, 5, 13 etc.)

Esclarecimentos sobre as regras:

  • Se abs(N)não for um número de Fibonacci, ele nunca aparecerá na série EFN ; portanto, você não deve produzir nada / uma coleção vazia, se possível, ou se isso não for possível no seu idioma, você poderá gerar algum valor não numérico constante.
  • Se N aparecer em vários locais no EFN , sua saída não precisará ser classificada. Embora cada índice deva aparecer exatamente uma vez.
  • Embora a maioria dos desafios de permita que você escolha se deseja usar a indexação com base em 1 ou em 0, esse desafio deve usar a indexação descrita (onde 0 aparece em 0).
  • Você pode levar a E / S através de qualquer formato padrão.

Casos de teste

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

E alguns casos de teste maiores:

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

Como sempre, a resposta mais curta em bytes vence!

DJMcMayhem
fonte
Relacionado , embora não seja duplicado, pois não requer manipulação de números negativos ou não de Fibonacci.
DJMcMayhem
12
A propósito, há outra boa razão para que os números de Fibonacci sempre sejam indexados para que $ F_0 = 0 $, mesmo quando se usa apenas números positivos de Fibonacci. Essa é a indexação que permite essa bela propriedade: se $ k $ divide $ n $, $ F_k $ divide $ F_n $.
Greg Martin

Respostas:

9

Haskell , 78 bytes

4 bytes salvos graças 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]}

Experimente online!

Primeiro, configuramos (#), obtemos (#)dois parâmetros ae b, e retorna a lista a iniciando com ae seguida por b#(a-b). Isso cria uma lista infinita, mas, como Haskell é preguiçoso, não precisamos nos preocupar com isso para sempre. Isso funciona essencialmente para trás, criando a sequência de Fibonacci antes de um determinado par. Por exemplo, (0#1)seria a lista de todos os números de Fibonacci com índice negativo.

A partir daqui, fazemos f. fusa um argumento aque é o número que estamos tentando encontrar na sequência. Aqui usamos a donotação para fazer uma compreensão da lista. Começamos com os primeiros a*a+1elementos da lista 0#11 . Como a função a*a+1cresce mais rápido que o inverso da sequência de Fibonacci, podemos ter certeza de que, se verificarmos dentro desse limite, encontraremos todos os resultados. Isso nos impede de pesquisar uma lista infinita. Então, para cada valor xe índice i, se x==aencontramos ana metade negativa da sequência, retornamos -ie seabs x==a retornamos i, porque o valor absoluto da metade negativa é a metade positiva, e então a encontramos.

Como isso faz com que a lista [0,0]para 0nós codifique a saída correta para essa.

1: Esse truque foi retirado da resposta limpa do ousurous . A mesma aceleração se aplica aqui e ali, substitua a*a+1por abs a+1para economizar muito tempo.

Assistente de Trigo
fonte
Substituir upor a#b=a:b#(a-b)mais 0#1salva um byte: Experimente online!
nimi 9/02
@nimi Na verdade, ele salva 4 bytes, seu link de tio possui 3 espaços extras.
Wheat Wizard
5

Limpo , 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]

Experimente online!

g :: Int -> Inté a função de Fibonacci.
? :: Int -> [Int]apenas indexa os elementos do EFN dentro k^2+1de 0.

Para uma versão que é executada em uma quantidade razoável de tempo, altere k*k+1para abs k+1.

Furioso
fonte
1
Esse truque de compreensão da lista é bem legal! Salva meus 14 bytes na minha resposta.
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

Experimente online!

-0 0n=0 0

Arnauld
fonte
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

Experimente online! Explicação:

[1-9].*
$*

Converta para unário, a menos que a entrada seja zero.

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

Calcule o índice de Fibonacci do valor absoluto, mas se o número não for um número de Fibonacci, exclua-o, a menos que seja zero. Isso usa o regex de teste de Fibonacci do @ MartinEnder.

-1(11)+$

Exclua números negativos cujos valores absolutos são números ímpares de Fibonacci.

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

Adicione índices negativos para números de Fibonacci positivos ímpares.

1+
$.&

Converta para decimal.

^2$
-1,1,2

Adicione os índices extras para 1.

Neil
fonte
1

Na verdade , 34 bytes

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

Força bruta salva o dia

Explicação:

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

Experimente online!

Mego
fonte
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}

Experimente online!

Retorna um conjunto de índices.

Erik, o Outgolfer
fonte
0

05AB1E , 36 bytes

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

Tem que haver uma abordagem melhor ..>.> Existem seis (ou sete, se incluirmos 0 ) cenários diferentes para esse desafio, e isso está me matando.

Experimente online ou verifique todos os casos de teste .

Explicação:

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)

Alguns exemplos passo a passo:

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
fonte