Prodotti Fibonacci


13

Puoi scomporre un numero maggiore di 0 come somma unica di numeri di Fibonacci positivi. In questa domanda lo facciamo sottraendo ripetutamente il maggior numero possibile di Fibonacci positivo. Per esempio:

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

Ora chiamo un prodotto Fibonacci gli stessi elenchi di cui sopra, ma con l'aggiunta sostituita dalla moltiplicazione. Ad esempio f(100) = 89 * 8 * 3 = 2136,.

Scrivi un programma o una funzione che dato un numero intero positivo n restituisce il prodotto Fibonacci di quel numero.


Casi test:

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

6
L'affermazione non è del tutto corretta. Ad esempio 2può essere scomposto come -1 + 3. L'affermazione corretta del teorema di Zeckendorf è che un numero di Fibonacci positivo può essere scomposto in modo univoco come una somma di numeri di Fibonacci non consecutivi con indice positivo.
Peter Taylor,

1
@PeterTaylor Non considero i numeri negativi di Fibonacci parte della serie per questa domanda. Consecutivo o non importa solo quando vuoi gli indici, non ci preoccupiamo degli indici per questa domanda.
orlp,

1
Non sto dicendo che dovresti cambiare la domanda per supportare i numeri negativi di Fibonacci: sto dicendo che dovresti modificarla per essere espliciti sui presupposti che stai formulando.
Peter Taylor,

1
@orlp consecutivi o meno importa un po ', dal momento che due forme diverse darebbero due prodotti diversi. Hai già dichiarato il problema in un modo che già esclude implicitamente termini consecutivi di Fibonacci, quindi non c'è nulla di cui preoccuparsi lì.
Hobbs,

2
(in particolare: F (n) e F (n + 1) non possono apparire entrambi nell'output perché l'algoritmo garantisce che, prima di considerarli, il resto è già inferiore a F (n + 2) = F (n) + F (n + 1))
hobbs

Risposte:


5

Gelatina , 16 15 byte

Rf1+С¤ṪạµÐĿIAP

Non particolarmente veloce o adatto alla memoria, ma abbastanza efficiente per tutti i casi di test. Provalo online!

Come funziona

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.  

6
Sembra grande, Dennis.
orlp,

9

Python, 54 byte

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

Solo qualche buona vecchia ricorsione.


5

Perl, 69 63 + 4 ( -pl61flag) = 67 byte

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


La spiegazione dovrebbe menzionare che ottale 061è la codifica ASCII per il personaggio '1'. Bello hack da usare $\per stamparlo quasi gratis.
Peter Cordes,

2

JavaScript (ES6), 78 42 byte

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

Porta della risposta di @ Sp3000. Versione originale a 78 byte:

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 byte

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

Si aspetta che il numero di input sia presente nello stack all'avvio del programma.

Costruisce la sequenza di Fibonacci ( f0, f1, f2, ..., fn) sullo stack fino a quando non viene raggiunto un numero maggiore dell'input ( i). Quindi, con un prodotto ( p) inizializzato su 1...

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

Provalo online!


Bello! Ti suggerisco di pubblicare un link usando un compilatore online
Luis Mendo,


1

Pyth, 24 byte

W=-QeaYh.WgQeH,eZsZ1;*FY

Provalo online: dimostrazione o Test Suite

Spiegazione:

Q è assegnato con il numero di input.

La parte h.WgQeH,eZsZ1calcola il numero maggiore di Fibonacci, che è più piccolo o uguale aQ

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

Quindi Q = 10, se , genera i numeri / coppie:

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

Il resto del codice calcola la partizione e moltiplica i numeri insieme:

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

Ci sono ovviamente molte soluzioni più brevi (con tempi di esecuzione davvero cattivi), come *FhfqQsTyeM.u,eNsNQ1.


1

Haskell, 44 byte

Sì per la ricorsione reciproca:

(a&b)c|c<1=1|b>c=a*f(c-a)|d<-a+b=b&d$c
f=0&1
  • a è il precedente numero di Fibonacci
  • b è l'attuale numero di Fibonacci
  • c è l'input
  • f è la funzione desiderata

Meno golf:

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

1

In realtà, 22 byte

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

Provalo online!

Spiegazione:

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

In realtà ha una sua codifica? Conto 35 byte su 22 caratteri. mothereff.in/…
cat

1
@cat Proprio come sul serio, utilizza CP437.
Mego

1

Javascript (ES6) 134 106 92 byte

Grazie per @cat per aver individuato uno spazio.

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 versione non ottimizzata creata sul mio telefono, la metto giù una volta tornata a casa. Le idee sono benvenute


C'è uno spazio bianco superfluo. : P
gatto

1

INVIO , 44 byte

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

Try it here.

Lambda anonima sorprendentemente inefficiente che lascia il risultato su Stack2. Uso:

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

NOTA: ␌ e ␁ sono segnaposto per i rispettivi caratteri non stampabili: avanzamento modulo e inizio dell'intestazione .

Spiegazione

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

Conto 46 byte su 42 caratteri. Se RETURN utilizza una sorta di codifica speciale, dovrebbe essere di 42 byte su 42 caratteri, ma sembra essere unicode, quindi è 46.
cat

In realtà, mi sono appena reso conto che mi ero dimenticato di inserire alcuni non stampabili.
Mama Fun Roll

Avevo bisogno di un microscopio per dire cosa fossero, quindi mi sono collegato a loro per te. : D (non saprei dire se fosse SOH o BOM)
gatto

0

PHP, 119 byte

Il codice (racchiuso in due righe per leggibilità):

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 prima riga calcola nei $fnumeri di Fibonacci più piccoli di $n(l'argomento fornito nella riga di comando). La seconda riga calcola i fattori di Fibonacci (per sottrazione) e li moltiplica per calcolare il prodotto $o.

Prepara il codice con <?php(tecnicamente non parte del programma), inseriscilo in un file ( fibonacci-factors.php) quindi eseguilo come:

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

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

Il codice non salvato e la suite di test sono disponibili su Github .


0

Q, 47 byte

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

Test

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

leggilo come coppie (i, map (m, i)), dove m è la funzione di calcolo e i diversi argomenti

scrive

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

Spiegazione

n funtion\arg applica la funzione (funzione (funzione (... funzione (args))) n volte (usa internamente la ricorsione tal) e restituisce la sequenza dei risultati. Calcoliamo i primi 60 elementi delle serie fibonnaci come *+60(|+\)\1 0. In quel caso la funzione è ( | +): + \ applicato su una sequenza calcola somme parziali (ex + \ 1 2 3 è 1 3 6) e | inverte il seq. Quindi ogni 'iterazione' calcoliamo somme parziali dei due precedenti numeri di fibonacci e restituiamo il parziale somme invertite 60(|+\)\1 0genera sequenze 1 0, 1 1, 2 1, 3 2, 5 3, 8 5, 13 8, 21 13, ... *+applicate su questo risultato capovolgile (trasponi) e prende la prima. Il risultato è la sequenza 1 1 2 3 5 8 13 21 34 55 ..

(cond)function\args applica la funzione (funzione (.. funzione (args))) mentre cond true e restituisce la sequenza di risultati parziali

function[arg] applicato su una funzione di più di un argomento crea una proiezione (applicazione parziale)

Possiamo dare un nome agli arg, ma i nomi impliciti sono x, y, z

{y-x x bin y}[*+60(|+\)\1 0]dichiara un lambda con args x, y con proiezione parziale (arg x è una serie di fibonacci, calcola come * + 60 (| +) \ 1 0). x rappresentano i valori di fibonacci e y il numero da elaborare. La ricerca binaria (bin) viene utilizzata per individuare l'indice del numero maggiore di fibonacci <= y ( x bin y) e sottrarre il valore corrispondente di x.

Per calcolare il prodotto dai risultati parziali, li invertiamo e calcoliamo la differenza di ogni coppia ( -':|), rilasciamo il primo ( 1_perché è 0) e moltiplichiamo (*/ ).

Se siamo interessati alla somma accumulata, il codice è lo stesso, ma con +/invece di*/ . Possiamo anche usare qualsiasi altro operatore diadico invece di + o *

Informazioni sull'efficienza dell'esecuzione

So che in questo concorso l'efficienza non è un problema. Ma in questo problema possiamo variare dal costo lineare al costo esponenziale, quindi ne sono curioso.

Ho sviluppato una seconda versione (lunghezza 48 byte escluso il commento) e ripetuto test case batteria 1000 volte su entrambe le versioni.

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

il tempo di esecuzione è: versione originale 0'212 seg, nuova versione 0'037 seg

La versione originale calcola la serie fibbonaci una volta per applicazione di funzione; la nuova versione calcola fibonacci solo uno.

In entrambi i casi il calcolo della serie fibonacci utilizza la ricorsione della coda

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.