Fibonacci Faktoringi


21

Fibonacci Sayıları

Fibonacci Sayıları ile başlayan f(1) = 1ve f(2) = 1(bazı içerir f(0) = 0ama bu bu meydan okumaya önemsizdir. Sonra için n > 2, f(n) = f(n-1) + f(n-2).

Meydan okuma

Göreviniz n, Fibonacci sayılarının ürünü olarak ifade edilebilecek pozitif sayıyı bulmak ve çıktısını almaktır. Hangisi size daha uygunsa, 0 veya 1 dizin oluşturmayı seçebilirsiniz, ancak bunu cevabınızda belirtmelisiniz.

Ayrıca, cevabınız 100. terimi makul bir sürede hesaplamalıdır.

testcases

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

Referanslar


Test durumunda neden bazıları n = sonuçtur, oysa 7 ve üstü için eşit değildir. Belki de soruyu anlamıyorum. Ama ben sadece kontrol etmek istiyorum
George

1
7Fibonacci sayılarının ürünü olarak ifade edilemez. Bu nedenle, 1st gerekli sayıdır 1, 2nd olduğunu 2, ..., 6inci olduğunu 6, ancak 7th 8.
Sızdıran Rahibe

Ah, elbette, bu mantıklı
george 11

Numara oluştururken tüm yolları yazdırmanız gerekir. Mesela 16'nın iki yolu var ya da sadece bir tane çıkartabilir misiniz?
george

3
@george Ben " corresponding product" sadece açıklama için olduğuna inanıyorum . Kodunuzun yalnızca " result" yazması gerekir .
trichoplax

Yanıtlar:


6

Jöle , 26 24 23 21 bayt

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

Çevrimiçi deneyin!

Nasıl çalışır

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
Girdi açısından bu algoritmanın karmaşıklığı nedir?
Sızdıran Rahibe,

Her durumda, çok hızlı! 100. dönem için 2 saniyeden az
Luis Mendo

@LeakyNun Bunu nasıl hesaplayacağımı bilemiyorum, ancak girdi 400'ün girdi 100'den 32 kat daha uzun sürdüğünü görünce, üstel olduğunu söyleyebilirim. Yine de kolaylıkla 100 işliyor.
Dennis,

1
Pekala, algoritmanızın ne olduğunu sadece siz biliyorsunuz ...
Leaky Nun

Test edilen her numara için Fibonacci dizisini yeniden hesaplayarak çok daha hızlı hale getirmeyi başardım. Golf biter bitmez bir açıklama ekleyeceğim.
Dennis

5

Julia, 79 bayt

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

Çevrimiçi deneyin!

Arka fon

In Gelişmiş Sorunlar ve Çözümleri, H-187: Fibonacci bir karedir , teklifi getiren gösterileri olduğunu

Fibonacci / Lucas kimliği

burada L , n temsil eder n inci Lucas numarası , ve - diğer taraftan - eğer

sohbet etmek Fibonacci / Lucas kimliği

o zaman n bir Fibonacci sayısıdır ve m bir Lucas sayısıdır.

Nasıl çalışır

İkili operatörü <|amaçlarımız için tanımlarız . Julia'nın son sürümlerinde tanımlanmamıştır, ancak hala çözümleyici tarafından bir operatör olarak tanınır.

Yalnızca bir argümanla ( n ) çağrıldığında , k'yi 1 olarak <|başlatır . İken n pozitif, o çıkarır ! K ( 1 eğer k Fibonacci sayıları, bir ürünüdür 0 dan değilse) n ve yinelemeli artışlarla, kendisini çağıran k tarafından 1 . Bir kez n ulaşır 0 , ürünlerin arzu edilen miktarı, bulunan çok edilmiştir getirileri önceki değer k , yani ~ k = k - 1 .<|

!Fibonacci sayı ürünleri için bir test olarak yeniden tanımlanmış unary operatörü görevini aşağıdaki şekilde yerine getirmektedir.

  • Eğer k = 1 ise , k Fibonacci sayıları ürünüdür. Bu durumda, ~ -k = k - 1 = 0any(...) gücünün dönüş değerini yükseltiriz , böylece sonuç 1 olur .

  • Eğer k> 1 , sonuç değeri olacaktır any(....)dönecektir, gerçek yüklem ancak ve ancak √(5i^2+[4,-4])%1∋k%i<!(k÷i)döner gerçek bazı tamsayı için ben öyle ki 2 ≤ i k ≤ .

    Belirlemedeki zincirleme koşullar, k%iait √(5i^2+[4,-4])%1ve k%iondan küçük olması durumunda geçerlidir !(k÷i).

    • √(5i^2+[4,-4])%15i 2 + 4 ve 5i 2 - 4'ün karekökünü alır ve artıkları modulo 1 'i hesaplar . Her bir modül bir 0 karşılık gelen sayı, pozitif bir sayı daha mükemmel bir kare ise ve 1 , aksi.

      Bu yana k%iise geri dönüş bir tamsayıdır, sadece modüllerinin dizisine aittir olabilir K% i = 0 (yani, k bölünemeyen i ve en az bir adet arasında) 5i 2 + 4 ve 5i 2 - 4 mükemmel bir kare (yani, Ben bir Fibonacci numarasıdır).

    • !(k÷i)art arda 1'i k ÷ i (tamsayı bölme) argümanıyla çağırır ; bu, eğer k ÷ i Fibonacci sayılarının bir ürünü ise 0'dan büyük olacaktır .

İndüksiyonla ! istenen özelliğe sahiptir.


5

Python, 90 bayt

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)

Ana fonksiyonu gverir kFibonacci ürün inci, 1-endekslendi. Neredeyse anında g(100)olduğu gibi hesaplar 315. Fonksiyonu sağlayan örnekleri narayan sayıları sayan genel bir özyinelemeli tarifi ile devam ediyor . Bu tür bir örnek, ulaşana kadar gereken sayıyı düşürür .kfk0

Yardımcı fonksiyon f, bir Fibonacci ürünü olmak için bir sayıyı test eder. İsteğe bağlı argümanlarında Fibonacci sayılarını özyinelemeli olarak üretir ave b. Aşağıdakilerden herhangi biri doğruysa "evet" yazar:

  • n<2. Bu n==1önemsiz ürün anlamına gelir )
  • n%a<f(n/a). Bu gerektirir n%a==0ve f(n/a)==True, yani bu nFibonacci sayısının bir katıdır ave bu ahala bu faktörün kaldırılması bir Fibonacci ürünü verir.
  • n-a>0<f(n,b,a+b)eşdeğerdir n>a and f(n,b,a+b). Test edilen mevcut Fibonacci sayısının en azından olmadığını nve bazı Fibonacci sayısının çalıştığını kontrol eder. Dennis'e 2 tasarruf baytı için yerine kısa devre eşitsizliğini kullanarak and.

İşlev gbir bayt kadar kısa olabilir.

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

eğer g(k)her zaman en fazla ise k*k, emin değilim ki asimptotik olarak doğru. Bir sınır 2**kyeterli, ama sonra g(100)çok uzun sürüyor. Belki bunun yerine özyinelemeli gyapılabilir f.


OEIS'teki bu tabloya göre , ne zaman ve yukarısında g(k)aşıyor . k*kk = 47000
isaacg

2

Perl 6 ,  95  93 bayt

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

(0 tabanlı dizin)

Ölçek:

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

Açıklama:

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

-22 bayt için @Dennis sayesinde

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)

STDIN'den girdi alır ve STDOUT'a yazdırır. Bu bir dizinli. 100. terimi hesaplamak kabaca saniyenin onda birini alır.

Nasıl çalışır

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

Ideone'da dene


2

Python 2, 120 107 bayt

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

İdeone üzerinde test et .

Nasıl çalışır

Bu başlatma F başlığın olarak (2, 3) (daha önce iki Fibonacci sayısı ne kadar büyükse , 1 ), k olarak 0 ve n, bir tam sayı STDIN'den okumak.

N pozitif olsa da , aşağıdakileri yaparız:

  • Ekleme olarak hesaplanan bir sonraki Fibonacci sayı, F [k] + F [-1] , yani, son iki elemanlarının toplamı F tuplea F .

  • Artış k .

  • G (k) 'yi n'den çıkarın .

g döndüren 1 ve ancak eğer k Fibonacci sayıları bir ürünü, bu nedenle bir kez olduğu n ulaşır 0 , k ise n inci Fibonacci sayı ve STDOUT yazdırmak.

g amacına aşağıdaki şekilde ulaşır.

  • Eğer k ise 1 , bu Fibonacci sayıları bir ürünüdür ve 1/kemin biz dönmek yapar 1 .

  • Eğer k büyüktür 1 , dediğimiz g(k/i)tüm Fibonacci sayıları için yinelemeli i içinde F .

    g(k/i)K / i'nin bir Fibonacci numarası ürünü olup olmadığını tekrar tekrar test eder . Eğer g(k/i)döner 1 ve I böler k eşit, k% i, 0 = ve durumu k%i<g(k/i)tutan, böylece gr döndürür 1 olacak şekilde bir Fibonacci sayı olduğu, ancak ve ancak k ürünüdür Fibonacci sayı ve Fibonacci numaralarının başka bir ürün.


1

JavaScript (ES6), 136

Bu şekilde golf oyunu oldukça yavaş, bilgisayarımdaki terim yaklaşık 8 saniyede.

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

Daha az golf oynadı ve daha hızlı (kaçınarak 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
}

Ölçek

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 bayt

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

Çok tembel, çok sonsuz!

Muhtemelen kısa yol değil, fakat bu yaklaşımı denemek zorunda kaldım, hamming sayılarının listesini hesaplamak için oldukça iyi bilinen bir yöntemin genelleştirmesi. f2'den başlayan fibonacci sayıları listesidir. Kısalık için, bir lol'in (listelerin listesi), ilk elemanları tarafından sıralanan, sıralı sonsuz listelerin sonsuz bir listesi olduğunu söyleyelim. mçiftleri kaldırarak bir lol'i birleştirme işlevidir. İki infix yardımcı fonksiyonunu kullanır. ?bir lol içine sonsuz sıralanmış bir liste ekler. #ilk listenin başı olarak görünebilecek bir lol'den bir değeri siler, kalan listeyi yeniden yerleştirir ?.

Son olarak, l1 olarak tanımlanan fibonacci sayılarının ürünleri olan sayıların listesi, ardından lbir fibonacci sayısı ile çarpılarak elde edilen tüm listelerin birleştirilmesidir . Son satır, gerekli işlevi (her zamanki gibi bir ada bağlamadan, bu yüzden olduğu gibi kopyalamayın) !!listeye dizine sokarak, işlevi 0 dizinli hale getirir.

100 veya 100,000'inci sayıyı hesaplamakta sorun yoktur.



0

Python 2, 129 128 125 123 121 bayt

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

İdeone üzerinde test et .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.