Fattorizzazione di Fibonacci


21

Numeri di Fibonacci

I numeri di Fibonacci inizia con f(1) = 1e f(2) = 1(un po 'include f(0) = 0ma questo è irrilevante per questa sfida. Poi, per n > 2, f(n) = f(n-1) + f(n-2).

La sfida

Il tuo compito è quello di trovare e produrre il nnumero esimo positivo che può essere espresso come prodotto dei numeri di Fibonacci. Puoi scegliere di renderlo 0-indicizzato o 1-indicizzato, a seconda di come ti si addice meglio, ma devi specificarlo nella tua risposta.

Inoltre, la tua risposta deve calcolare il centesimo termine in un tempo ragionevole.

Casi test

n   result corresponding product (for reference)
1   1      1
2   2      2
3   3      3
4   4      2*2
5   5      5
6   6      2*3
7   8      2*2*2 or 8
8   9      3*3
9   10     2*5
10  12     2*2*3
11  13     13
12  15     3*5
13  16     2*2*2*2 or 2*8
14  18     2*3*3
15  20     2*2*5
16  21     21
17  24     2*2*2*3 or 3*8
18  25     5*5
19  26     2*13
20  27     3*3*3
100 315    3*5*21

Riferimenti


Nel caso di test, perché alcuni di essi sono n = risultato, mentre per 7 e oltre non sono uguali. Forse non capisco la domanda. Ma voglio solo controllare
George,

1
7non può essere espresso come il prodotto dei numeri di Fibonacci. Pertanto, il 1numero richiesto è 1, il n 2è 2, ..., il 6th è 6, ma il 7th è 8.
Leaky Nun,

Ah, certo, ha senso
George,

Dovresti stampare tutti i modi per creare un numero. Ad esempio, 16 ha due modi o puoi semplicemente produrne uno?
george,

3
@george Credo che il " corresponding product" sia solo per chiarimenti. Il tuo codice deve solo generare " result".
trichoplax,

Risposte:


6

Gelatina , 26 24 23 21 byte

ÆDf÷߀FðḊ¡
1ç#2+С1¤Ṫ

Provalo online!

Come funziona

1ç#2+С1¤Ṫ  Main link. Argument: n (integer)

        ¤   Combine the three links to the left into a niladic chain.
   2          Set the left argument and the return value to 2 (third positive
              Fibonacci number).
       1      Yield 1 (second positive Fibonacci number).
    +С       Compute the sum of the return value and right argument, replacing the
              return value with the sum and the right argument with the previous
              return value.
              Do this n times, collecting all return values in a list.
              This returns A, the first n Fibonacci numbers greater than 1.
1             Set the return value to 1.
 ç#           Call the helper link with left argument k = 1, 2, 3... and right
              argument A = [2, 3, 5...] until n of them return a truthy value.
              Collect the matches in a list.
           Ṫ  Tail; extract the last (n-th) match.


ÆDf÷߀FðḊ¡    Helper link. Left argument: k. Right argument: A

        Ḋ     Dequeue; yield r := [2, ..., k].
       ð ¡    If r in non-empty, execute the chain to the left. Return k otherwise.
ÆD              Yield the positive divisors of k.
   ÷            Divide k by all Fibonacci numbers in A.
  f             Filter; keep divisors that belong to k÷A, i.e., all divisors
                d for which k÷d belongs to A.
    ߀          Recursively call the helper link for each kept divisor d, with left
                argument d and right argument A.
      F         Flatten the result, yielding a non-empty array iff any of the
                recursive calls yielded a non-empty array or a number.
                If the left argument is 1, the helper link returns 1, so the
                array will be non-empty if the consecutive divisions by Fibonacci
                numbers eventually produced a 1.

2
Qual è la complessità di questo algoritmo, in termini di input?
Leaky Nun,

In ogni caso, è molto veloce! Meno di 2 secondi per il centesimo termine
Luis Mendo,

@LeakyNun Non ho idea di come calcolarlo, ma vedendo come l'ingresso 400 impiega 32 volte di più dell'ingresso 100, direi che è esponenziale. Gestisce 100 con facilità però.
Dennis,

1
Bene, solo tu sai qual è il tuo algoritmo ...
Leaky Nun,

Sono riuscito a renderlo molto più veloce non ricalcolando la sequenza di Fibonacci per ogni numero testato. Aggiungerò una spiegazione non appena avrò finito di giocare a golf.
Dennis,

5

Julia, 79 byte

!k=any(i->√(5i^2+[4,-4])%1k%i<!(k÷i),2:k)^~-k
<|(n,k=1)=n>0?n-!k<|-~k:~-k

Provalo online!

sfondo

In Advanced Problems and Solutions, H-187: Fibonacci è un quadrato , lo dimostra il proponente

Identità di Fibonacci / Lucas

dove L n denota il n ° numero di Lucas , e che - al contrario - se

conversare identità di Fibonacci / Lucas

allora n è un numero di Fibonacci e m è un numero di Lucas.

Come funziona

Definiamo l'operatore binario <|per i nostri scopi. Non è definito nelle recenti versioni di Julia, ma è ancora riconosciuto come operatore dal parser.

Quando viene chiamato con un solo argomento ( n ), <|inizializza k come 1 . Mentre n è positivo, sottrae ! K ( 1 se k è un prodotto dei numeri di Fibonacci, 0 se non) da n e si chiama ricorsivamente, incrementa k di 1 . Una volta che n raggiunge 0 , la quantità desiderata di prodotti è stata trovata, quindi <|restituisce il valore precedente di k , ovvero ~ -k = k - 1 .

L'operatore unario !, ridefinito come test per i prodotti numerici Fibonacci, svolge il suo compito come segue.

  • Se k = 1 , k è un prodotto dei numeri di Fibonacci. In questo caso, aumentiamo il valore di ritorno any(...)alla potenza ~ -k = k - 1 = 0 , quindi il risultato sarà 1 .

  • Se k> 1 , il risultato sarà il valore di any(....), che restituirà true se e solo se il predicato √(5i^2+[4,-4])%1∋k%i<!(k÷i)restituisce true per un numero intero i tale che 2 ≤ i ≤ k .

    Le condizioni concatenate nel predicato sono valide se k%iappartengono √(5i^2+[4,-4])%1e k%isono inferiori a !(k÷i).

    • √(5i^2+[4,-4])%1prende la radice quadrata di 5i 2 + 4 e 5i 2 - 4 e calcola i loro residui modulo 1 . Ogni modulo è 0 se il numero corrispondente è un quadrato perfetto e un numero positivo inferiore a 1 altrimenti.

      Poiché k%irestituisce un numero intero, può appartenere alla matrice di moduli solo se k% i = 0 (ovvero, k è divisibile per i ) e almeno uno tra 5i 2 + 4 e 5i 2 - 4 è un quadrato perfetto (ovvero, io è un numero di Fibonacci).

    • !(k÷i)chiama ricorsivamente 1 con argomento k ÷ i (divisione intera), che sarà maggiore di 0 se e solo se k ÷ i è un prodotto dei numeri di Fibonacci.

Per induzione ,! ha la proprietà desiderata.


5

Python, 90 byte

f=lambda n,a=2,b=3:n<2or n%a<f(n/a)or n-a>0<f(n,b,a+b)
g=lambda k,n=1:k and-~g(k-f(n),n+1)

La funzione principale ggenera il kprodotto Fibonacci, 1 indicizzato. Si calcola g(100)come 315quasi istantaneamente. Va così con una ricetta generale ricorsiva di contare i numeri alla nricerca di kistanze che soddisfano la funzione f. Ciascuna di queste istanze riduce il conteggio richiesto kfino a raggiungere 0.

La funzione ausiliaria fverifica un numero per essere un prodotto Fibonacci. Genera ricorsivamente i numeri di Fibonacci nei suoi argomenti opzionali ae b. Emette "sì" se si verifica una delle seguenti condizioni:

  • n<2. Ciò implica n==1, il prodotto banale)
  • n%a<f(n/a). Ciò richiede n%a==0e f(n/a)==True, cioè, nè un multiplo del numero di Fibonacci a, e la rimozione di questo fattore aproduce ancora un prodotto Fibonacci.
  • n-a>0<f(n,b,a+b), equivalente a n>a and f(n,b,a+b). Verifica che l'attuale numero di Fibonacci in fase di test non sia almeno ne che funzioni un numero maggiore di Fibonacci. Grazie a Dennis per aver salvato 2 byte usando il cortocircuito della disuguaglianza anziché and.

La funzione gpuò essere più corta di un byte come

lambda k:filter(f,range(k*k+1))[k]

se g(k)è sempre al massimo k*k, il che non sono sicuro che sia asintoticamente vero. Un limite è 2**ksufficiente, ma g(100)richiede troppo tempo. Forse invece si gpuò fare il ricorsivo di f.


Secondo questa tabella di OEIS, g(k)supera k*kquando k = 47000e oltre.
isaacg,

2

Perl 6 ,  95  93 byte

{(1..*).grep({$/=$_;map {->{$/%$_||($//=$_);$/}...*!%%$_;0},reverse 2,3,&[+]...*>$_;2>$/})[$_]}
{(1..*).grep({$/=$_;map {->{$/%$_||($//=$_);$/}...*%$_;0},reverse 2,3,&[+]...*>$_;2>$/})[$_]}

(Indice basato su 0)

Test:

my &fib-prod = {(1..*).grep({$/=$_;map {->{$/%$_||($//=$_);$/}...*%$_;0},reverse 2,3,&[+]...*>$_;2>$/})[$_]}

say fib-prod 0 ..^ 20;
# (1 2 3 4 5 6 8 9 10 12 13 15 16 18 20 21 24 25 26 27)
say time-this { say fib-prod 100 -1; };
# 315
# 1.05135779

sub time-this (&code) {
  my $start = now;
  code();
  now - $start;
}

Spiegazione:

{
  (1..*).grep(
    {
      $/ = $_; # copy the input ($_) to $/
      map { # map used just for side effect
        ->{
          $/ % $_    # if $/ is divisible by the current fib factor
        ||
          ($/ /= $_) # divide it out once
        ;
          # return the current value in $/
          $/
        }
        ... # repeat until that returns:
        * !%% $_ # something that is not divisible by the current fib factor
        ;0
      },
      # the possible fibonacci factors plus one, reversed
      # ( the extra is to save one byte )
      reverse 2,3,&[+] ... *>$_;

      # is the end result of factoring equal to 1
      # ( for the grep above )
      2 > $/
    }
  )[ $_ ] # get the value at 0-based index
}

2

Python 3, 175 170 148 byte

Grazie a @Dennis per -22 byte

j=x=int(input())
y=1,1
exec('y+=y[-2]+y[-1],;'*x)
i=c=0
while c<x:
    if j>=x:j=0;i+=1;t=i
    if t%y[~j]<1:t/=y[~j];j-=1
    if t<2:c+=1;j=x
    j+=1
print(i)

Riceve input da STDIN e stampa su STDOUT. Questo è uno indicizzato. Il calcolo del centesimo termine richiede circa un decimo di secondo.

Come funziona

j=x=int(input())                Get term number x from STDIN and set Fibonacci number index
                                j to x to force initialisation of j later 
y=1,1                           Initialise tuple y with start values for Fibonacci sequence
exec('y+=y[-2]+y[-1],;'*x)      Compute the Fibonacci sequence to x terms and store in y
i=c=0                           Initialise test number i and term counter c
while c<x:                      Loop until x th term is calculated
    if j>=x:j=0;i+=1;t=i        Initialise Fibonacci number index j, increment i and
                                initialise temp variable t for looping through all j for
                                some i. Executes during the first pass of the loop since
                                at this point, j=x
    if t%y[~j]<1:t/=y[~j];j-=1  Find t mod the j th largest Fibonacci number in y and if no
                                remainder, update t by dividing by this number.
                                Decrementing j means that after a later increment, no
                                change to j occurs, allowing for numbers that are 
                                divisible by the same Fibonacci number more than once by
                                testing again with the same j
    if t<2:c+=1;j=x             If repeated division by ever-smaller Fibonacci numbers
                                leaves 1, i must be a Fibonacci product and c is
                                incremented. Setting j equal to x causes j to be reset
                                to 0 during the next loop execution
    j+=1                        Increment j
print(i)                        i must now be the x th Fibonacci product. Print i to STDOUT

Provalo su Ideone


2

Python 2, 120 107 byte

g=lambda k:1/k+any(k%i==0<g(k/i)for i in F)
F=2,3;k=0;n=input()
while n:F+=F[k]+F[-1],;k+=1;n-=g(k)
print k

Provalo su Ideone .

Come funziona

Inizializziamo F come tupla (2, 3) (i primi due numeri di Fibonacci maggiori di 1 ), k come 0 e n come numero intero letto da STDIN.

Mentre n è positivo, facciamo quanto segue:

  • Aggiungere il seguente numero di Fibonacci, calcolato come F [k] + F [-1] , cioè, la somma degli ultimi due elementi di F alla tupla F .

  • Incremento k .

  • Sottrai g (k) da n .

g restituisce 1 se e solo se k è un prodotto di numeri di Fibonacci, quindi una volta n raggiunge 0 , k è il n esimo numero di Fibonacci e stamparlo STDOUT.

g raggiunge il suo scopo come segue.

  • Se k è 1 , è un prodotto dei numeri di Fibonacci e si 1/kassicura che restituiamo 1 .

  • Se k è maggiore di 1 , chiamiamo g(k/i)ricorsivamente per tutti i numeri di Fibonacci i in F .

    g(k/i)verifica ricorsivamente se k / i è un prodotto con numero di Fibonacci. Se g(k/i)restituisce 1 e i divide k in modo uniforme, k% i = 0 e la condizione k%i<g(k/i)vale, quindi g restituirà 1 se e solo se esiste un numero di Fibonacci tale che k è il prodotto di quel numero di Fibonacci e un altro prodotto dei numeri di Fibonacci.


1

JavaScript (ES6), 136

Abbastanza lento da golf in questo modo, calcolando il termine 100 in circa 8 secondi sul mio PC.

(n,F=i=>i>1?F(i-1)+F(i-2):i+1,K=(n,i=1,d,x)=>eval('for(;(d=F(i++))<=n&&!(x=!(n%d)&&K(n/d)););x||n<2'))=>eval('for(a=0;n;)K(++a)&&--n;a')

Meno golf e anche più veloce (evitando eval)

n=>{
  F=i=> i>1 ? F(i-1)+F(i-2) : i+1; // recursive calc Fibonacci number
  K=(n,i=1,d,x)=>{ // recursive check divisibility
    for(; (d=F(i++))<=n && !(x=!(n%d)&&K(n/d)); );
    return x||n<2
  };
  for(a=0; n; )
    K(++a) && --n;
  return a
}

Test

X=(n,F=i=>i>1?F(i-1)+F(i-2):i+1,K=(n,i=1,d,x)=>eval('for(;(d=F(i++))<=n&&!(x=!(n%d)&&K(n/d)););x||n<2'))=>eval('for(a=0;n;)K(++a)&&--n;a')

function test() {
  var i=+I.value
  O.textContent=X(i)
}

test()
<input id=I value=100 >
<button onclick="test()">Go</button><pre id=O></pre>


1

Haskell, 123 byte

f=2:scanl(+)3f
m((a:b):c)=a:m(b?(a#c))
v#((a:b):c)|v==a=b?(v#c)
_#l=l
y?(z:e)|y>z=z:y?e
a?b=a:b
l=1:m[[a*b|b<-l]|a<-f]
(l!!)

Molto pigro, molto infinito!

Forse non è il modo più breve, ma ho dovuto provare questo approccio, una generalizzazione di un metodo abbastanza noto per calcolare l'elenco dei numeri di martellamento. fè l'elenco di numeri di fibonacci a partire da 2. Per brevità, diciamo che un lol (elenco di elenchi) è un elenco infinito di elenchi infiniti ordinati, ordinati per i loro primi elementi. mè una funzione per unire un lol, rimuovendo i duplicati. Utilizza due funzioni helper infix. ?inserisce un elenco infinito in un lol. #rimuove un valore da un lol che può apparire come head dei primi elenchi, reinserendo l'elenco rimanente con ?.

Infine, lè l'elenco di numeri che sono prodotti di numeri di fibonacci, definito come 1 seguito dall'unione di tutte le liste ottenute moltiplicando lper un numero di fibonacci. L'ultima riga indica la funzione richiesta (come al solito senza associarla a un nome, quindi non copiarla così com'è) usando !!per indicizzare nella lista, il che rende la funzione indicizzata a 0.

Non vi è alcun problema nel calcolo del 100 o 100.000 numero.


1

Buccia , 13 byte

Nota che Husk è più recente di questa sfida. Tuttavia, questa e la funzione più utile per questo golf ( Ξ) non sono state create tenendo presente questa sfida.

S!!Ṡ¡ȯuΞIṪ*İf

Provalo online!

Versione più efficiente per 14 byte:

Provalo online!


0

Python 2, 129 128 125 123 121 byte

g=lambda k:1/k|any(abs(round(5**.5*i)**2-5*i*i)==4>k%i<g(k/i)for i in range(k+1))
f=lambda n,k=1:n and f(n-g(k),k+1)or~-k

Provalo su Ideone .

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.