เขียนตัวเลขเป็นผลรวมฟีโบนักชี


9

ให้เรากำหนดลำดับฟีโบนักชีเป็น

F(1) = 1

F(2) = 2

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

ดังนั้นเราจึงมีลำดับไม่สิ้นสุด1,2,3,5,8,13,... เป็นที่ทราบกันดีว่าเลขจำนวนเต็มบวกใด ๆ สามารถเขียนเป็นผลรวมของตัวเลขฟีโบนักชีบางส่วนได้ ข้อแม้เดียวคือการรวมนี้อาจไม่ซ้ำกัน มีอย่างน้อยหนึ่งวิธีในการเขียนตัวเลขเป็นผลรวมของตัวเลขฟีโบนักชี แต่อาจมีอีกมากมาย

ความท้าทายของคุณคือการเขียนโปรแกรมที่สมบูรณ์ซึ่งใช้ stdin จะใช้จำนวนเต็มบวกระหว่างหนึ่งถึงหนึ่งล้านรวมแล้วเอาท์พุทโดยใช้ stdout การสรุปที่เป็นไปได้ทั้งหมดของหมายเลขฟีโบนักชีซึ่งรวมถึงอินพุต ในการสรุปหมายเลขฟีโบนัชชีต้องไม่ซ้ำและรวมถึงหมายเลข1นั้น ในการสรุปใด ๆ หาก1มีอยู่จะต้องแสดงเพียงครั้งเดียวเท่านั้นเนื่องจากในคำจำกัดความของลำดับข้างต้น1ปรากฏเพียงครั้งเดียว การสรุปที่มีคำศัพท์เพียงอย่างเดียวนั้นจะถูกต้องดังนั้นหากหมายเลขอินพุตคือหมายเลขฟีโบนักชีเองดังนั้นตัวเลขนั้นจึงเป็นผลรวมที่ถูกต้องและต้องพิมพ์ หากผลรวมหลายค่าระหว่างสองจำนวนใด ๆ จะต้องมีบรรทัดว่างเพื่อแยกความแตกต่างระหว่างพวกเขาได้อย่างง่ายดาย

นี่คือตัวอย่างบางส่วน

./myfib 1
1

มีเพียงผลรวมเดียวและมีคำศัพท์เพียงอย่างเดียวนั่นคือทั้งหมดที่พิมพ์ออกมา

./myfib 2
2

โปรดทราบว่านี่1+1ไม่ใช่ผลรวมที่ถูกต้องเพราะ1ซ้ำ

./myfib 3
1+2

3

สองจำนวนเงินและพวกเขาทั้งสองพิมพ์ด้วยบรรทัดว่างในระหว่าง

./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

รหัสที่แท้จริงกอล์ฟ รหัสที่สั้นที่สุดในทุกภาษาชนะ กรุณาโพสต์รหัสของคุณด้วยกรณีทดสอบ (นอกเหนือจากที่ฉันให้ไว้ข้างต้น) ในกรณีของความสัมพันธ์ฉันเลือกหนึ่งที่มี upvotes สูงสุดหลังจากรออย่างน้อยสองสัปดาห์และอาจนานกว่านั้น ดังนั้นชุมชนโปรดอย่าลังเลที่จะแก้ไขปัญหาใด ๆ ที่คุณต้องการ ความฉลาด / ความสวยงามของรหัสมีความสำคัญมากกว่าใครโพสต์ก่อน

การเข้ารหัสที่มีความสุข!


1
... ฉันแค่อยากจะตำหนิเรื่องนี้: P ถ้าฉันโพสต์คำตอบอย่าคาดหวังว่ามันจะทำงานได้ดี :)
Doorknob

มันคือ code-golf ไม่ใช่ code ที่เร็วที่สุด :-D
จุดคงที่

1
ฉันเขียนมันและมันก็ทำงานได้อย่างรวดเร็วจริง ๆ : P
Doorknob

ไม่ซ้ำกันมาก แต่เกี่ยวข้องอย่างใกล้ชิดกับcodegolf.stackexchange.com/q/2677/194
Peter Taylor

1
@shiona เนื่องจากฉันไม่ได้ระบุให้เลือกรายการโปรดของคุณ :-)
แก้ไขจุด

คำตอบ:



4

Ruby, 118 114 (เอาต์พุตอาร์เรย์) หรือ138 134 (เอาต์พุตที่ถูกต้อง)

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

วิ่งตัวอย่าง:

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

เปลี่ยนgetsเป็น$*[0]ถ้าคุณต้องการอาร์กิวเมนต์บรรทัดคำสั่ง ( >fibadd 100), อักขระ +1

ด้วยผลลัพธ์ที่ถูกต้อง:

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*?+}*'

'

ตัวอย่างการวิ่ง:

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

อันสุดท้าย (12804) ใช้เวลาประมาณ 3 วินาทีเท่านั้น!


4

Mathematica, 89 85 ตัวอักษร

ลดเหลือ 85 chars ด้วย David Carraher

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

Mathematica มีฟังก์ชั่นในตัวFibonacciแต่ฉันไม่ต้องการใช้


กะทัดรัดมาก ดี
ดร. เบลิซาเรียส

1
76 ตัวอักษรหากคุณไม่ทราบพิมพ์เป็นรายการของเงินก้อนนี้:i = Input[]; #~Row~"+" & /@ Select[If[# > i, Subsets@{##}, #0[# + #2, ##]] &[2, 1], Tr@# == i &]
DavidC

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

2

หลาม 206 181 ตัวอักษร

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"

เรียกใช้ตัวอย่าง:

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

กำจัดช่องว่างเหล่านั้นทั้งหมดคุณสามารถใช้หนึ่งแท็บหรือตัวอักษรเว้นวรรคเพื่อเยื้องรหัส นอกจากนี้ยังเขียนรหัสวงในบรรทัดเดียวเมื่อเป็นไปได้จะสั้นลงเช่นwhile i<1000000:v+=[i];i,j=j,i+j
Wasi

ข้อเสนอแนะบางอย่าง (ฉันไม่ต้องการเพียงลอกเลียนคำตอบของคุณและโพสต์ฉบับย่อของฉัน): import itertools as zลบ newlines after the colons ใส่เข้าไปy=input()ในx,y,vบรรทัดและลบช่องว่างเพิ่มเติมหลังจากifคำสั่งสุดท้าย
SimonT

ฉันได้รวมคำแนะนำของคุณไว้ในรหัสแล้ว ขอบคุณ :)
batman

2

สกาลา, 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 ไบต์

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

วิธีการBคืนค่าIEnumerableที่แสดงถึงชุด Fibonacci (ไม่ จำกัด ) ทั้งหมด วิธีที่สองให้ตัวเลขnดูที่nหมายเลข Fibonacci แรก(overkill ขนาดใหญ่ที่นี่) ค้นหาชุดย่อยที่เป็นไปได้ทั้งหมด (ชุดพลังงาน) แล้วกรองลงไปที่ชุดย่อยซึ่งผลรวมแน่นอนnแล้วพิมพ์ออกมา


1

APL (75)

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

การแข่งขันน้อยกว่าที่ฉันต้องการส่วนใหญ่เป็นเพราะรูปแบบผลลัพธ์

เอาท์พุท:

⎕:
      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 

คำอธิบาย:

  • I←⎕: Iอ่านเข้าจัดเก็บใน
  • ⍳2: เริ่มต้นด้วยรายการ1 2,
  • {⍵,+/¯2↑⍵}: เพิ่มผลรวมขององค์ประกอบสองรายการสุดท้ายลงในรายการ
  • ⍣{I<⊃⌽⍺}: จนกว่าIจะมีขนาดเล็กกว่าองค์ประกอบสุดท้ายของรายการ
  • F←: เก็บในF(เหล่านี้คือตัวเลขฟีโบนักชีจาก1ถึงI)
  • N←⍴F: เก็บข้อมูลจำนวนของตัวเลข fibonacci Nใน
  • ↓⍉(N⍴2)⊤⍳2*N: รับตัวเลขจาก1ถึง2^Nเป็นบิต
  • S←/∘F¨: ใช้แต่ละเหล่านี้เป็น bitmask ในร้านค้าในFS
  • I=+/¨S: สำหรับแต่ละรายการย่อยในดูว่าผลรวมของมันจะมีค่าเท่ากับSI
  • S/⍨: Sเลือกเหล่านี้จาก (ตอนนี้เรามีรายการหมายเลขฟีโบนักชีทั้งหมดที่รวมIอยู่)
  • {... : สำหรับแต่ละรายการเหล่านี้:
    • ,'+',⍪⍵: เพิ่ม a +ด้านหน้าของแต่ละหมายเลข
    • 1↓: +ถอยกลับก่อน
    • ⎕TC[2]: เพิ่มบรรทัดใหม่พิเศษ
    • ⎕←: และเอาท์พุท

1

Haskell - 127

หลังจากทำซ้ำหลายครั้งฉันลงเอยด้วยรหัสต่อไปนี้:

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

ฉันสามารถบันทึกตัวละครได้หนึ่งตัวโดยการโกงและเพิ่ม "0+" ด้านหน้าของบรรทัดเอาต์พุตทุกบรรทัด

ฉันต้องการแบ่งปันเวอร์ชันอื่น (ความยาว 143) ฉันมาด้วยขณะพยายามเล่นกอล์ฟโซลูชันก่อนหน้า ฉันไม่เคยทำร้ายผู้ประกอบการและทูเปิลมากขนาดนี้มาก่อน:

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

กรณีทดสอบ 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

และ 1,000:

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

ข้อมูลประสิทธิภาพบางอย่างเนื่องจากมีคนมีสิ่งนี้:

% 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 ไบต์ (ไม่แข่งขัน)

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

ลองออนไลน์!

nคำนวณจำนวนเงินที่เป็นไปได้ทั้งหมดสำหรับการใดก็ตาม ตัวอย่างเอาต์พุตสำหรับ 1,000:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.