Fibonacci Toplamı Olarak Sayı Yazma


9

Fibonacci dizisini şu şekilde tanımlayalım:

F(1) = 1

F(2) = 2

F(n) = F(n - 2) + F(n - 1)

Bu yüzden sonsuz diziye sahibiz 1,2,3,5,8,13,... Herhangi bir pozitif tamsayının bazı Fibonacci sayılarının toplamı olarak yazılabileceği iyi bilinmektedir. Tek uyarı, bu toplamın benzersiz olmayabilir. Fibonacci sayılarının toplamı olarak bir sayı yazmanın her zaman en az bir yolu vardır, ancak çok daha fazlası olabilir.

Zorluğunuz, stdin'i kullanarak bir ile bir milyon arasında pozitif bir tamsayı alan ve daha sonra girdiyi toplayan Fibonacci sayılarının tüm olası özetlerini kullanarak çıktı veren tam bir program yazmaktır. Özetle, Fibonacci sayıları tekrarlanmamalıdır ve sayıyı içerir 1. Herhangi bir özette, varsa 1, sadece bir kez mevcut olmalıdır, çünkü yukarıdaki dizinin tanımında 1sadece bir kez görünür. Yalnızca terim içeren toplamlar geçerlidir, bu nedenle giriş numarası bir Fibonacci numarasıysa, sayının kendisi geçerli bir toplamdır ve yazdırılmalıdır. Birden fazla toplam varsa, herhangi iki toplam arasında aralarını kolayca ayırt edebilmek için boş bir satır olmalıdır.

İşte bazı örnekler.

./myfib 1
1

Böyle bir miktar var ve sadece bir terimi var, bu yüzden yazdırılan tek şey bu.

./myfib 2
2

Burada tekrarların 1+1geçerli bir tutar olmadığını unutmayın 1.

./myfib 3
1+2

3

İki toplam ve ikisi de aralarında boş bir çizgi ile yazdırılır.

./myfib 10
2+8

2+3+5

./myfib 100
3+8+89

1+2+8+89

3+8+34+55

1+2+3+5+89

1+2+8+34+55

3+8+13+21+55

1+2+3+5+34+55

1+2+8+13+21+55

1+2+3+5+13+21+55

Gerçek kod golf. Herhangi bir dilde en kısa kod kazanır. Lütfen kodunuzu bazı test durumlarıyla birlikte gönderin (yukarıda verdiğim kodun yanı sıra). Bağlar söz konusu olduğunda, en az iki hafta ve muhtemelen daha uzun süre bekledikten sonra en yüksek upvotes'a sahip olanı seçiyorum. Bu yüzden topluluk lütfen istediğiniz çözümleri değerlendirmekten çekinmeyin. Kodun akıllılığı / güzelliği, ilk kimin yayınladığından çok daha önemlidir.

Mutlu kodlama!


1
... Ben sadece bunu bruteforce için gidiyorum: P Bir cevap gönderirseniz, iyi performans beklemeyin :)
Kapı Tokmağı

Peki bu kod-golf değil en hızlı kod. :-D
Sabit Nokta

1
Ben yazdım ve aslında hızlı çalışır: P
Kapı Tokmağı

Oldukça kopya değil, ancak codegolf.stackexchange.com/q/2677/194
Peter Taylor

1
@shiona Belirtmediğim için en beğendiğinizi seçin. :-)
Sabit Nokta

Yanıtlar:


9

GolfScript, 54 karakter

~1.{3$)<}{.@+}/<[[]]{{+}+1$%+}@/\{~)+{+}*!}+,{'+'*n.}/

Çevrimiçi olarak test edin veya örneklere göz atın:

> 54
2+5+13+34

> 55
1+2+5+13+34

3+5+13+34

8+13+34

21+34

55

4

Yakut, 118 114 (dizi çıkış) veya 138 134 (doğru çıkış)

i=gets.to_i
a=[x=y=1]
a+=[y=x+x=y]until y>i
p (1..a.size).flat_map{|n|a.combination(n).select{|o|o.inject(:+)==i}}

Örnek çalışma:

c:\a\ruby>fibadd
100
[[3, 8, 89], [1, 2, 8, 89], [3, 8, 34, 55], [1, 2, 3, 5, 89], [1, 2, 8, 34, 55], [3, 8, 13, 21, 55], [1, 2, 3, 5, 34, 55], [1, 2, 8, 13, 21, 55], [1, 2, 3, 5, 13, 21, 55]]

Değişim getsiçin $*[0]komut satırı argümanları (isterseniz >fibadd 100), gerçi 1 karakter.

Doğru çıktı ile:

i=gets.to_i
a=[x=y=1]
a+=[y=x+x=y]until y>i
$><<(1..a.size).flat_map{|n|a.combination(n).select{|o|o.inject(:+)==i}}.map{|o|o*?+}*'

'

Örnek çalışmalar:

c:\a\ruby>fibadd
100
3+8+89

1+2+8+89

3+8+34+55

1+2+3+5+89

1+2+8+34+55

3+8+13+21+55

1+2+3+5+34+55

1+2+8+13+21+55

1+2+3+5+13+21+55
c:\a\ruby>fibadd
1000
13+987

5+8+987

13+377+610

2+3+8+987

5+8+377+610

13+144+233+610

2+3+8+377+610

5+8+144+233+610

13+55+89+233+610

2+3+8+144+233+610

5+8+55+89+233+610

13+21+34+89+233+610

2+3+8+55+89+233+610

5+8+21+34+89+233+610

2+3+8+21+34+89+233+610
c:\a\ruby>obfcaps
12804
2+5+21+233+1597+10946

2+5+8+13+233+1597+10946

2+5+21+89+144+1597+10946

2+5+21+233+610+987+10946

2+5+21+233+1597+4181+6765

2+5+8+13+89+144+1597+10946

2+5+8+13+233+610+987+10946

2+5+8+13+233+1597+4181+6765

2+5+21+34+55+144+1597+10946

2+5+21+89+144+610+987+10946

2+5+21+89+144+1597+4181+6765

2+5+21+233+610+987+4181+6765

2+5+8+13+34+55+144+1597+10946

2+5+8+13+89+144+610+987+10946

2+5+8+13+89+144+1597+4181+6765

2+5+8+13+233+610+987+4181+6765

2+5+21+34+55+144+610+987+10946

2+5+21+34+55+144+1597+4181+6765

2+5+21+89+144+233+377+987+10946

2+5+21+89+144+610+987+4181+6765

2+5+21+233+610+987+1597+2584+6765

2+5+8+13+34+55+144+610+987+10946

2+5+8+13+34+55+144+1597+4181+6765

2+5+8+13+89+144+233+377+987+10946

2+5+8+13+89+144+610+987+4181+6765

2+5+8+13+233+610+987+1597+2584+6765

2+5+21+34+55+144+233+377+987+10946

2+5+21+34+55+144+610+987+4181+6765

2+5+21+89+144+233+377+987+4181+6765

2+5+21+89+144+610+987+1597+2584+6765

2+5+8+13+34+55+144+233+377+987+10946

2+5+8+13+34+55+144+610+987+4181+6765

2+5+8+13+89+144+233+377+987+4181+6765

2+5+8+13+89+144+610+987+1597+2584+6765

2+5+21+34+55+144+233+377+987+4181+6765

2+5+21+34+55+144+610+987+1597+2584+6765

2+5+21+89+144+233+377+987+1597+2584+6765

2+5+8+13+34+55+144+233+377+987+4181+6765

2+5+8+13+34+55+144+610+987+1597+2584+6765

2+5+8+13+89+144+233+377+987+1597+2584+6765

2+5+21+34+55+144+233+377+987+1597+2584+6765

2+5+8+13+34+55+144+233+377+987+1597+2584+6765

Bu sonuncusu (12804) sadece 3 saniye sürdü!


4

Mathematica, 89 85 karakter

David Carraher sayesinde 85 karaktere kısaldı.

i=Input[];#~Row~"+"&/@Select[If[#>i,Subsets@{##},#0[#+#2,##]]&[2,1],Tr@#==i&]//Column

Mathematica'nın yerleşik bir işlevi vardır Fibonacci, ancak kullanmak istemiyorum.


Çok kompakt. Güzel.
Dr. belisarius

1
Toplamlar listesi olarak yazdırmanın sakıncası yoksa 76 karakter:i = Input[]; #~Row~"+" & /@ Select[If[# > i, Subsets@{##}, #0[# + #2, ##]] &[2, 1], Tr@# == i &]
DavidC

1
84 karakter:i = Input[]; #~Row~"+" & /@ Select[If[# > i, Subsets@{##}, #0[# + #2, ##]] &[2, 1], Tr@# == i &] // Column
DavidC

2

piton 206 181 karakter

import itertools as a
i,j,v,y=1,2,[],input()
while i<1000000:v,i,j=v+[i],j,i+j
for t in range(len(v)+1):
 for s in a.combinations(v,t):
  if sum(s)==y:print "+".join(map(str,s))+"\n"

Örnek Çalışma:

25
1+3+21

1+3+8+13

1000
13+987

5+8+987

13+377+610

2+3+8+987

5+8+377+610

13+144+233+610

2+3+8+377+610

5+8+144+233+610

13+55+89+233+610

2+3+8+144+233+610

5+8+55+89+233+610

13+21+34+89+233+610

2+3+8+55+89+233+610

5+8+21+34+89+233+610

2+3+8+21+34+89+233+610

Tüm bu ekstra alanlardan kurtulun.Kodu girintilemek için bir sekme veya boşluk karakteri kullanabilirsiniz. Ayrıca mümkün olduğunda döngü kodlarını tek bir satıra yazmak daha kısadırwhile i<1000000:v+=[i];i,j=j,i+j
Wasi

Bazı öneriler (Sadece cevabınızı intihal etmek ve kısaltılmış versiyonumu göndermek istemedim):, import itertools as ziki nokta üst üste işaretinden sonra yeni satırları kaldırın y=input(), x,y,vsatırla birlikte girin ve son ififadeden sonra fazladan alanı kaldırın .
SimonT

Önerilerinizi koda ekledim. Teşekkürler :)
batman

2

Scala, 171

def f(h:Int,n:Int):Stream[Int]=h#::f(n,h+n)
val x=readInt;(1 to x).flatMap(y=>f(1,2).takeWhile(_<=x).combinations(y).filter(_.sum==x)).foreach(z=>println(z.mkString("+")))

2

C #, 376 bayt

class A{IEnumerable<int>B(int a,int b){yield return a+b;foreach(var c in B(b,a+b))yield return c;}void C(int n){foreach(var j in B(0,1).Take(n).Aggregate(new[]{Enumerable.Empty<int>()}.AsEnumerable(),(a,b)=>a.Concat(a.Select(x=>x.Concat(new[]b})))).Where(s=>s.Sum()==n))Console.WriteLine(string.Join("+",j));}static void Main(){new A().C(int.Parse(Console.ReadLine()));}}

Ungolfed:

class A
{
    IEnumerable<int>B(int a,int b){yield return a+b;foreach(var c in B(b,a+b))yield return c;}
    void C(int n){foreach(var j in B(0,1).Take(n).Aggregate(new[]{Enumerable.Empty<int>()}.AsEnumerable(),(a,b)=>a.Concat(a.Select(x=>x.Concat(new[]{b})))).Where(s=>s.Sum()==n))Console.WriteLine(string.Join("+",j));}
    static void Main(){new A().C(int.Parse(Console.ReadLine()));}
}

Yöntem tüm (sonsuz) Fibonacci setini temsil eden Bbir döndürür IEnumerable. Bir sayı verildiğinde ikinci yöntem, nilk nFibonacci sayılarına (burada aşırı devir) bakar, tüm olası alt kümeleri (güç seti) bulur ve ardından toplamı tam olan alt kümelere süzer nve sonra yazdırır.


1

APL (75)

I←⎕⋄{⎕←⎕TC[2],1↓,'+',⍪⍵}¨S/⍨I=+/¨S←/∘F¨↓⍉(N⍴2)⊤⍳2*N←⍴F←{⍵,+/¯2↑⍵}⍣{I<⊃⌽⍺}⍳2

Çoğunlukla çıktı biçimi nedeniyle istediğimden daha az rekabetçi.

Çıktı:

⎕:
      100

 3 + 8 + 89 

 3 + 8 + 34 + 55 

 3 + 8 + 13 + 21 + 55 

 1 + 2 + 8 + 89 

 1 + 2 + 8 + 34 + 55 

 1 + 2 + 8 + 13 + 21 + 55 

 1 + 2 + 3 + 5 + 89 

 1 + 2 + 3 + 5 + 34 + 55 

 1 + 2 + 3 + 5 + 13 + 21 + 55 

Açıklama:

  • I←⎕: girişi oku, kaydet I.
  • ⍳2: listeden başlayarak 1 2,
  • {⍵,+/¯2↑⍵}: listeye son iki öğenin toplamını ekleyin,
  • ⍣{I<⊃⌽⍺}: until I, listenin son öğesinden daha küçüktür.
  • F←: Saklayın F(bunlardan Fibonacci sayılardır 1için I).
  • N←⍴F: fibonacci sayısı miktarını depolayın N.
  • ↓⍉(N⍴2)⊤⍳2*N: Numaraları almak 1için 2^Nbit olarak.
  • S←/∘F¨: Bunların her birini bir bit maskesi olarak kullanın F, saklayın S.
  • I=+/¨S: içindeki her alt liste Siçin toplamın eşit olup olmadığına bakın I.
  • S/⍨: bunları seçin S. (Şimdi tüm fibonacci sayılarının listelerine sahibiz I.)
  • {... : bunların her biri için:
    • ,'+',⍪⍵: +her sayının önüne a ekleyin ,
    • 1↓: ilk +geri çekilin,
    • ⎕TC[2]: ekstra bir satırsonu ekleyin,
    • ⎕←: ve çıktı.

1

Haskell - 127

Birçok yinelemeden sonra aşağıdaki kodla karşılaştım:

f=1:scanl(+)2f
main=getLine>>=putStr.a f "".read
a(f:g)s n|n==f=s++show f++"\n\n"|n<f=""|n>f=a g(s++show f++"+")(n-f)++a g s n

Hile yaparak ve her çıkış satırının önüne fazladan "0+" ekleyerek belki bir karakter kaydedebilirdim.

Önceki çözümü golf yapmaya çalışırken geldi başka bir sürümü (uzunluk 143) paylaşmak istiyorum. Operatörleri ve tuplesleri daha önce hiç bu kadar kötüye kullanmadım:

f=1:scanl(+)2f
main=getLine>>=(\x->putStr$f€("",read x))
o%p=o++show p;(f:g)€t@(s,n)|n==f=s%f++"\n\n"|n<f=""|n>f=g€(s%f++"+",n-f)++g€t

Test senaryoları, 256:

256
2+3+5+13+34+55+144

2+3+5+13+89+144

2+3+5+13+233

2+8+13+34+55+144

2+8+13+89+144

2+8+13+233

2+21+34+55+144

2+21+89+144

2+21+233

ve 1000:

1000
2+3+8+21+34+89+233+610

2+3+8+55+89+233+610

2+3+8+144+233+610

2+3+8+377+610

2+3+8+987

5+8+21+34+89+233+610

5+8+55+89+233+610

5+8+144+233+610

5+8+377+610

5+8+987

13+21+34+89+233+610

13+55+89+233+610

13+144+233+610

13+377+610

13+987

Birisi şu şeylere sahip olduğu için bazı verimlilik verileri:

% echo "12804" | time ./fibsum-golf > /dev/null
./fibsum-golf > /dev/null  0.09s user 0.00s system 96% cpu 0.100 total
% echo "128040" | time ./fibsum-golf > /dev/null
./fibsum-golf > /dev/null  2.60s user 0.01s system 99% cpu 2.609 total

0

05AB1E , 19 bayt (Rakip değil)

ÅFævy©O¹Qi®'+ý}})ê»

Çevrimiçi deneyin!

Verilen herhangi bir tutar için tüm olası toplamları hesaplar n. 1000 için örnek çıktı:

1+1+3+8+144+233+610
1+1+3+8+21+34+89+233+610
1+1+3+8+377+610
1+1+3+8+55+89+233+610
1+1+3+8+987
13+144+233+610
13+21+34+89+233+610
13+377+610
13+55+89+233+610
13+987
2+3+8+144+233+610
2+3+8+21+34+89+233+610
2+3+8+377+610
2+3+8+55+89+233+610
2+3+8+987
5+8+144+233+610
5+8+21+34+89+233+610
5+8+377+610
5+8+55+89+233+610
5+8+987
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.