Fibonacci-Faktorisierung


21

Fibonacci-Zahlen

Fibonacci - Zahlen beginnen mit f(1) = 1und f(2) = 1(etwas enthält , f(0) = 0aber dies ist auf diese Herausforderung irrelevant. Dann wird für n > 2, f(n) = f(n-1) + f(n-2).

Die Herausforderung

Ihre Aufgabe ist es, die n-te positive Zahl zu finden und auszugeben, die als Produkte von Fibonacci-Zahlen ausgedrückt werden kann. Sie können wählen, ob der Index 0 oder 1 sein soll, je nachdem, was für Sie am besten geeignet ist. Dies müssen Sie jedoch in Ihrer Antwort angeben.

Außerdem muss Ihre Antwort die 100. Amtszeit in angemessener Zeit berechnen.

Testfälle

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

Verweise


Im Testfall, warum sind einige von ihnen n = Ergebnis, während für 7 und höher sie nicht gleich sind. Vielleicht verstehe ich die Frage nicht. Aber ich will nur überprüfen
george

1
7kann nicht als Produkt von Fibonacci-Zahlen ausgedrückt werden. Daher ist die 1erste erforderliche Zahl 1, die 2zweite ist 2, ..., die 6dritte ist 6, aber die 7dritte ist 8.
Undichte Nonne

Ah, das macht natürlich Sinn
George

Solltest du alle Möglichkeiten drucken, um eine Nummer zu machen. Zum Beispiel hat 16 zwei Möglichkeiten, oder können Sie einfach eine ausgeben?
George

3
@george Ich glaube das " corresponding product" dient nur zur Verdeutlichung. Ihr Code muss nur das " result" ausgeben .
Trichoplax

Antworten:


6

Jelly , 26 24 23 21 Bytes

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

Probieren Sie es online!

Wie es funktioniert

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
Wie komplex ist dieser Algorithmus in Bezug auf die Eingabe?
Undichte Nonne

Auf jeden Fall ist es sehr schnell! Weniger als 2 Sekunden für die 100. Amtszeit
Luis Mendo

@LeakyNun Ich habe keine Ahnung, wie ich das berechnen soll, aber da die Eingabe 400 32-mal länger dauert als die Eingabe 100, würde ich sagen, dass sie exponentiell ist. Fasst 100 jedoch mühelos an.
Dennis

1
Nun, nur Sie wissen, was Ihr Algorithmus ist ...
Undichte Nonne

Ich habe es viel schneller gemacht, indem ich die Fibonacci-Sequenz nicht für jede getestete Zahl neu berechnet habe. Ich werde eine Erklärung hinzufügen, sobald ich mit dem Golfen fertig bin.
Dennis

5

Julia, 79 Bytes

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

Probieren Sie es online!

Hintergrund

In Advanced Problems and Solutions ist H-187: Fibonacci ein Quadrat , wie der Antragsteller zeigt

Fibonacci / Lucas Identität

Dabei bezeichnet L n die n- te Lucas-Zahl und umgekehrt, wenn

gegenteilige Fibonacci / Lucas Identität

dann ist n eine Fibonacci-Zahl und m ist eine Lucas-Zahl.

Wie es funktioniert

Wir definieren den binären Operator <|für unsere Zwecke. Es ist in neueren Versionen von Julia nicht definiert, wird jedoch vom Parser weiterhin als Operator erkannt.

Bei Aufruf mit nur einem Argument ( n ) wird k als 1<| initialisiert . Während n positiv ist, subtrahiert es ! K ( 1, wenn k ein Produkt von Fibonacci-Zahlen ist, 0, wenn nicht) von n und ruft sich selbst rekursiv auf und erhöht k um 1 . Sobald n 0 erreicht , wurde die gewünschte Menge an Produkten gefunden, und es wird der vorherige Wert von k zurückgegeben , dh ~ -k = k - 1 .<|

Der !als Test für Fibonacci- Zahlenprodukte neu definierte unäre Operator erfüllt seine Aufgabe wie folgt.

  • Wenn k = 1 ist , ist k ein Produkt von Fibonacci-Zahlen. In diesem Fall erhöhen wir den Rückgabewert von any(...)auf die Potenz ~ -k = k - 1 = 0 , sodass das Ergebnis 1 ist .

  • Wenn k> 1 ist , ist das Ergebnis der Wert von any(....), der genau dann true√(5i^2+[4,-4])%1∋k%i<!(k÷i) zurückgibt, wenn das Prädikat für eine ganze Zahl i true zurückgibt , sodass 2 ≤ i ≤ k ist .

    Die verketteten Bedingungen im Prädikat gelten, wenn sie k%izu gehören √(5i^2+[4,-4])%1und k%ikleiner als sind !(k÷i).

    • √(5i^2+[4,-4])%1Nimmt die Quadratwurzel von 5i 2 + 4 und 5i 2 - 4 und berechnet ihre Reste modulo 1 . Jeder Modul ist 0, wenn die entsprechende Zahl ein perfektes Quadrat ist, und eine positive Zahl, die ansonsten kleiner als 1 ist .

      Da k%ieine ganze Zahl zurückgegeben wird, kann sie nur dann zum Array von Modulen gehören, wenn k% i = 0 ist (dh k ist durch i teilbar ) und mindestens eines von 5i 2 + 4 und 5i 2 - 4 ein perfektes Quadrat ist (dh Ich bin eine Fibonacci-Zahl.

    • !(k÷i)Ruft rekursiv 1 mit dem Argument k ÷ i (Ganzzahldivision) auf, das genau dann größer als 0 ist, wenn k ÷ i ein Produkt von Fibonacci-Zahlen ist.

Durch Induktion ! hat die gewünschte Eigenschaft.


5

Python, 90 Bytes

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)

Die Hauptfunktion ggibt das kFibonacci-Produkt 1-indiziert aus. Es rechnet g(100)wie 315fast augenblicklich. Dies gilt auch für ein allgemeines rekursives Rezept, bei dem nnach kInstanzen gesucht wird , die die Funktion erfüllen f. Jede dieser Instanzen senkt die erforderliche Anzahl, kbis sie erreicht ist 0.

Die Hilfsfunktion ftestet eine Zahl als Fibonacci-Produkt. Es generiert rekursiv die Fibonacci-Zahlen in seinen optionalen Argumenten aund b. Es gibt "Ja" aus, wenn eine der folgenden Bedingungen erfüllt ist:

  • n<2. Dies impliziert n==1, das triviale Produkt)
  • n%a<f(n/a). Dies erfordert n%a==0und f(n/a)==True, dh das nist ein Vielfaches der Fibonacci-Zahl a, und das Entfernen dieses Faktors ergibt aimmer noch ein Fibonacci-Produkt.
  • n-a>0<f(n,b,a+b)äquivalent zu n>a and f(n,b,a+b). Überprüft, ob die aktuell getestete Fibonacci-Zahl mindestens so ngroß ist und ob eine größere Fibonacci-Zahl funktioniert. Vielen Dank an Dennis für das Speichern von 2 Bytes mithilfe des Ungleichheitskurzschlusses anstelle von and.

Die Funktion gkann ein Byte kürzer sein als

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

wenn g(k)es höchstens immer ist k*k, was ich nicht sicher bin, ist asymptotisch wahr. Eine Schranke 2**kreicht aus, g(100)dauert dann aber zu lange. Vielleicht kann stattdessen das rekursive von gin durchgeführt werden f.


Nach dieser Tabelle bei OEIS, g(k)überschreitet k*kwann k = 47000und oben.
isaacg

2

Perl 6 ,  95  93 Bytes

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

(0 basierter Index)

Prüfung:

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

Erläuterung:

{
  (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 Bytes

Vielen Dank an @Dennis für -22 Bytes

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)

Nimmt Eingaben von STDIN und druckt auf STDOUT. Dies ist einindexiert. Die Berechnung des 100. Terms dauert ungefähr eine Zehntelsekunde.

Wie es funktioniert

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

Probieren Sie es auf Ideone


2

Python 2, 120 107 Bytes

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

Teste es auf Ideone .

Wie es funktioniert

Wir initialisieren F als Tupel (2, 3) (die ersten beiden Fibonacci-Zahlen größer als 1 ), k als 0 und n als Ganzzahl, die aus STDIN gelesen wird.

Während n positiv ist, machen wir Folgendes:

  • Hänge die nächste Fibonacci-Zahl, berechnet als F [k] + F [-1] , dh die Summe der letzten beiden Elemente von F an das Tupel F an .

  • Inkrement k .

  • Subtrahiere g (k) von n .

g gibt genau dann 1 zurück, wenn k ein Produkt von Fibonacci-Zahlen ist. Wenn n also 0 erreicht , ist k die n- te Fibonacci-Zahl und wir geben sie an STDOUT aus.

g erreicht seinen Zweck wie folgt.

  • Wenn k ist 1 , ist es ein Produkt der Fibonacci - Zahlen, und 1/kstellt sicher , dass wir zurückkommen 1 .

  • Wenn k größer als 1 ist , rufen wir g(k/i)rekursiv für alle Fibonacci-Zahlen i in F auf .

    g(k/i)testet rekursiv, ob k / i ein Fibonacci-Zahlenprodukt ist. Wenn g(k/i)Returns 1 und i aufteilt k gleichmäßig, k% i = 0 und der Zustand k%i<g(k/i)hält, so g wird wieder 1 , wenn und nur wenn es eine Fibonacci - Zahl , die so ist , dass k das Produkt aus der Fibonacci - Zahl , und ein weiteres Produkt der Fibonacci - Zahlen.


1

JavaScript (ES6), 136

Auf diese Weise ist das Golfen ziemlich langsam, da ich auf meinem PC Term 100 in ungefähr 8 Sekunden berechnet habe.

(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')

Weniger Golf und auch schneller (Ausweichen 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
}

Prüfung

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 Bytes

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

Sehr faul, unendlich viel!

Möglicherweise nicht der kurze Weg, aber ich musste diesen Ansatz ausprobieren, eine Verallgemeinerung einer ziemlich bekannten Methode, um die Liste der Hamming-Zahlen zu berechnen. fist die Liste der Fibonacci-Zahlen, die mit 2 beginnt. Der Kürze halber sei ein lol (Liste von Listen) eine unendliche Liste von geordneten unendlichen Listen, geordnet nach ihren ersten Elementen. mist eine Funktion, um ein lol zusammenzuführen und Duplikate zu entfernen. Es werden zwei Infix-Hilfsfunktionen verwendet.?fügt eine unendliche sortierte Liste in ein lol ein. #Entfernt einen Wert aus einem lol, der als Kopf der ersten Liste erscheinen kann, und fügt die verbleibende Liste mit wieder ein ?.

Schließlich list die Liste der Zahlen, die Produkte von Fibonacci-Zahlen sind, definiert als 1, gefolgt von der Zusammenführung aller durch Multiplikation erhaltenen Listenl mit einer Fibonacci-Zahl erhalten werden. Die letzte Zeile gibt die erforderliche Funktion an (wie üblich, ohne sie an einen Namen zu binden, kopieren Sie sie also nicht so wie sie ist), indem Sie !!in die Liste indexieren, wodurch die Funktion 0-indexiert wird.

Es ist kein Problem, die 100. oder 100.000. Zahl zu berechnen.


1

Schale , 13 Bytes

Beachten Sie, dass Husk neuer als diese Herausforderung ist. Es und die nützlichste Funktion für diesen Golf ( Ξ) wurden jedoch nicht unter Berücksichtigung dieser Herausforderung erstellt.

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

Probieren Sie es online!

Effizientere Version für 14 Bytes:

Probieren Sie es 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

Teste es auf Ideone .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.