Viết một số dưới dạng tổng số Fibonacci


9

Hãy để chúng tôi xác định chuỗi Fibonacci là

F(1) = 1

F(2) = 2

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

Vì vậy, chúng ta có chuỗi vô hạn 1,2,3,5,8,13,... Người ta biết rằng bất kỳ số nguyên dương nào cũng có thể được viết dưới dạng tổng của một số số Fibonacci. Nhắc nhở duy nhất là tổng kết này có thể không phải là duy nhất. Luôn có ít nhất một cách để viết một số dưới dạng tổng của các số Fibonacci nhưng có thể có nhiều số khác nữa.

Thử thách của bạn là viết một chương trình hoàn chỉnh, sử dụng stdin sẽ lấy một số nguyên dương từ một đến một triệu bao gồm, và sau đó xuất ra bằng cách sử dụng tất cả các phép tính tổng của các số Fibonacci có thể tổng hợp với đầu vào. Trong một tổng kết, các số Fibonacci không được lặp lại và bao gồm số đó 1. Trong bất kỳ tổng kết nào, nếu 1có mặt, nó chỉ phải hiện diện một lần vì trong định nghĩa của tôi về trình tự trên 1chỉ xuất hiện một lần. Các tóm tắt chỉ có thuật ngữ là hợp lệ, do đó, nếu số đầu vào là một số Fibonacci, thì chính số đó là một tổng hợp hợp lệ và phải được in. Nếu nhiều khoản tiền, thì giữa hai khoản tiền bất kỳ phải có một dòng trống để dễ dàng phân biệt giữa chúng.

Dưới đây là một số mẫu.

./myfib 1
1

Chỉ có một số tiền như vậy và nó chỉ có thời hạn nên đó là tất cả những gì được in.

./myfib 2
2

Lưu ý ở đây 1+1không phải là một khoản tiền hợp lệ vì 1lặp lại.

./myfib 3
1+2

3

Hai khoản tiền và cả hai đều được in với một dòng trống ở giữa.

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

Đúng mã golf. Mã ngắn nhất trong bất kỳ ngôn ngữ nào sẽ thắng. Vui lòng gửi mã của bạn với một số trường hợp thử nghiệm (ngoài trường hợp tôi đã đưa ra ở trên). Trong trường hợp quan hệ, tôi chọn một người có mức tăng cao nhất sau khi chờ ít nhất hai tuần và có thể lâu hơn. Vì vậy, cộng đồng xin vui lòng nâng cấp bất kỳ giải pháp nào bạn thích. Sự thông minh / vẻ đẹp của mã quan trọng hơn nhiều so với người đăng đầu tiên.

Chúc mừng mã hóa!


1
... Tôi sắp sửa phá vỡ điều này: P Nếu tôi đăng câu trả lời, đừng hy vọng nó sẽ hoạt động tốt :)
Doorknob

Vâng, đó là mã golf không phải mã nhanh nhất. :-D
Điểm cố định

1
Tôi đã viết nó và nó thực sự chạy rất nhanh: P
Doorknob

Không hoàn toàn trùng lặp, nhưng liên quan chặt chẽ với codegolf.stackexchange.com/q/2677/194
Peter Taylor

1
@shiona Vì tôi không chỉ định, hãy chọn mục yêu thích của bạn. :-)
Điểm cố định

Câu trả lời:


9

GolfScript, 54 ký tự

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

Kiểm tra trực tuyến hoặc xem qua các ví dụ:

> 54
2+5+13+34

> 55
1+2+5+13+34

3+5+13+34

8+13+34

21+34

55

4

Ruby, 118 114 (đầu ra mảng) hoặc 138 134 (đầu ra chính xác)

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

Chạy mẫu:

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

Thay đổi getsthành $*[0]nếu bạn muốn đối số dòng lệnh ( >fibadd 100), ký tự +1.

Với đầu ra chính xác:

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

'

Chạy mẫu:

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

Cái cuối cùng đó (12804) chỉ mất khoảng 3 giây!


4

Toán học, 89 85 ký tự

Rút ngắn xuống còn 85 ký tự nhờ David Carraher.

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

Mathematica có chức năng tích hợp Fibonacci, nhưng tôi không muốn sử dụng nó.


Rất nhỏ gọn. Đẹp.
Tiến sĩ belisarius

1
76 ký tự nếu bạn không ngại in như một danh sách các khoản tiền:i = Input[]; #~Row~"+" & /@ Select[If[# > i, Subsets@{##}, #0[# + #2, ##]] &[2, 1], Tr@# == i &]
DavidC

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

2

Con trăn 206 181 ký tự

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"

Chạy mẫu:

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

Loại bỏ tất cả các khoảng trắng thừa đó. Bạn có thể sử dụng một tab hoặc ký tự khoảng trắng để mã thụt lề. Đồng thời viết mã vòng lặp trong một dòng khi có thể ngắn hơn tức làwhile i<1000000:v+=[i];i,j=j,i+j
Wasi 23/12/13

Một số gợi ý (tôi không muốn chỉ đạo văn câu trả lời của bạn và đăng phiên bản rút gọn của tôi) : import itertools as z, xóa các dòng mới sau dấu hai chấm, đặt dòng y=input()vào x,y,vvà xóa khoảng trắng thừa sau ifcâu lệnh cuối cùng .
SimonT

Tôi đã bao gồm các đề xuất của bạn trong mã. Cảm ơn :)
dơi

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 byte

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

Ung dung:

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

Phương thức Btrả về một IEnumerableđại diện cho toàn bộ tập hợp Fibonacci (vô hạn). Phương thức thứ hai, được đưa ra một số n, xem xét các nsố Fibonacci đầu tiên (mức quá lớn ở đây), tìm tất cả các tập hợp con có thể (tập hợp sức mạnh), sau đó lọc xuống các tập hợp con có tổng chính xác n, sau đó in.


1

APL (75)

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

Ít cạnh tranh hơn tôi muốn, chủ yếu là do định dạng đầu ra.

Đầu ra:

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

Giải trình:

  • I←⎕: đọc đầu vào, lưu trữ trong I.
  • ⍳2: bắt đầu với danh sách 1 2,
  • {⍵,+/¯2↑⍵}: thêm tổng của hai phần tử cuối vào danh sách,
  • ⍣{I<⊃⌽⍺}: cho đến khi Inhỏ hơn phần tử cuối cùng của danh sách.
  • F←: store in F(đây là những số Wikipedia từ 1đến I).
  • N←⍴F: lưu trữ số lượng số Wikipedia trong N.
  • ↓⍉(N⍴2)⊤⍳2*N: lấy các số từ 1đến 2^N, dưới dạng bit.
  • S←/∘F¨: sử dụng từng cái như một bitmask trên F, lưu trữ trong S.
  • I=+/¨S: cho mỗi danh sách phụ trong S, xem tổng của nó có bằng không I.
  • S/⍨: chọn những cái này từ S. (Bây giờ chúng tôi có tất cả các danh sách các số Wikipedia tổng hợp I.)
  • {... : cho mỗi thứ này:
    • ,'+',⍪⍵: thêm một +phía trước mỗi số,
    • 1↓: lấy +lại đầu tiên ,
    • ⎕TC[2]: thêm một dòng mới,
    • ⎕←: và đầu ra.

1

Haskell - 127

Sau nhiều lần lặp, tôi đã kết thúc với đoạn mã sau:

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

Tôi có thể đã lưu có thể một ký tự bằng cách gian lận và thêm "0+" phía trước mỗi dòng đầu ra.

Tôi muốn chia sẻ một phiên bản khác (dài 143) mà tôi đã nghĩ ra trong khi cố gắng đánh golf giải pháp trước đó. Tôi chưa bao giờ lạm dụng các toán tử và bộ dữ liệu này nhiều như vậy trước đây:

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

Các trường hợp thử nghiệm, 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

và 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

Một số dữ liệu hiệu quả kể từ khi ai đó có công cụ này:

% 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 byte (Không cạnh tranh)

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

Hãy thử trực tuyến!

Tính tất cả các khoản tiền có thể cho bất kỳ n. Ví dụ đầu ra cho 1000:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.