Productos de Fibonacci


13

Puede descomponer un número mayor que 0 como una suma única de números positivos de Fibonacci. En esta pregunta, hacemos esto restando repetidamente el mayor número positivo posible de Fibonacci. P.ej:

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

Ahora, llamo a un producto de Fibonacci las mismas listas que arriba, pero con la suma reemplazada por multiplicación. Por ejemplo, f(100) = 89 * 8 * 3 = 2136.

Escriba un programa o función que dado un número entero positivo n devuelva el producto de Fibonacci de ese número.


Casos de prueba:

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

66
La declaración no es del todo correcta. Por ejemplo, 2se puede descomponer como -1 + 3. La afirmación correcta del teorema de Zeckendorf es que un número positivo de Fibonacci puede descomponerse de manera única como una suma de números de Fibonacci no consecutivos con índice positivo.
Peter Taylor

1
@PeterTaylor No considero que los números negativos de Fibonacci sean parte de la serie para esta pregunta. Consecutiva o no solo importa cuando desea los índices, no nos interesan los índices para esta pregunta.
orlp

1
No digo que debas cambiar la pregunta para admitir números negativos de Fibonacci: digo que debes editarla para que sea explícita sobre los supuestos que estás haciendo.
Peter Taylor

1
@orlp consecutiva o no importa bastante, ya que dos formas diferentes darían dos productos diferentes. Sin embargo, ya mencionó el problema de una manera que ya excluye implícitamente los términos consecutivos de Fibonacci, por lo que no hay nada de qué preocuparse.
hobbs

2
(específicamente: F (n) y F (n + 1) no pueden aparecer en la salida porque el algoritmo garantiza que, antes de considerarlos, el resto ya es menor que F (n + 2) = F (n) + F (n + 1))
hobbs

Respuestas:


5

Jalea , 16 15 bytes

Rf1+С¤ṪạµÐĿIAP

No es particularmente rápido ni amigable con la memoria, pero lo suficientemente eficiente para todos los casos de prueba. Pruébalo en línea!

Cómo 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.  

66
Esto parece grande, Dennis.
orlp

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)

Solo una buena y vieja recursión.


5

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

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

Utilizando:

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

Sin golf:

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 .


La explicación debería mencionar que octal 061es la codificación ASCII para el carácter '1'. Buen truco para usar $\para imprimirlo casi gratis.
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

Puerto de la respuesta de @ Sp3000. Versión 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

2

> <> , 57 bytes

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

Espera que el número de entrada esté presente en la pila al inicio del programa.

Desarrolla la secuencia de Fibonacci ( f0, f1, f2, ..., fn) en la pila hasta que se alcanza un número que es mayor que la entrada ( i). Luego, con un producto ( p) inicializado a 1...

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

Pruébelo en línea!


¡Agradable! Le sugiero que publique un enlace usando un compilador en línea
Luis Mendo


1

Pyth, 24 bytes

W=-QeaYh.WgQeH,eZsZ1;*FY

Pruébelo en línea: Demostración o conjunto de pruebas

Explicación:

Q se asigna con el número de entrada.

La parte h.WgQeH,eZsZ1calcula el mayor número de Fibonacci, que es menor o 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

Entonces Q = 10, si , genera los números / pares:

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

El resto del código calcula la partición y multiplica los números:

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, hay muchas soluciones más cortas (con tiempos de ejecución realmente malos), como *FhfqQsTyeM.u,eNsNQ1.


1

Haskell, 44 bytes

Yay por recursión mutua:

(a&b)c|c<1=1|b>c=a*f(c-a)|d<-a+b=b&d$c
f=0&1
  • a es el número de Fibonacci anterior
  • b es el número actual de Fibonacci
  • c es la entrada
  • f es la función deseada

Menos golfizado:

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

1

En realidad, 22 bytes

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

Pruébalo en línea!

Explicación:

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

¿Realmente tiene su propia codificación? Cuento 35 bytes en 22 caracteres. mothereff.in/…
gato

1
@cat Al igual que en serio, utiliza CP437.
Mego

1

Javascript (ES6) 134 106 92 bytes

Gracias por @cat por ver un espacio.

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

Solo una versión no optimizada hecha en mi teléfono, la uso una vez que llego a casa. Las ideas son bienvenidas.


Hay un espacio en blanco superflua. : P
gato

1

RETORNO , 44 bytes

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

Try it here.

Asombrosamente ineficiente lambda anónima que deja resultado en Stack2. Uso:

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

NOTA: ␌ y ␁ son marcadores de posición para sus respectivos caracteres no imprimibles: avance de formulario y comienzo de encabezado .

Explicación

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

Cuento 46 bytes en 42 caracteres. Si RETURN utiliza una codificación un poco especial, debe tener 42 bytes en 42 caracteres, pero parece ser unicode, por lo que es 46.
cat

En realidad, me di cuenta de que olvidé poner algunos no imprimibles.
Mama Fun Roll

Necesitaba un microscopio para saber qué son, así que los vinculé por ti. : D (no podría decir si era SOH o BOM)
gato

0

PHP, 119 bytes

El código (envuelto en dos líneas para facilitar la lectura):

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;

La primera línea calcula en $flos números de Fibonacci más pequeños que$n (el argumento proporcionado en la línea de comando). La segunda línea calcula los factores de Fibonacci (por sustracción) y los multiplica para calcular el producto $o.

Anteponga el código con <?php(técnicamente no forma parte del programa), póngalo en un archivo ( fibonacci-factors.php) y ejecútelo como:

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

O ejecutarlo usando php -d error_reporting=0 -r '... code here ...' 100 .

El código no protegido y el conjunto de pruebas se pueden encontrar en Github .


0

Q, 47 bytes

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

Prueba

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

léalo como pares (i, map (m, i)), donde m es la función de cálculo e i los diferentes argumentos

escribe

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

Explicación

n funtion\arg aplica function (function (function (... function (args))) n veces (usa internamente recursión tal) y devuelve la secuencia de resultados. Calculamos los 60 primeros elementos de la serie fibonnaci como *+60(|+\)\1 0. En ese caso, la función es ( | +): + \ aplicado sobre una secuencia calcula sumas parciales (por ejemplo, + \ 1 2 3 es 1 3 6) e invierte la secuencia. Por lo tanto, cada 'iteración' calculamos sumas parciales de los dos números de Fibonacci anteriores y devuelve el parcial sumas invertidas. 60(|+\)\1 0genera secuencias 1 0, 1 1, 2 1, 3 2, 5 3, 8 5, 13 8, 21 13, ... *+aplicadas sobre este resultado, voltéalo (traspónsalo) y toma el primero. El resultado es la secuencia 1 1 2 3 5 8 13 21 34 55 ..

(cond)function\args aplica function (function (.. function (args))) mientras cond verdadero, y devuelve la secuencia de resultados parciales

function[arg] aplicado sobre una función de más de un argumento crea una proyección (aplicación parcial)

Podemos dar nombre a los argumentos, pero los nombres implícitos son x, y, z

{y-x x bin y}[*+60(|+\)\1 0]declara una lambda con args x, y con proyección parcial (arg x es una serie de Fibonacci, calcula como * + 60 (| +) \ 1 0). x representa los valores de Fibonacci, yy el número a procesar. La búsqueda binaria (bin) se usa para ubicar el índice del mayor número de Fibonacci <= y ( x bin y) y restar el valor correspondiente de x.

Para calcular el producto a partir de resultados parciales, los invertimos y calculamos la diferencia de cada par ( -':|), soltamos el primero ( 1_porque es 0) y lo multiplicamos ( */).

Si estamos interesados ​​en la suma acumulada, el código es el mismo, pero con en +/lugar de */. También podemos usar cualquier otro operador diadic en lugar de + o *

Sobre la eficiencia de ejecución

Sé que en este concurso la eficiencia no es un problema. Pero en este problema podemos variar desde el costo lineal hasta el costo exponencial, así que tengo curiosidad al respecto.

Desarrollé una segunda versión (48 bytes de longitud sin incluir comentarios) y repetí la batería de casos de prueba 1000 veces en ambas versiones.

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

el tiempo de ejecución es: versión original 0'212 seg, nueva versión 0'037 seg

La versión original calcula la serie fibbonaci una vez por aplicación de función; La nueva versión calcula Fibonacci solo uno.

En ambos casos, el cálculo de la serie de Fibonacci utiliza la recursión de la cola

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.