9 tỷ tên của Chúa


74

9 tỷ tên của Chúa là một truyện ngắn của Arthur C. Clarke. Đó là về một nhóm các nhà sư Tây Tạng có trật tự được viết ra để viết ra tất cả các tên có thể của Thiên Chúa, được viết trong bảng chữ cái của riêng họ. Về cơ bản, họ được dành để viết mọi hoán vị có thể có của bảng chữ cái của họ, bị hạn chế bởi một vài quy tắc. Trong câu chuyện, tu viện thuê một số kỹ sư viết một chương trình để làm tất cả công việc cho họ. Mục tiêu của bạn là viết chương trình đó.

Quy tắc:

  • Bảng chữ cái của nhà sư sử dụng 13 ký tự (theo ước tính của tôi). Bạn có thể sử dụng ABCDEFGHIJKLMhoặc một số bộ 13 ký tự khác.

  • Độ dài tối thiểu của một tên có thể là 1 ký tự. Độ dài tối đa là 9 ký tự.

  • Không có nhân vật có thể lặp lại hơn 3 lần liên tiếp. AAABAlà một tên hợp lệ, nhưng AAAABkhông phải.

  • Chương trình của bạn nên in ra (vào một tệp) mọi tên có thể theo thứ tự từ Ađến MMMLMMMLM, được phân tách bằng bất kỳ ký tự nào không có trong bảng chữ cái (dòng mới, dấu chấm phẩy, bất cứ thứ gì).

  • Đây là môn đánh gôn và bạn có thể sử dụng bất kỳ ngôn ngữ nào. Giải pháp ngắn nhất vào ngày 1 tháng 6 năm 2014 chiến thắng.

Chỉnh sửa: Các tên phải bắt đầu bằng Avà kết thúc bằng MMMLMMMLM, tiến triển qua tất cả hàng tỷ tên theo tuần tự. Nhưng trình tự cụ thể là tùy thuộc vào bạn. Bạn có thể in ra tất cả các tên 1 chữ cái trước, sau đó tất cả các tên 2 chữ cái, v.v. Hoặc bạn có thể in tất cả các tên bắt đầu bằng A, sau đó tất cả các tên bắt đầu bằng Bhoặc một số mẫu khác. Nhưng một người nên có thể đọc qua tệp và xác nhận tất cả họ đều ở đó và theo bất kỳ thứ tự logic nào bạn chọn, giả sử họ có thời gian.


29
Bạn đang cố gắng để kết thúc vũ trụ, thưa ông?
Boluc Papuccuoglu

8
Liên kết đến câu chuyện , cho bất cứ ai quan tâm.
ThatOneGuy


1
Điều này xác minh rằng số lượng tên trong vấn đề hiện tại thực sự là 11.459.252.883 (như được tìm thấy trong chương trình C của edc65 ). Việc triển khai giải pháp của Ross Millikan tại MathSE tạo ra công thức đa thức sau cho số lượng tên có độ dài <= 9, cho kích thước bảng chữ cái thay đổi k : f(k) = k^9 + k^8 + k^7 - 5*k^6 + k^5 + k^4 + 4*k^3 - 2*k^2 + k. Thực hiện hiền nhân: goo.gl/0srwhq
res

3
@ edc65 Vậy 105.8GBtất cả đã nói và làm xong! Tôi rất vui vì các ngôi sao đã không ra ngoài ... hoặc có lẽ bạn phải in danh sách để điều đó xảy ra ...?
đệ

Câu trả lời:


34

Ruby, 46

?A.upto(?M*9){|s|s[/(.)\1{3}|[N-Z]/]||puts(s)}

Giải pháp tương tự ban đầu của tôi dài hơn và sai (nó xuất ra 13 số cơ bản, không hoàn toàn là do số 0 dẫn đầu), nhưng tôi sẽ để nó ở đây vì dù sao nó cũng có phiếu bầu.

1.upto(13**9){|i|(s=i.to_s 13)[/(.)\1{3}/]||puts(s)}

14
Vâng, tôi đã chạy mã của bạn trong khoảng một giờ và nhận được tới 2 tỷ tên và tệp văn bản 21 GB trước khi thấy điều này và thoát nó. Tôi đã đánh giá thấp tập tin sẽ lớn như thế nào.
CSturgess

2
@CSturgess Chà, Ruby không phải là ngôn ngữ nhanh nhất cho những thứ như thế này ...
BenjiWiebe

8
@BenjiWiebe Nhưng vẫn nhanh hơn là được các nhà sư viết tay!
Turophile

1
Chấp nhận cái này vì nó có nhiều phiếu hơn.
CSturgess

4
Không đăng bài này dưới dạng một câu trả lời riêng biệt, vì nó đòi hỏi một lượng bộ nhớ cực lớn (~ 30 TB, nếu tính toán của tôi là chính xác), nhưng trên lý thuyết bạn có thể rút ngắn nó xuống còn 43 ký tự vớik=*?A..?M*9;puts k-k.grep(/(.)\1{3}|[N-Z]/)
Ventero

24

C 140 177 235

Phong cách thủ tục cũ tốt, không cầu kỳ.
Nó đếm (không viết) 11.459.252.883 tên trong 8 phút.
Chỉnh sửa tiếp theo với thời gian chạy và kích thước của tập tin tên. Xem bầu trời ...
Thời gian chạy 57 phút, kích thước tệp 126,051,781,713 (9 ký tự + crlf mỗi hàng). Vui lòng cho tôi biết địa chỉ email của các nhà sư để tôi có thể gửi cho họ tệp nén, để kiểm tra thủ công ...

Chỉnh sửa Golf thêm một chút, làm lại kiểm tra cho các chữ cái lặp đi lặp lại.
Vẫn không phải là ngắn nhất, nhưng ít nhất điều này chấm dứt và tạo ra đầu ra cần thiết.
Thời gian chạy 51 phút, kích thước tệp 113,637,155,697 (không có khoảng trống hàng đầu lần này)

Một lưu ý phụ: rõ ràng tệp đầu ra rất dễ nén, tôi vẫn phải giết 7zip, sau khi làm việc 36 giờ, nó ở mức 70%. Kỳ dị.

char n[]="@@@@@@@@@@";p=9,q,r;main(){while(p)if(++n[p]>77)n[p--]=65;else for(r=q=p=9;r&7;)(r+=r+(n[q]!=n[q-1])),n[--q]<65&&puts(n+q+1,r=0);}

Ung dung

char n[]="@@@@@@@@@@";
p=9,q,r;
main()
{
    while (p)
    {
        if (++n[p] > 77)
        {
            n[p--] = 65; // when max reached, set to min and move pointer to left
        }
        else 
        {
            for (r=q=p=9; r & 7 ;) // r must start as any odd number
            {
                r += r+(n[q]!=n[q-1])); // a bitmap: 1 means a difference, 000 means 4 letters equal
                n[--q] < 65 && puts(n+q+1,r=0);
            }
        }
    }
}

không có #includes?
Simon Kuang

@SimonKuang, một số trình biên dịch sẽ tự động đưa những trình biên dịch cơ bản (stdio) vào.
Paul Draper

1
@Simon đó là tiêu chuẩn C. Theo mặc định, các đối tượng toàn cầu là các hàm int và global trả về int. Visual studio đưa ra cảnh báo C4013 về 'đặt' không được xác định, nhưng dù sao nó cũng hợp lệ.
edc65

4
phù hợp với một tweet!
CincauHangus

19

Golf, 58 47 ký tự

"A"13
9?,{13base{65+}%n+}%{`{\4*/,}+78,1/%1-!},

Nhờ Peter Taylor, tôi tránh được việc seppuku không đánh bại giải pháp Ruby! Tự chạy mã lên đến 10đây là bằng chứng cho thấy nó bỏ qua các số bốn liên tiếp .


1
Tiết kiệm dễ dàng: sử dụng n+thay vì ''+n. Tôi nghĩ đó là trong các quy tắc để sử dụng một bảng chữ cái với ký tự điều khiển, vì vậy bạn cũng có thể thay thế 65+với 13+và tiết kiệm nhân vật khác bằng cách đặt tên 13:^. Và tôi nghĩ rằng 13,{ stuff [...]có thể được 13,1/{ stuff 4*.
Peter Taylor

1
Suy nghĩ ban đầu của tôi là việc tiết kiệm sẽ thông qua một bộ lọc và với một chút công việc có thể được thực hiện. Từ 13,trên có thể được thay thế bằng {65+}%n+}%{ backtick {\4*/,}+78,1/%1-!},tổng số 8 tiết kiệm, cứu mạng bạn.
Peter Taylor

Miễn là nhân vật là thứ mà bạn có thể thấy, nó sẽ hoạt động. Thực sự bạn thậm chí có thể bao gồm các dòng mới như một nhân vật. Chỉ cần có một chuỗi các nhân vật.
CSturgess

@PeterTaylor: Bạn là một quý ông và một học giả!
Claudiu

Sau khi AAAMnó nên AAABA, và không BAAAB, phải không?
cần

18

Tiện ích dòng lệnh Bash + Linux, 43 byte

jot -w%x $[16**9]|egrep -v "[0ef]|(.)\1{3}"

Điều này sử dụng một kỹ thuật tương tự như câu trả lời của tôi dưới đây, nhưng chỉ đếm ở cơ sở 16 và loại bỏ tất cả các "tên" có chứa 0, ehoặc fcả những tên có nhiều hơn 3 chữ số liên tiếp.

Chuyển đổi sang bảng chữ cái của nhà sư như sau:

jot -w%x $[16**9]|egrep -v "[0ef]|(.)\1{3}" | tr 1-9a-d A-M

Bash + coreutils (dc và egrep), 46 byte

Chỉnh sửa - sửa phiên bản

dc<<<Edo9^[p1-d0\<m]dsmx|egrep -v "0|(.)\1{3}"

Điều này sẽ mất một lúc để chạy nhưng tôi nghĩ nó đúng.

dcđếm xuống từ 14 ^ 9 đến 1 và xuất ra trong cơ sở 14. egrep lọc ra các số có nhiều hơn 3 chữ số liên tiếp. Chúng tôi cũng lọc bất kỳ tên nào có chữ số "0", vì vậy chúng tôi có được bộ chữ cái chính xác trong tên.

Câu hỏi chỉ định rằng bất kỳ bảng chữ cái nào cũng có thể được sử dụng, vì vậy tôi đang sử dụng [1-9] [AD]. Nhưng để thử nghiệm, điều này có thể được chuyển thành [AM] bằng cách sử dụng tr:

dc<<<Edo9^[p1-d0\<m]dsmx|egrep -v "0|(.)\1{3}" | tr 1-9A-D A-M

Điều này mang lại trình tự:

MMMLMMMLM MMMLMMMLL MMMLMMMLK ... AC AB AA M L K ... C B A

Lưu ý dclệnh này yêu cầu đệ quy đuôi để làm việc. Điều này hoạt động trên phiên bản dc 1.3.95 (Ubuntu 12.04) chứ không phải 1.3 (OSX Mavericks).


10

APL (59)

↑Z/⍨{~∨/,↑⍷∘⍵¨4/¨⎕A[⍳13]}¨Z←⊃,/{↓⍉⎕A[1+(⍵/13)⊤¯1⌽⍳13*⍵]}¨⍳9

Được viết trong bảng chữ cái của riêng nó :) Nó hơi dài. Nó cũng mất nhiều thời gian để chạy với 9, hãy thử với số thấp hơn để kiểm tra nếu bạn muốn.

Giải trình:

  • {... }¨⍳9: cho mỗi số từ 1 đến 9:
    • ⍳13*⍵: lấy tất cả các số từ 1 đến 13^⍵
    • ¯1⌽: Xoay danh sách sang trái bằng 1 (vì vậy chúng tôi có 13^⍵, 1, 2, ..., 13^⍵-1, mà biến thành 0, 1, 2 ...modulo 13^⍵).
    • (⍵/13)⊤: mã hóa từng số trong cơ sở 13 bằng chữ số
    • ⎕A[1+... ]: thêm một (mảng được lập chỉ mục 1) và tra cứu trong ⎕A(bảng chữ cái)
    • ↓⍉: biến ma trận thành một vectơ dọc theo các cột.
  • Z←⊃,/: nối từng vectơ bên trong của các vectơ lại với nhau, cung cấp cho chúng tôi danh sách các tên có thể (nhưng nó chưa đáp ứng các quy tắc).
  • {... : cho mỗi tên, kiểm tra xem nó có đáp ứng quy tắc 4 lần lặp lại không:
    • 4/¨⎕A[⍳13]: cho mỗi ký tự, tạo một chuỗi gồm 4 ký tự đó
    • ⍷∘⍵¨: cho mỗi chuỗi, kiểm tra nếu nó có trong
    • ∨/,↑: thực hiện logic hoặc của tất cả các thử nghiệm này,
    • ~: và đảo ngược nó, vì vậy điều đó 1có nghĩa là nó đáp ứng các quy tắc và 0có nghĩa là nó không.
  • Z/⍨: chọn từ Ztất cả các yếu tố đáp ứng các di tích
  • : hiển thị từng cái trên một dòng riêng biệt

9
Tôi thất vọng. Với danh tiếng của nó, bạn sẽ nghĩ APL sẽ có giải pháp một ký tự cho việc này, mà không bàn phím nào có thể gõ được.
Đánh dấu

7
@Mark, tôi chắc chắn rằng APL có điều đó, nhưng không ai biết nhân vật đó là gì :)
Paul Draper

1
người ta nên viết cái này lên một hòn đá và khi con người trong tương lai tìm thấy thứ này, họ có thể nghĩ rằng đó chỉ là ngôn ngữ viết nguyên thủy.
CincauHangus

9

Perl, 70 68 66 50 ký tự

$"=",";map/(.)\1{3}/||say,glob$i.="{@a}"for@a=A..M

Sử dụng:

$ perl -E 'code' > output_file

Điều thú vị là các bản in được đệm, do đó bạn nhận được tất cả các giải pháp 1 ký tự được in trước, tiếp theo là các từ 2 ký tự, v.v.


Điều tốt nhất về giải pháp này là tiếng la ó ở bên trái của 1.
Dan Hanly

8

Perl - 35 byte

#!perl -l
/(.)\1{3}|[N-Z]/||print for A..1x9

Đếm shebang là một byte.

Đây là một bản dịch lỏng lẻo của câu trả lời của lịch sử .

A..1x9là một chút kỳ lạ; đây là tốc ký cho 'A'..'111111111'. Bộ tích lũy sẽ không bao giờ thực sự đạt đến giá trị đầu cuối (nó chỉ chứa các chữ cái viết hoa), nhưng nó vẫn sẽ chấm dứt một khi nó dài hơn 9 ký tự. Điều này có thể được kiểm tra, ví dụ, bằng cách sử dụng 1x4thay thế.


Sự tôn trọng! Bây giờ tại sao tôi không nghĩ về điều đó? ;)
Zaid

Lưu ý rằng Ruby không phải tạo toàn bộ phạm vi để lặp lại nó. Lý do duy nhất mà mã trong bình luận của tôi đòi hỏi một lượng bộ nhớ lớn như vậy là vì nó biến phạm vi thành một mảng (để nó có thể sử dụng Array#-).
Ventero

@Ventero Ahh vâng, grepsẽ làm điều đó. Tôi không hoàn toàn thông thạo Ruby.
primo

6

Pyg (Waaay quá dài, vì một ngôn ngữ dành cho chơi gôn)

thì thầm : 101 ...

Pe(*ItCh(((J(x)for x in ItPr("ABCDEFGHIJKLM",repeat=j)if not An((i*3 in x)for i in x))for j in R(14))))

Mặc dù điều này gần với cách tôi thực sự làm điều đó trong Python:

from itertools import *
for i in range(14):
    for j in ("".join(k) for k in product("ABCDEFGHIJKLM",repeat=i) if not any((i*3 in k) for i in k)):
        print j

Trừ đi các biến chứng dài dòng tất nhiên;)


3

Pyth , 34 ký tự

Kf<T"n"GJKFbJI>lb9Bb~Jm+bdfXVb*Y3K

Giải trình:

Kf<T"n"G        K = list of letters in the alphabet before n.
JK              J = copy of K
FbJ             For b in J:
I>lb9B          If length of b > 9: break
b               print(b)
~J              J+=
~Jm+bd          J+=map(lambda d:b+d,
       XVb*Y3   index of Y*3 in reversed(b)
      fXVb*Y3K  filter for non-zero for Y in K on function index of Y*3 in reversed(b)
~Jm+bdfXVb*Y3K  J+=map(lambda d:b+d, filter(lambda Y:index of Y*3 in reversed(b), K))

2

Python 2 - 212 byte

from itertools import chain,product as p
a='ABCDEFGHIJKLM'
q={c*4 for c in a}
c=0
for n in chain(*(p(*([a]*l)) for l in range(1,10))):
 n=''.join(n)
 if not any(u in n for u in q):print n
 c+=1
 if c==10**9:break

0

Japt , 21 byte

Ep9 osE kè/0|(.)\1{3}

Hãy thử trực tuyến! (liên kết chỉ tính toán tối đa 14**4.)

Làm thế nào nó hoạt động

Ep9 osE kè/0|(.)\1{3}/

Ep9  14**9
osE  Range from 0 to n (exclusive), mapped through base-14 conversion
kè   Remove elements that match at least once...
/0|(.)\1{3}/  the regex that matches a zero or four times same char.

Giả sử triển khai ECMAScript 2017 tiêu chuẩn là lớp JS (và đủ bộ nhớ để lưu trữ mảng), trong đó một Arrayđối tượng có thể có 2**53-1chiều dài tối đa .

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.