Produtos Fibonacci

13

Você pode decompor um número maior que 0 como uma soma exclusiva dos números positivos de Fibonacci. Nesta questão, fazemos isso subtraindo repetidamente o maior número possível de Fibonacci positivo. Por exemplo:

1 = 1
2 = 2
3 = 3
4 = 3 + 1
12 = 8 + 3 + 1
13 = 13
100 = 89 + 8 + 3

Agora, chamo um produto de Fibonacci da mesma lista que acima, mas com a adição substituída pela multiplicação. Por exemplo f(100) = 89 * 8 * 3 = 2136,.

Escreva um programa ou função que, dado um número inteiro positivo n, retorne o produto Fibonacci desse número.


Casos de teste:

1: 1
2: 2
3: 3
4: 3
5: 5
6: 5
7: 10
8: 8
9: 8
42: 272
1000: 12831
12345: 138481852236
orlp
fonte
6
A afirmação não está correta. Por exemplo, 2pode ser decomposto como -1 + 3. A afirmação correta do teorema de Zeckendorf é que um número de Fibonacci positivo pode ser decomposto exclusivamente como uma soma de números de Fibonacci não consecutivos com índice positivo.
Peter Taylor
1
@ PeterTaylor Não considero números negativos de Fibonacci parte da série para esta pergunta. Consecutivo ou não importa apenas quando você deseja os índices, não nos importamos com os índices para esta pergunta.
orlp 13/05
1
Não estou dizendo que você deve alterar a pergunta para suportar números negativos de Fibonacci: estou dizendo que você deve editá-la para ser explícita sobre as suposições que está fazendo.
Peter Taylor
1
@orlp consecutivo ou não importa muito, já que duas formas diferentes dariam dois produtos diferentes. Você já declarou o problema de uma maneira que já exclui implicitamente termos consecutivos de Fibonacci, portanto não há nada com o que se preocupar.
Hbbs #:
2
(especificamente: F (n) e F (n + 1) não podem aparecer na saída porque o algoritmo garante que, antes de considerá-los, o restante já é menor que F (n + 2) = F (n) + F (n + 1))
hobbs 13/05

Respostas:

5

Geléia , 16 15 bytes

Rf1+С¤ṪạµÐĿIAP

Não é particularmente rápido ou amigo da memória, mas eficiente o suficiente para todos os casos de teste. Experimente online!

Como funciona

Rf1+С¤ṪạµÐĿIAP  Main link. Argument: n (integer)

         µ       Combine the chain to the left into a link.
          ÐĿ     Apply that link until the results are no longer unique.
                 Return the list of unique results.
      ¤            Combine the two links to the left into a niladic chain.
  1                  Set the left (and right) argument to 1.
   +D¡               Apply + to the left and right argument, updating the left
                     argument with the sum, and the right argument with the
                     previous value of the left one. Return the list of results.
                     Repeat this process n times.
                   This yields n + 1 Fibonacci numbers, starting with 1, 2.
R                  Range; map k to [1, ..., k].
 f                 Filter; keep the items in the range that are Fibonacci numbers.
       Ṫ           Tail; yield the last one or 0 if the list is empty.
        ạ          Absolute difference with k.
                   This is the argument of the next iteration.
            I    Compute the increments of the arguments to the loop, yielding
                 the selected Fibonacci numbers (with changed sign).
             A   Apply absolute value to each.
              P  Compute their product.  
Dennis
fonte
6
Isso parece grande, Dennis.
orlp 13/05
9

Python, 54 bytes

f=lambda n,a=1,b=1:n<1or b>n and a*f(n-a)or f(n,b,a+b)

Apenas uma boa e velha recursão.

Sp3000
fonte
5

Perl, 69 63 + 4 ( -pl61sinalizador) = 67 bytes

#!perl -pl61
while($_){$n=$m=1;($n,$m)=($m,$n+$m)until$m>$_;$_-=$n;$\*=$n}}{

Usando:

> echo 42 | perl -pl61e 'while($_){$n=$m=1;($n,$m)=($m,$n+$m)until$m>$_;$_-=$n;$\*=$n}}{'

Ungolfed:

while (<>) {
# code above added by -p
    # $_ has input value
    # $\ = 1 by -l61
    while ($_ != 0) {
        my $n = 1;
        my $m = 1;
        while ($m <= $_) {
            ($n, $m) = ($m, $n + $m);
        }
        $_ -= $n;
        $\ *= $n;
    }
} {
# code below added by -p
    print;  # prints $_ (undef here) and $\
}

Ideone .

Denis Ibaev
fonte
A explicação deve mencionar que octal 061é a codificação ASCII para o caractere '1'. Bom truque para usar $\para imprimi-lo quase de graça.
Peter Cordes
2

JavaScript (ES6), 78 42 bytes

f=(n,a=1,b=1)=>n?b>n?a*f(n-a):f(n,b,a+b):1

Porta da resposta do @ Sp3000. Versão original de 78 bytes:

f=(n,a=[2,1])=>n>a[0]?f(n,[a[0]+a[1],...a]):a.map(e=>e>n?0:(r*=e,n-=e),r=1)&&r
Neil
fonte
2

> <> , 57 bytes

111\ ;n{/
:@+>:{:})?\$:@@
~{*}:0=?\}>:0${:})?$~:{$-$:1@?$

Espera que o número de entrada esteja presente na pilha no início do programa.

Constrói a sequência de Fibonacci ( f0, f1, f2, ..., fn) na pilha até que seja atingido um número maior que a entrada ( i). Em seguida, com um produto ( p) inicializado para 1...

while (i != 0)
   if (fn <= i)
      i = i - fn
      p = p * fn
   else
      i = i - 0
      p = p * 1
   discard fn
output p

Experimente online!

Sok
fonte
Agradável! Eu sugiro que você postar um link usando um compilador de linha
Luis Mendo
1

Pitão, 28 bytes

K1WQJ0 .WgQH+Z~JZ1=*KJ=-QJ;K

Eu acho que pode ser jogado muito mais longe ...

Experimente online!

Freira Furada
fonte
1

Pitão, 24 bytes

W=-QeaYh.WgQeH,eZsZ1;*FY

Experimente on-line: Demonstration or Test Suite

Explicação:

Q é atribuído com o número de entrada.

A parte h.WgQeH,eZsZ1calcula o maior número de Fibonacci, menor ou igual aQ

h.WgQeH,eZsZ1
            1   start with H=Z=1
 .WgQeH         while Q >= end(H):
       ,eZsZ       H=Z=(end(Z), sum(Z))
h               first

Então Q = 10, se ele gera os números / pares:

1 -> (1,1) -> (1,2) -> (2,3) -> (3,5) -> (5,8) -> (8,13) -> 8

O restante do código calcula a partição e multiplica os números juntos:

W=-QeaY...;*FY    implicit: Y = empty list
     aY...        add the calculated Fibonacci number to the empty list
    e             take the last element of Y (yes the number we just added)
 =-Q              and update Q with the difference of Q and ^
W         ;       continue until Q == 0
           *FY    multiply all number in Y and print

Obviamente, existem muitas soluções mais curtas (com tempos de execução realmente ruins), como *FhfqQsTyeM.u,eNsNQ1.

Jakube
fonte
1

Haskell, 44 bytes

Yay para recursão mútua:

(a&b)c|c<1=1|b>c=a*f(c-a)|d<-a+b=b&d$c
f=0&1
  • a é o número anterior de Fibonacci
  • b é o número atual de Fibonacci
  • c é a entrada
  • f é a função desejada

Menos golfe:

(a & b) c | c == 0    = 1
          | c <  b    = a * f (c-a)
          | otherwise = b & (a + b) $ c
f x = (0 & 1) x
Michael Klein
fonte
1

Na verdade, 22 bytes

W;╗uR♂F;`╜≥`M░M;╜-WXkπ

Experimente online!

Explicação:

W;╗uR♂F;`╜≥`M░M;╜-WXkπ
                        (implicit input)
W                 W     while top of stack is truthy:
 ;╗                       push a copy of n to reg0
   uR♂F;                  push 2 copies of [Fib(a) for a in range(1, n+2)]
        `╜≥`M░            filter: take values where n <= Fib(a)
              M;          two copies of maximum (call it m)
                ╜-        subtract from n (this leaves n-m on top of the stack to be the new n next iteration, with a copy of m below it)
                   X    discard the 0 left over after the loop ends
                    kπ  product of all stack values
Mego
fonte
Realmente tem sua própria codificação? Conto 35 bytes em 22 caracteres. mothereff.in/…
cat
1
@cat Assim como a sério, ele usa o CP437.
Mego 14/05
1

Javascript (ES6) 134 106 92 bytes

Obrigado pelo @cat por detectar um espaço.

n=>{for(c=[a=b=s=1,1];a+b<=n;)a+=b,c.unshift(b+=a,a);c.map(i=>i<=n&&(n-=i)&(s*=i));alert(s)}

Apenas uma versão não otimizada feita no meu telefone, eu jogo quando chego em casa. Idéias são bem vindas.

Bálint
fonte
um espaço em branco supérfluo. : P
cat
1

RETURN , 44 bytes

[a:[a;][1$[¤¤+$a;->~][]#%$␌a;\-a:]#␁[¤][×]#]

Try it here.

Lambda anônima surpreendentemente ineficiente que deixa o resultado no Stack2. Uso:

12345[a:[a;][1$[¤¤+$a;->~][]#%$␌a;\-a:]#␁[¤][×]#]!

NOTA: ␌ e ␁ são espaços reservados para seus respectivos caracteres não imprimíveis: alimentação de formulário e início do cabeçalho .

Explicação

[                                           ]  lambda
 a:                                            store input to a
   [  ][                         ]#            while loop
    a;                                           check if a is truthy
        1$[¤¤+$a;->~][]#%                        if so, generate all fibonacci numbers less than a 
                         $␌                      push copy of TOS to stack2
                           a;\-a:                a-=TOS
                                   ␁[¤][×]#   get product of stack2
Mama Fun Roll
fonte
Conto 46 bytes em 42 caracteres. Se RETURN usa alguns codificação tipo especial, que deve ser de 42 bytes em 42 caracteres, mas parece ser unicode, por isso é 46.
cat
Na verdade, acabei de perceber que esqueci de colocar alguns imprimíveis.
Mama Fun Roll
Eu precisava de um microscópio para dizer o que são, então liguei a eles para você. : D (eu não sabia dizer se era SOH ou BOM) #
cat
0

PHP, 119 bytes

O código (dividido em duas linhas para facilitar a leitura):

for($o=$c=1;$c<=$n=$argv[1];$f[++$k]=$c,$a=$b,$b=$c,$c+=$a);
for($i=$k;$i;$i--)for(;$n>=$d=$f[$i];$n-=$d,$o*=$d);echo$o;

A primeira linha calcula nos $fnúmeros de Fibonacci menores que $n(o argumento fornecido na linha de comando). A segunda linha calcula os fatores de Fibonacci (por subtração) e os multiplica para calcular o produto $o.

Anexe o código com <?php(tecnicamente não faz parte do programa), coloque-o em um arquivo ( fibonacci-factors.php) e execute-o como:

$ php -d error_reporting=0 fibonacci-factors.php 100
# The output:
2136

Ou execute-o usando php -d error_reporting=0 -r '... code here ...' 100.

O código não-protegido e o conjunto de testes podem ser encontrados no Github .

axiac
fonte
0

Q, 47 bytes

m:{*/1_-':|(0<){y-x x bin y}[*+60(|+\)\1 0]\x}

Teste

+(i;m'i:1 2 3 4 5 6 7 8 9 42 1000 12345)

leia-o como pares (i, mapa (m, i)), onde m é a função de cálculo ei os diferentes argumentos

escreve

1     1
2     2
3     3
4     3
5     5
6     5
7     10
8     8
9     8
42    272
1000  12831
12345 138481852236

Explicação

n funtion\arg aplica function (function (function (... function (args))) n times (usa internamente tal recursão) e retorna a sequência de resultados. Calculamos os 60 primeiros itens da série fibonnaci como *+60(|+\)\1 0. Nesse caso, a função é ( | +): + \ aplicado sobre uma sequência calcula somas parciais (ex + \ 1 2 3 é 1 3 6) e | inverte a seq. Portanto, cada 'iteração' calculamos somas parciais dos dois números anteriores de fibonacci e retornamos o parcial soma invertida 60(|+\)\1 0gera as seqüências 1 0, 1 1, 2 1, 3 2, 5 3, 8 5, 13 8, 21 13, ...*+ aplicado sobre esse resultado flip (traspose) e pega o primeiro. 1 2 3 5 8 13 21 34 55 ..

(cond)function\args aplica function (function (.. function (args))) enquanto cond true e retorna a sequência de resultados parciais

function[arg] aplicado sobre uma função de mais de um argumento cria uma projeção (aplicação parcial)

Podemos dar um nome aos argumentos, mas os nomes implícitos são x, y, z

{y-x x bin y}[*+60(|+\)\1 0]declara um lambda com args x, y com projeção parcial (arg x é uma série de fibonacci, calcula como * + 60 (| +) \ 1 0). x representam valores de fibonacci e y o número a processar. A pesquisa binária (bin) é usada para localizar o índice do maior número de fibonacci <= y ( x bin y) e subtrair o valor correspondente de x.

Para calcular o produto a partir de resultados parciais, nós os revertemos e calculamos a diferença de cada par ( -':|), descartamos o primeiro ( 1_porque é 0) e multiplicamos por ( */).

Se estamos interessados ​​na soma acumulada, o código é o mesmo, mas com em +/vez de */. Também podemos usar qualquer outro operador diádico em vez de + ou *

Sobre eficiência de execução

Eu sei que neste concurso a eficiência não é um problema. Mas neste problema, podemos variar de custo linear a custo exponencial, por isso estou curioso.

Eu desenvolvi uma segunda versão (comprimento de 48 bytes, excluindo comentários) e repeti os casos de teste de bateria 1000 vezes nas duas versões.

f:*+60(|+\)\1 0;m:{*/1_-':|(0<){x-f f bin x}\x}    /new version

o tempo de execução é: versão original 0'212 seg, nova versão 0'037 seg

A versão original calcula a série fibbonaci uma vez por aplicativo de função; nova versão calcula fibonacci apenas um.

Em ambos os casos, o cálculo da série de fibonacci usa recursão da cauda

J. Sendra
fonte