Esse número é secretamente Fibonacci?

23

fundo

Muitos de vocês sabem o que é um número de Fibonacci . Alguns de vocês devem saber que todos os números inteiros positivos podem ser representados como uma soma de um ou mais números distintos de Fibonacci, de acordo com o Teorema de Zeckendorf . Se o número de termos na representação ideal de Zeckendorf de um número inteiro nfor ele próprio um número de Fibonacci, chamaremos nFibonacci "secretamente".

Por exemplo:

139 = 89 + 34 + 13 + 3
This is a total of 4 integers. Since 4 is not a Fibonacci number, 139 is not secretly Fibonacci

140 = 89 + 34 + 13 + 3 + 1
This is a total of 5 integers. Since 5 is a Fibonacci number, 140 is secretly Fibonacci

Notas

  • A representação ideal de Zeckendorf pode ser encontrada usando um algoritmo guloso. Basta pegar o maior número de Fibonacci <= n e subtraí-lo de n até chegar a 0
  • Todos os números de Fibonacci podem ser representados como uma soma de 1 número de Fibonacci (ele mesmo). Como 1 é um número de Fibonacci, todos os números de Fibonacci também são secretamente Fibonacci.

Desafio

Seu desafio é escrever um programa ou função que use um número inteiro e retorne se esse número inteiro é secretamente Fibonacci.

Entrada

Você pode receber informações em qualquer formato razoável. Você pode assumir que a entrada será um único número inteiro positivo.

Saída

Saída de um dos dois resultados distintos para saber se a entrada é secretamente Fibonacci. Exemplos incluem True/ False, 1/ 0, etc.

Pontuação

Isso é , então a resposta mais curta em bytes vence! As brechas padrão são proibidas.

Casos de teste

Truthy (secretly Fibonacci)
1
2
4
50
140
300099

Falsey (NOT secretly Fibonacci)
33
53
54
139
118808
Cowabunghole
fonte
6
Isso significa que eles são fi-curiosos?
kevin
2
Caso seja útil para qualquer pessoa: a soma ideal é a solução única que não utiliza dois números consecutivos de Fibonacci.
kasperd
2
@kasperd Você está correto, o que faz sentido se você pensar sobre isso. Se a solução tivesse dois números consecutivos de Fibonacci, eles poderiam ser adicionados para formar o próximo. Se a sua solução continha 5 e 8, seria menos ideal do que ter uma única 13.
Cowabunghole
@ Cowabunghole Essa é a intuição. Uma prova completa é um pouco mais complicada do que isso. Se a solução já continha 5, 8 e 13, você adicionaria 8 + 13 e não 5 + 8. E a outra direção também precisa ser comprovada.
kasperd

Respostas:

8

Python 2 , 77 bytes

def f(n):z=[bin(x).count('1')for x in range(n*n+1)if x&2*x<1];print z[z[n]]<2

Experimente online!

Isso faz uso do teorema de que as duas descrições do OEIS A003714 são equivalentes:

n=F(Eu1)+F(Eu2)++F(Euk)nnuma(n)=2Eu1+2Eu2++2Euk1's.

zn

Resta verificar se z[n]é um número de Fibonacci, ou seja z[z[n]] == 1.

n2+1

Lynn
fonte
Você pode cortar dois bytes removendo os backticks bin(x). Você também pode remover um alterando range(n*n+1)para range(n<<n). (Supondo que 0 é inválido)
nedla2004
Eu não sei o que estava pensando com as costas bin(x), haha. E, hm, 1<<njá é muito, muito mais do que suficiente, mas eu gostaria de manter o tempo de execução não-astronômico
Lynn
Bom, acho que poder executar o código pode ser um atributo importante. :)
nedla2004
6

Gelatina , 15 bytes

‘ÆḞ€fRṪạµƬL’Ɗ⁺Ị

Um link monádico que aceita um número inteiro não negativo que produz 1se "secretamente Fibonacci" e 0outros.

Experimente online! (muito ineficiente para os casos de teste maiores)

Quão?

‘ÆḞ€fRṪạµƬL’Ɗ⁺Ị - Link: integer, I
        µƬ      - perform the monadic link to the left as a function of the current I,
                - collecting up all the inputs until the results are no longer unique:
‘               -   increment I -> I+1
 ÆḞ€            -   nth Fibonacci number for €ach n in [1,I+1]
     R          -   range from 1 to I
    f           -   filter discard (discard Fibonacci numbers not in the range, i.e. > I)
      Ṫ         -   tail (get the largest)
       ạ        -   absolute difference with I
                - This gives us a list from I decreasing by Fibonacci numbers to 0
                - e.g. for 88 we get [88,33,12,4,1,0]
                -      because (88-33)+(33-12)+(12-4)+(4-1)+(1-0)=55+21+8+3+1=88 
          L     - length (the number of Fibonacci numbers required plus one)
           ’    - decrement (the number of Fibonacci numbers required)
            Ɗ   - treat the last three links (which is everything to the left) as a monad:
             ⁺  - ...and repeat it
                - i.e. get the number of Fibonacci numbers required for the number of
                -      Fibonacci numbers required to represent I.
                -      This is 1 if I is Secretly Fibonacci, and greater if not)
              Ị - insignificant? (is the absolute value of that <= 1?)
Jonathan Allan
fonte
5

R , 83 bytes

function(n){T=1:0
while(n>T)T=c(T[1]+T[2],T)
while(n){n=n-T[T<=n][1]
F=F+1}
F%in%T}

Experimente online!

Giuseppe
fonte
5

C # (.NET Core) , 124 115 98 bytes

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

Experimente online!

-3 bytes: mudou o loop while para for (graças a Olivier Grégoire )
-6 bytes: retornos comutados para usar a variável inicializada bec fora dos loops (graças a Kevin Cruijssen )
-17 bytes: condição alterada no segundo loop para mover se fora do loop e combine com retorno, variáveis ​​reutilizadas bec no último loop (graças ao raznagul )

Ungolfed:

a => {
    int n = 0, b, c;                        // initialize variables

    for(; a > 0; a -= b, n++)               // increase n until a is 0
        for(b = c = 1; c <= a; b = c - b)   // set b and c to 1 for each a; set second largest Fibonacci number until largest Fibonacci number reaches a
            c += b;                         // set largest Fibonacci number of current sequence

    for(b = c = 1; c < n; c += b)           // while e is less than or equal to n, continue incrementing largest (e) Fibonacci number in the sequence
        b = c - b;                          // increment second-largest (d) Fibonacci number

    return c == n;                          // if c equals n, a is a secret Fibonacci number
}
Meerkat
fonte
1
for(;c<=a;b=c-b)c+=b;você economizará 3 bytes.
Olivier Grégoire
1
115 bytes . {}Tirei todos os suportes de seus loops e coloquei tudo em for-loops. Além disso, adicionei uma variável rque definimos 1no seu if(e==n)e retornamos no final, para que você tenha apenas um return.
Kevin Cruijssen 30/10
Boa ligação para ambos. Eu tentei mudar o loop while para for e de alguma forma perdi a maneira mais fácil de fazer isso. Ter uma variável separada para retorno também é definitivamente melhor.
Meerkat
1
Ao alterar a condição no segundo loop para e<nque você pode mover a ifpara após o loop e consequentlly combiná-lo com o returnde 101 bytes .
raznagul
1
Você pode salvar outros 3 bytes reutilizando be cno último loop e removendo de e.
raznagul
4

Perl 6 , 58 bytes

{(1,&[+]...*>$_)∋($_,{$^n-(1,&[+]...^*>$n).tail}...0)-1}

Experimente online!

1, &[+] ... * > $_ é apenas a sequência de Fibonacci, parada em um local não-infinito conveniente (o número de entrada).

$_, { $^n - (1, &[+] ...^ * > $n).tail } ... 0é uma sequência de números, começando com o número de entrada, e cada elemento sucessivo obtido subtraindo o maior número de Fibonacci menor ou igual ao elemento anterior do elemento anterior. A sequência termina quando 0é alcançada. Por exemplo, se $_estiver 140, então esta sequência é 140, 51, 17, 4, 1, 0.

Subtrair um desta sequência o trata como um número, seu comprimento e a diferença é o número de números de Fibonacci que, somados, fornecem o número de entrada. Em seguida, esse número é verificado para associação na primeira sequência de Fibonacci.

Sean
fonte
Eu nunca vi esse truque com o &[+]antes! Bom economizar em não ter que definir dois termos iniciais
Jo rei
1
51 bytes por atribuir a sequência de Fibonacci a uma função e um par de outras alterações
Jo Rei
Resposta JavaScript do porto da l4m2, 50 bytes
nwellnhof 30/10
@nwellnhof Ha, eu tinha praticamente a mesma coisa, exceto por uma pequena diferença
Jo rei
3

Perl 6 , 48 bytes

{4>($_,{$_,{$_-(1,&[+]...*>$_)[*-2]}...^0}...1)}

Experimente online!

Transforma a entrada em uma lista de Representações Zeckendorf repetidamente até atingir um único número e depois verifica se o comprimento da sequência foi menor que 4.

A função Zenckendorf no meio é principalmente da resposta de Sean com algumas melhorias.

Explicação:

{4>($_,{$_,{$_-(1,&[+]...*>$_)[*-2]}...^0}...1)}
{                                              } # Anonymous code block
                                          ...     # Define a sequence:
    $_  # That starts at the input
      ,{                                 }  # Each element is defined by:
                                   ... # Another sequence that:
        $_,   # Starts at the previous element
            $_-   # The previous element minus
                1,&[+]...*     # The Fibonacci sequence
                          >$_  # Ending when it is larger than the previous element
               (             )[*-2]  # The second from last element
          {                        }...^0  # Run until 0, discarding the last element
         # This returns the length of the Zeckendorf Representation
                                         ...1  # Run this until it is length 1
 4>(                                         )  # Return true if the length of the sequence is smaller than 4

Por exemplo, a sequência para 2é que 2 12é um número de Fibonacci. A sequência para 140é 140 5 1e, como 5 é um número de Fibonacci, isso retorna verdadeiro. A sequência para 33é 33 4 2 1e, como 4não é um número de Fibonacci, a sequência tem comprimento 4.

Brincadeira
fonte
3

05AB1E , 14 bytes

ΔDÅFθ-¼}¾ÅF¾<å

Experimente online . Não há suíte de testes para todos os casos de teste, porque o counter_variablenão pode ser redefinido para 0. No entanto, verifiquei tudo manualmente e eles estão corretos.

Explicação:

Δ      }          # Loop until the top of the stack no longer changes
 D                #  Duplicate the top of the stack
                  #  (implicitly the input in the first iteration)
  ÅF              #  Get a list of all Fibonacci numbers lower than this number
    θ             #  Get the last item (largest one)
     -            #  Subtract it from the number
      ¼           #  Increase the counter_variable by 1 every iteration
        ¾         # After the loop, push the counter_variable
         ÅF       # Get all Fibonacci numbers below this counter_variable
           ¾<     # Push the counter_variable again, and subtract 1
             å    # Check if this value is in the list of Fibonacci numbers
                  # (and output implicitly)

NOTA: counter_variableSeria 5para entrada 139e 6para entrada 140, porque, para que o Δloop-verifique a pilha permaneceu a mesma, é claro que faz uma iteração adicional.

Kevin Cruijssen
fonte
2

Retina 0.8.2 , 61 bytes

.+
$*
M`((?>\2?)(\1|\G.))*..|.
.+
$*
^(((?>\3?)(\2|^.))*.)?.$

Experimente online! O link inclui casos de teste. Explicação:

.+
$*

Converta para unário.

M`((?>\2?)(\1|\G.))*..|.

Conte o número de números de Fibonacci necessários.

A primeira alternância lida com números de Fibonacci que são pelo menos 2. Na primeira passagem, \2ainda não existe, mas felizmente é opcional, portanto, não precisamos correspondê-la. \1também não existe, mas, felizmente, temos a alternativa \G.que corresponde a um único caractere no início da partida. Ambos \2e, \1portanto, assumem o valor 1.

Nos passes subsequentes, \2existe, então tentamos combiná-lo. Desta vez, se falhar, \1também falhará (já que é maior que \2), mas se for bem-sucedido, o (?>)impedirá de voltar atrás; portanto, se \2corresponder, mas \1não, não tentamos apenas \1. ( \G1sempre falha desde que avançamos após o início do patch.) Finalmente \2assume o valor anterior de \1while \1assume a soma dos dois valores.

Portanto, combinamos o maior número possível de Fibonacci, adicionando à medida que avançamos. Como as somas parciais da sequência 1, 2, 3, 5...são, 0, 1, 3, 6, 11...ou seja, 2 menores que os números de Fibonacci, terminamos combinando 2 no final.

Obviamente, isso não corresponde a 1, então uma alternância lida com esse caso.

.+
$*

Converta para unário.

^(((?>\3?)(\2|^.))*.)?.$

Teste se este é um número de Fibonacci. Isso usa a mesma idéia do primeiro teste, mas usa em ^vez de \Ge também precisamos corresponder exatamente, portanto, usa uma captura opcional em vez de uma alternância, pois é mais golfista (mas aumenta os números de captura em 1).

Retina , 35 bytes

.+
*
2}C`((?>\2?)(\1|\G.))*..|.
^1$

Experimente online! O link inclui casos de teste. Explicação:

.+
*

Converta para unário.

C`((?>\2?)(\1|\G.))*..|.

Conte o número de números de Fibonacci necessários. (Fazer um loop na conversão e na contagem economiza um byte inteiro, deixando a contagem unária em primeiro lugar.)

2}

Execute as etapas anteriores duas vezes no total. Isso leva a contagem de números de Fibonacci necessária para somar à contagem de números de Fibonacci.

^1$

Se o número era secretamente Fibonacci, o resultado é 1.

Neil
fonte
1

Python 2 , 146 137 bytes

lambda a:len(g(len(g(a))))<2
f=lambda n:n<3or f(n-2)+f(n-1)
def g(a,n=1):j=f(n-1);return[j]if a-j<1else[j]+g(a-j)if a-f(n)<0else g(a,n+1)

Experimente online!

f () é uma função recursiva que retorna o valor do enésimo número de Fibonacci. Retirado desta resposta .

g () é uma função recursiva que retorna a representação Zeckendorf do número fornecido como uma lista de números inteiros.

Como todos os números de Fibonacci terão um comprimento de retorno de um item de g (), h () verifica se o comprimento de g () de g (n) == 1.

EDIT: Salvo 9 bytes graças a nedla2004 . Fico esquecendo que as lambdas nem sempre são a melhor solução ...

Triggernometria
fonte
1
138 bytes . Na maioria das vezes, apenas criei guma função para que eu pudesse definir f(n-1)uma variável. Algumas outras mudanças a partir ==de <onde eles são os mesmos.
nedla2004