九十亿个上帝的名字


74

上帝的90亿个名字是Arthur C. Clarke的短篇小说。这是关于一群藏族僧侣的,他们的命题是写下所有可能的神的名字,并用自己的字母写下。从本质上讲,他们致力于编写受某些规则限制的字母的所有可能排列。在故事中,修道院聘请了一些工程师编写程序来为他们完成所有工作。您的目标是编写该程序。

规则:

  • 和尚的字母使用13个字符(根据我的估计)。您可以使用ABCDEFGHIJKLM或其他一组13个字符。

  • 可能名称的最小长度为1个字符。最大长度为9个字符。

  • 角色连续重复的次数不得超过3次。AAABA是有效名称,但AAAAB不是。

  • 你的程序应该从顺序打印出来(到文件)每一个可能的名字AMMMLMMMLM为任意字符,也有字母分开(换行符,分号,等等)。

  • 这是代码高尔夫球,您可以使用任何语言。2014年6月1日之前最短的解决方案将获胜。

编辑:名称应以开头A和结尾MMMLMMMLM,依次遍历所有数十亿个名称。但是具体的顺序由您决定。您可以先打印所有1个字母的名称,然后打印所有2个字母的名称,等等。或者您可以打印所有以开头的名称A,然后打印以开头的所有名称B,或其他模式。但是,假设他们有时间,人应该应该能够通读文件并确认文件全部存在,并以您选择的任何逻辑顺序进行确认。


29
先生,您是否想结束宇宙?
Boluc Papuccuoglu 2014年

8
链接到故事,适合任何有兴趣的人。
ThatOneGuy 2014年


1
这可以验证当前问题中的名称确实为11,459,252,883(如edc65的C程序中所示)。在MathSE上实施Ross Millikan解决方案时,对于字母大小为k:的长度小于等于9的名称数,将生成以下多项式公式f(k) = k^9 + k^8 + k^7 - 5*k^6 + k^5 + k^4 + 4*k^3 - 2*k^2 + k。贤者实现:goo.gl/0srwhq
水库

3
@ edc65 105.8GB所有人都说完了!我很高兴星星没有熄灭...或者您可能必须打印出要完成的列表...?
recursion.ninja 2014年

Answers:


34

Ruby,46岁

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

我最初的类似解决方案又长又错(输出base13数字,由于前导零而不是全部),但我将其保留在这里,因为无论如何它都获得了投票。

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

14
好吧,我运行了大约一个小时的代码,得到了多达20亿个名称和一个21 GB的文本文件,然后才能看到并退出它。我低估了文件的大小。
CSturgess 2014年

2
@CSturgess好吧,Ruby并不是这类事情中最快的语言……
BenjiWiebe 2014年

8
@BenjiWiebe但是比和尚手写的还要快!
Turophile 2014年

1
接受此投票,因为它有更多票。
CSturgess

4
不要将其作为单独的答案发布,因为它需要大量的内存(如果我的计算是正确的,则需要大约30 TB),但是从理论上讲,您可以使用k=*?A..?M*9;puts k-k.grep(/(.)\1{3}|[N-Z]/)
Ventero,2014年

24

C 140177235

良好的旧程序风格,没有幻想。
它在8分钟内计算(不写)11,459,252,883个名字。
下一步使用名称文件的运行时和大小进行编辑。观看天空...
运行时 57分钟,文件大小126,051,781,713(每行9个字符+小数)。请告诉我和尚的电子邮件地址,以便我将压缩文件发送给他们,以便进行手动检查...

Edit打了些球,重新检查了一下是否有重复的字母。
仍然不是最短的,但是至少这一个终止并生成所需的输出。
运行时51分钟,文件大小113,637,155,697(这次没有空白)

旁注:很明显,输出文件是非常可压缩的,在工作36小时后,我仍然不得不杀死7zip,它的效率是70%。奇怪的。

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

不打高尔夫球

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

没有#includeS'
Simon Kuang

@SimonKuang,某些编译器会自动插入基本的(stdio)。
Paul Draper 2014年

1
@Simon这是C标准。默认情况下,全局对象为int,全局函数返回int。Visual Studio输出C4013关于“ puts”的警告,但未定义,但仍然有效。
edc65 2014年

4
适合推文!
CincauHangus 2014年

19

Golfscript,58个 47个字符

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

感谢彼得·泰勒(Peter Taylor),我幸免于seppuku的失败,而不是击败Ruby解决方案!自己最多运行10个代码这证明它跳过了四行代码


1
易于保存:使用n+代替''+n。我认为这是在规则之内使用与控制字符的字母,所以你也可以更换65+13+和命名保存另一个字符13:^。我认为13,{ stuff [...]可能是这样13,1/{ stuff 4*
彼得·泰勒

1
我最初的想法是,可以通过过滤器来节省费用,并且可以做一些工作。从13,开始可以替换{65+}%n+}%{ backtick {\4*/,}+78,1/%1-!},为,总共可以节省8,从而节省了生命。
彼得·泰勒

只要角色是您可以实际看到的东西,它就会起作用。确实,您甚至可以包含换行符作为字符。只要字符有顺序即可。
CSturgess 2014年

@PeterTaylor:您是一位绅士和学者!
2014年

之后AAAM应该是AAABA,不是BAAAB,对吗?
justhalf 2014年

18

Bash + Linux命令行工具,43个字节

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

这使用与我在下面的答案类似的技术,但仅以16为底数,并去除包含的所有“名称” 0e或者f去除连续3个以上连续数字的“名称” 。

转换为和尚的字母,如下所示:

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

Bash + coreutils(DC和egrep),46字节

编辑-更正的版本

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

这需要一段时间才能运行,但我认为它是正确的。

dc从14 ^ 9向下计数到1,并在基数14中输出。egrep过滤出连续3个以上相同数字的数字。我们还会过滤掉任何带有“ 0”数字的名称,因此我们在名称中得到了正确的字母集。

问题指定可以使用任何字母,因此我正在使用[1-9] [AD]。但是对于测试,可以使用tr将其转换为[AM]:

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

这产生了序列:

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

注意,此dc命令需要尾递归才能起作用。这适用于DC版本1.3.95(Ubuntu 12.04),但不适用于1.3版本(OSX Mavericks)。


10

APL(59)

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

用自己的字母写:)它有点长。使用它还需要花费很长时间9,请尝试使用较小的数字来测试是否需要。

说明:

  • {... }¨⍳9从1到9的每个数字:
    • ⍳13*⍵:获取从1到1的所有数字 13^⍵
    • ¯1⌽:1转动左侧列表中(所以我们有13^⍵12,... 13^⍵-1,它变成0, 1, 2 ...13^⍵)。
    • (⍵/13)⊤:使用数字对以13为底的每个数字进行编码
    • ⎕A[1+... ]:加一个(数组按1索引)并在⎕A(字母)中查找
    • ↓⍉:将矩阵变成沿列的向量的向量。
  • Z←⊃,/:将向量的每个内部向量连接在一起,为我们提供了可能的名称列表(但尚不符合规则)。
  • {... :对于每个名称,请测试其是否符合4个重复字符的规则:
    • 4/¨⎕A[⍳13]:为每个字符生成一个由4个字符组成的字符串
    • ⍷∘⍵¨:对于每个字符串,测试它是否存在于
    • ∨/,↑:进行逻辑所有这些测试,
    • ~:并将其反转,这1意味着它符合规则,0但不符合。
  • Z/⍨:从Z符合规则的所有元素中进行选择
  • :在单独的一行上显示每个

9
我很失望。考虑到它的声誉,您可能会认为APL会为此提供一个字符的解决方案,而这种键盘是无法键入的。
2014年

7
@Mark,我敢肯定APL确实有这个功能,但没人知道这个角色是什么:)
Paul Draper

1
人们应该把它写在一块石头上,当未来的人们发现它时,他们可能会认为这只是原始的书面语言。
CincauHangus 2014年

9

Perl,70 68 66 50个字符

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

用法:

$ perl -E 'code' > output_file

令人高兴的是,打印内容得到缓冲,因此您首先打印了所有1个字符的解决方案,然后打印了2个字符的单词,依此类推。


关于这个解决方案的最好的事情是布布到1的左
丹汉利

8

Perl-35个字节

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

将shebang计为一个字节。

这是对历史学家答案的宽松翻译。

A..1x9有点奇怪;这是的简写'A'..'111111111'。累加器将永远不会真正达到最终值(它仅包含大写字母),但是一旦长度超过9个字符,它仍将终止。例如,可以使用来测试1x4


尊重!现在,为什么我没有想到呢?;)
Zaid 2014年

注意,Ruby也不必为了迭代而创建整个范围。我的注释中的代码需要如此大量内存的唯一原因是它将范围转换为Array(以便可以使用Array#-)。
Ventero 2014年

@Ventero啊,grep会的。我并不完全精通Ruby。
2014年

6

Pyg(Wayay太长了,对于打高尔夫球的语言而言)

耳语: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))))

即使这与我在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

减去当然的长线并发症;)


3

Pyth,34个字符

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

说明:

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字节

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字节

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

在线尝试!(链接最多只能计算14**4。)

这个怎么运作

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.

假定标准ECMAScript 2017实现为JS层(以及足够的内存来存储数组),其中Array对象可以具有最大2**53-1长度。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.