Xuất ra một danh sách tất cả các số hữu tỷ


13

Trong số tất cả toán học, sẽ luôn có một vài định lý vượt ra ngoài mọi lẽ thường. Một trong số đó là thực tế có nhiều kích cỡ khác nhau. Một sự thật thú vị khác là ý tưởng rằng nhiều vô số dường như có kích thước khác nhau thực sự có cùng kích thước. Có nhiều số chẵn như số nguyên, cũng như có số hữu tỷ.

Khái niệm chung của câu hỏi này là đối đầu với thực tế kỳ lạ của vô cực. Trong thử thách này, chương trình của bạn sẽ đưa ra một danh sách sẽ:

  • Tại bất kỳ thời điểm cụ thể nào, luôn có một số lượng mục
  • Cuối cùng có chứa (nếu còn lại để chạy đủ lâu) bất kỳ số hữu tỷ cụ thể (khác không) chính xác một lần trên toàn bộ danh sách
  • Chứa số lượng vị trí trống không giới hạn (các mục trong danh sách không cần thiết được đặt thành 0)
  • Có tỷ lệ các vị trí trống đạt đến giới hạn 100%
  • Với mỗi số nguyên dương N, có vô số vị trí với N vị trí trống liên tiếp

Các thách thức

Thách thức của bạn là viết chương trình ngắn nhất có thể sẽ đưa ra một danh sách đặc biệt với các quy tắc sau:

  1. Tất cả các mục có chỉ số không phải là số vuông nên được đặt thành không. Vì vậy, mục đầu tiên sẽ là khác không, mục thứ hai và thứ ba sẽ bằng không, mục thứ tư sẽ khác không, v.v.
  2. Tất cả các số hữu tỷ sẽ ở dạng phân số không chính xác (chẳng hạn như 4/5 hoặc 144/13) đã được đơn giản hóa. Ngoại lệ là số không, sẽ đơn giản 0.
  3. Tất cả các số hữu tỷ (dương và âm) cuối cùng sẽ xuất hiện trong danh sách nếu chương trình của bạn chạy đủ lâu và có đủ bộ nhớ. Đối với bất kỳ số hữu tỷ cụ thể nào, thời gian cần thiết có thể là một lượng lớn tùy ý, nhưng luôn luôn hữu hạn, lượng thời gian.
  4. Nếu chạy trong một khoảng thời gian vô hạn, không có số hữu tỷ nào khác không xuất hiện hai lần.

Quy tắc 3 không cho phép một số biến thể, vì trong đó có vô số đầu ra hợp pháp khác nhau có thể.

Đầu ra sẽ là một dòng của dòng. Mỗi dòng sẽ có dạng chung trong 5: 2/3đó số đầu tiên là số mục nhập, sau đó là số hữu tỷ. Lưu ý rằng 1: 0sẽ luôn là dòng đầu ra đầu tiên.

Ví dụ đoạn đầu ra:

1: 1/1
2: 0
3: 0
4: 2/1
5: 0
6: 0
7: 0
8: 0
9: -2/1
10: 0
etc...

Các quy tắc, quy định và ghi chú

Đây là mã golf. Quy tắc golf tiêu chuẩn áp dụng. Ngoài ra, do biến thể được cho phép ở đầu ra, ít nhất bạn cần chỉ ra lý do tại sao bạn tin rằng danh sách của bạn sẽ chứa tất cả các số hữu tỷ có thể chính xác một lần và giải pháp của bạn là chính xác.

EDIT: Vì các số nguyên tố đã làm phân tâm khỏi thử thách, tôi thay đổi nó thành số vuông. Điều này thực hiện cùng một mục đích, và cũng rút ngắn các giải pháp.


1
Điểm của quy tắc 1 là gì? Bạn có muốn mọi người cùng chơi golf hai chương trình riêng biệt để kiểm tra tính nguyên thủy và liệt kê các lý do không?
Peter Taylor

Nó cho thấy một phần rất nhỏ của các số nguyên vẫn có cùng số lượng với toàn bộ số hữu tỷ và nó cũng cho phép tỷ lệ phần trăm của các vị trí trống tiếp cận (nhưng không bao giờ đạt được) 100%.
PhiNotPi

Tôi giả sử rằng chương trình cũng cần chạy trong một lượng bộ nhớ cố định, tức là không thể cho rằng máy luôn có thể phân bổ nhiều hơn? Ngoài ra, nó có trái với quy tắc sử dụng (giả sử) một C int cho chỉ mục danh sách khi bạn biết rằng nó có phạm vi hữu hạn không? (Mặc dù giới hạn chính xác có thể thay đổi theo cách triển khai.) Có phải một số hình thức bignum cần thiết không?
hộp bánh mì

1
@PhiNotPi, có nhiều cách đơn giản hơn để làm điều đó và đó là một sự phân tâm từ phần thú vị hơn của câu hỏi.
Peter Taylor

1
Lưu ý rằng 1: 0sẽ luôn là dòng đầu ra đầu tiên. - Điều này mâu thuẫn với ví dụ của bạn và cũng không có ý nghĩa với tôi.
Wrzlprmft

Câu trả lời:


6

Haskell, 184 ký tự

main=putStr.unlines$zip[1..](s>>=g)>>=h
s=(1,1):(s>>=f)
f(a,b)=[(a,a+b),(a+b,b)]
g x@(a,b)=[x,(-a,b)]
h(i,(a,b))=(i^2)%(u a++'/':u b):map(%"0")[i^2+1..i*(i+2)]
i%s=u i++": "++s
u=show

Điều này thực hiện một giao dịch đầu tiên theo chiều rộng của Cây Calkin-Wilf , mang lại tất cả các số hữu tỷ dương ở dạng giảm chính xác một lần. Sau đó, nó xen kẽ giữa dương và âm để bao gồm tất cả các số hữu tỷ khác không và các số đệm với các số 0 giữa các mục vuông.

Đầu ra (không bao gồm các dòng không cho ngắn gọn):

1: 1/1
4: -1/1
9: 1/2
16: -1/2
25: 2/1
36: -2/1
49: 1/3
64: -1/3
81: 3/2
100: -3/2
...

5

Hiền nhân, 103 113 128

Sage có thể liệt kê các lý do một cách dễ dàng! Định dạng để phù hợp với yêu cầu của chương trình, như mọi khi, làm hỏng mọi thứ.

for i,q in enumerate(QQ):
 for j in[(i-1)^2+1..i*i]:print'%d:'%j,[0,'%d/%d'%(q.numer(),q.denom())][j==i*i]

Sage liệt kê QQtheo chiều cao của chúng : giá trị tuyệt đối tối đa của tử số & mẫu số sau khi giảm GCD.


Bạn có thể loại bỏ x.next()printchỉ sử dụng một lần, như sau, đưa điểm số xuống còn 124 : x=enumerate(QQ) for i,q in x: for j in[(i-1)^2+1..i*i]: print'%d: '%j,'%d/%d'%(q.numer(),q.denom())if j.is_square()else 0. Điều này không hiển thị đúng trong một bình luận, nhưng tôi nghĩ bạn có thể thấy những gì tôi muốn nói.
res

BTW, tôi nhận thấy rằng sau 4 yếu tố tích cực đầu tiên, phép liệt kê của Sage không giống như trong các câu trả lời khác. Các công thức Calkin-Wilf đưa ra một chuỗi trong đó mẫu số của một số hữu tỷ là tử số của số hữu tỷ tiếp theo; ví dụ: (..., 1/3, 3/2, 2/3, ...), so với Sage (..., 1/3, 3/1, 2/3, ...). Tôi dường như không thể tìm thấy bất kỳ tài liệu nào cho phép liệt kê của Sage, để xem nó được tính toán như thế nào.
res

@res, cảm ơn! Tôi muốn hợp nhất các câu lệnh in, nhưng quên sử dụng ký hiệu [x..y]. Thật tuyệt khi thấy một người dùng Sage khác ở đây!
gian hàng

4

Con trăn, 162

f=lambda n:f(n/2)if n%2 else f(n/2)+f(n/2-1)if n else 1
n=i=1
while 1:
 print'%d:'%i,
 if i-n*n:s=0
 else: n+=1;s='%d/%d'%((-1)**n*f(n/2-1),f(n/2))
 print s
 i+=1

Điều này sử dụng đệ quy được đưa ra trong Kể lại các Rational của Calkin & Wilf.


2

Haskell, 55 byte

mapM_ print$join$iterate(>>=(\x->[x+1,1/(1+1/x)]))[1%1]

đầu ra

1 % 1
2 % 1
1 % 2
3 % 1
2 % 3
3 % 2
1 % 3
4 % 1
...

1% 1 là gốc của cây Calkin-Wilf; iterate thêm cả hai con của mỗi nút; sự tham gia thu gọn các cấp thành một danh sách.

120 ký tự nếu bạn thêm nhập chính xác, 0 và phủ định:

import Data.Ratio
import Control.Monad
main=mapM_ print$0:(join(iterate(>>=(\x->[x+1,1/(1+1/x)]))[1%1])>>=(\x->[-x,x]))

đầu ra

0 % 1
(-1) % 1
1 % 1
(-2) % 1
2 % 1
(-1) % 2
1 % 2
(-3) % 1
3 % 1
(-2) % 3
2 % 3
(-3) % 2
3 % 2
(-1) % 3
1 % 3
(-4) % 1
4 % 1
...

xuất các khe trống? đó là hương vị kém :( bạn đã cho tôi vào "danh sách tất cả các lý do tích cực"


mapM_ print$fix((1%1:).(>>= \x->[x+1,1/(x+1)]))là 47 ký tự. từ haskellwiki . hoạt động như là, không có bất kỳ nhập khẩu nào, tại REPL "thử nó" REPL (tốt, không có mapM_ printphần ...)
Will Ness

1

105 byte PHP

Lưu ý: Mã này phải được lưu dưới dạng iso-8859-1 (ansi) để chạy chính xác. Thông dịch viên trực tuyến mã hóa tất cả đầu vào sang utf8 theo mặc định (chẳng hạn như ideone) sẽ tạo ra đầu ra sai.

<?for($f=µ;$i++<$j*$j||++$j%2||(--$$f?$$f--:$f^=C);)echo"$i: ",$i==$j*$j?$j%2?$x=++$ö.~Ð.++$µ:"-$x":0,~õ;

Sử dụng phép liệt kê của Georg Cantor (được sửa đổi một chút cho các giá trị +/-).

Nếu bạn gặp sự cố khi chạy mã ở trên (có thể do số lượng thông báo THÔNG BÁO quá nhiều), hãy sử dụng mã này thay thế (107 byte):

<?for($f=µ;$i++<$j*$j||++$j%2||(--$$f?$$f--:$f^=C);)echo"$i: ",$i==$j*$j?$j%2?$x=++$ö.'/'.++$µ:"-$x":0,'
';

1
Tôi gặp lỗi thời gian chạy với mã này (dường như có chứa một số ký tự lạ; ví dụ: "$ ö. ~ Đ.").
res

Bạn có thể chứng minh rằng giải pháp này hoạt động, nói trên ideone? Tôi cũng gặp lỗi: ideone.com/ru1fo
mellamokb

Ideone dường như lỗi khi có quá nhiều thông báo THÔNG BÁO được tạo ra: cả ~ Đ (bằng '/') và ~ õ (bằng "\ n") sẽ tạo ra một THÔNG BÁO mỗi lần lặp. Tất nhiên, nếu bạn có THÔNG BÁO, đó không phải là vấn đề. Một dán với cả hai được thay thế (107 Byte): ideone.com/lFUbl
primo

Tôi vừa nhận thấy rằng trình thông dịch PHP của Ideone tạo ra đầu ra sai. Nếu bạn chạy mã cục bộ, bạn sẽ thấy rằng nó là chính xác. Hoặc, bạn có thể kiểm tra nó với trình thông dịch PHP hợp lệ, chẳng hạn như trình kiểm tra hiệu suất của Anarchy Golf: golf.shinh.org/checker.html (lưu nó vào một tệp và tải lên)
primo

Khi tôi lưu mã sửa đổi của bạn vào một tệp có mã hóa ANSI, nó sẽ chạy trên trình thông dịch Anarchy Golf. Tuy nhiên, bây giờ có một vấn đề khác: nó vi phạm yêu cầu "không có số hữu tỷ khác không xuất hiện hai lần" trong danh sách. Trong thực tế, mã xuất hiện để liệt kê mọi lý trí vô hạn nhiều lần; ví dụ như 1/1, 2/2, 3/3, ... đều như nhau hợp lý, và tương tự như vậy cho 1/2, 2/4, 3/6, ..., vv
res

0

Octave, 168 byte

a=b=p=1;do for i=(p-1)^2+1:p^2-1 printf("%d: 0\n",i)end
printf("%d: %d/%d\n",p^2,a,b)
a=-a;if a>0do if b==1 b=a+1;a=1;else a++;b--;end until 1==gcd(a,b)end
p++;until 0

Giải pháp không phức tạp lắm, nó chỉ là một đường chéo đơn giản của "thảm" các số hữu tỷ, loại bỏ tất cả các phân số có thể được đơn giản hóa. Sau một số dương a/b, nó ngược lại -a/bluôn được in trước khi số tiếp theo từ chuỗi đi.

Đường chéo của tất cả các hợp lý tích cực

Vì tất cả các phân số đơn giản dương sẽ được in và các phân số được ký ngược lại với các phân số sẽ được in và không bao giờ có thể có hai phân số đơn giản khác nhau có cùng giá trị, mỗi số hữu tỷ khác không được in chính xác một lần.

Bị thoái hóa:

a=b=p=1
do
    for i=(p-1)^2+1:p^2-1
        printf("%d: 0\n",i)         # p=2,3,4: 1..3,5..8,10..15
    end
    printf("%d: %d/%d\n", p^2,a,b); # p=2,3,4: 4,9,16
    a=-a;
    if a>0                          # the rule is: after a/b, a>0 output -a/b
        do
            if b==1 b=a+1;a=1; else a++;b--; end
        until 1==gcd(a,b)
    end
    p++;
until 0
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.