神の90億の名前


74

神の90億の名前は、アーサーC.クラークによる短編です。それは、自分のアルファベットで書かれた神のすべての可能な名前を書き留めることに専念しているチベットの僧ksのグループについてです。基本的に、彼らはいくつかのルールによって制限されたアルファベットのあらゆる可能な順列を書くことに専念しています。物語の中で、修道院は何人かのエンジニアを雇って、彼らのためにすべての仕事をするプログラムを書くようにしています。あなたの目標はそのプログラムを書くことです。

ルール:

  • 僧kのアルファベットは13文字を使用しています(私の推定によると)。ABCDEFGHIJKLMまたは13文字のその他のセットを使用できます。

  • 可能な名前の最小長は1文字です。最大長は9文字です。

  • キャラクターは連続して3回以上繰り返すことはできません。AAABAは有効な名前ですが、そうでAAAABはありません。

  • プログラムは、アルファベット順ではない任意の文字(改行、セミコロン、その他)で区切られたAto から順に、可能なすべての名前を(ファイルに)出力する必要がありますMMMLMMMLM

  • これはコードゴルフであり、任意の言語を使用できます。2014年6月1日までの最短のソリューションが勝利します。

編集:名前はで始まり、Aで終わる必要がMMMLMMMLMあります。すべての数十億の名前が順番に処理されます。しかし、特定のシーケンスはあなた次第です。最初にすべての1文字の名前、次にすべての2文字の名前などを印刷できます。または、で始まるすべての名前を印刷しA、次にで始まるすべての名前B、または他のパターンを印刷できます。しかし、時間があると仮定すると、人間はファイルを読んで、すべてがそこにあり、あなたが選択した論理的な順序ですべてを確認できるはずです。


29
宇宙を終わらせようとしていますか?
ボーリュックパプクオグル14年

8
興味のある方のために、ストーリーへのリンク
ThatOneGuy 14年

1
ここにあります!math.stackexchange.com/a/34292
edc65

1
これにより、現在の問題の名前の数が実際に11,459,252,883であることが検証されますedc65のCプログラムに見られるように)。実装MathSEにおけるロスミリカンのソリューションは、長さの名前の数は、次の多項式を生成<= 9、可変アルファベットサイズkのために: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
res

3
@ edc65だから、105.8GBすべて言って完了しました!星が消えなかったことをうれしく思います...またはそれを実現するためにリストを印刷する必要があるかもしれません...?
recursion.ninja 14年

回答:


34

ルビー、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
さて、私はあなたのコードを約1時間実行し、これを見て終了するまでに最大20億の名前と21 GBのテキストファイルを取得しました。ファイルの大きさを過小評価していました。
CSturgess

2
@CSturgessまあ、Rubyは...そこにこの種のもののための最速の言語ではありません
BenjiWiebe

8
@BenjiWiebeしかし、修道士によって手書きされるよりもまだ速い!
Turophile

1
投票数が多いため、これを受け入れます。
CSturgess

4
(私の計算が正しければ〜30 TB、)それがメモリの非常に膨大な量を必要とするため、別の答えとしてこれを掲示はなく、理論的には、あなたは43文字にこれを短縮することができますk=*?A..?M*9;puts k-k.grep(/(.)\1{3}|[N-Z]/)
Ventero

24

C 140177235

古き良き手続きスタイル、空想なし。
8分間で11,459,252,883名(書き込みなし)をカウントします。
次に、ランタイムと名前ファイルのサイズを編集します。空を見る...
ランタイム 57分、ファイルサイズ126,051,781,713(行ごとに9文字+ crlf)。修道士のメールアドレスを教えてください。手動で確認するために、zipファイルを送信できます。

編集 Golfedをもう少し、繰り返し文字のチェックを作り直しました。
それでも最短ではありませんが、少なくともこれは終了し、必要な出力を生成します。
ランタイム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);
            }
        }
    }
}

いや#include
サイモンクアン14年

@SimonKuang、一部のコンパイラは基本的なもの(stdio)を自動的に挿入します。
ポールドレイパー14年

1
@SimonはC標準です。デフォルトでは、グローバルオブジェクトはintであり、グローバル関数はintを返します。Visual Studioは、「puts」が定義されていないというC4013警告を出力しますが、とにかく有効です。
edc65 14年

4
ツイートに収まります!
シンカウハングス14年

19

Golfscript、58 47文字

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

Peter Taylorのおかげで、私はRubyソリューションを破らないという切腹を免れました!自分最大10個のコードを実行する、4行の数字がスキップされることを証明できます


1
簡単な保存:のn+代わりに使用します''+n。制御文字にアルファベットを使用することは規則の範囲内であると思うので、名前を付けて別の文字に置き換え65+13+保存することもできます13:^。そして、私はそれ13,{ stuff [...]ができると思います13,1/{ stuff 4*
ピーターテイラー

1
私の最初の考えは、フィルターを介して保存することであり、少しの作業でそれを行うことができるということでした。以降は、合計8個の節約に13,置き換えられ、{65+}%n+}%{ backtick {\4*/,}+78,1/%1-!},あなたの命を救います。
ピーターテイラー

キャラクターが物理的に見えるものである限り、それは機能します。本当に改行を文字として含めることもできます。文字にシーケンスがある限り。
CSturgess

@PeterTaylor:あなたは紳士であり学者です!
クラウディ

AAAMではAAABAなくである必要がありBAAABますよね?
ちょうど半分14年

18

Bash + Linuxコマンドラインユーティリティ、43バイト

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

これは、以下の私の答えと同様の手法を使用しますが、ベース16でカウントし、を含むすべての「名前」0eまたはf3つ以上の連続する数字を持つものを取り除きます。

次のように僧kのアルファベットに変換します。

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

これは実行に時間がかかりますが、正しいと思います。

dc14 ^ 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ます。必要に応じて、テストするために小さい数値で試してください。

説明:

  • {... }¨⍳91〜9の各番号に対して:
    • ⍳13*⍵:1〜のすべての数値を取得 13^⍵
    • ¯1⌽:1(ので、我々は持って左にリストを回転させ13^⍵12、...、 13^⍵-1、これに変わる0, 1, 2 ...モジュロ13^⍵)。
    • (⍵/13)⊤数字を使用して基数13の各数値をエンコードします
    • ⎕A[1+... ]:1つを追加し(配列は1から始まる)、⎕A(アルファベット)で検索
    • ↓⍉:行列を列に沿ったベクトルのベクトルに変換します。
  • Z←⊃,/:ベクトルの各内部ベクトルを結合し、可能な名前のリストを提供します(ただし、まだルールを満たしていません)。
  • {... :名前ごとに、4回繰り返される文字ルールを満たしているかどうかをテストします。
    • 4/¨⎕A[⍳13]:各文字について、その文字の4つの文字列を生成します
    • ⍷∘⍵¨:各文字列について、それが存在するかどうかをテストします
    • ∨/,↑:これらのすべてのテストの論理的または
    • ~:そして、それを逆にします。つまり、それは1ルールを満たし、そうではないことを意味し0ます。
  • Z/⍨Zルールを満たすすべての要素から選択
  • :個別の行にそれぞれを表示します

9
がっかりだよ。その評判を考えると、APLにはこのための1文字のソリューションがあり、キーボードは入力できないと思うでしょう。
マーク14年

7
@マーク、APLにはそれがあると確信していますが、そのキャラクターが何であるかは誰にもわかりません:)
ポールドレイパー14年

1
これを石の上に書くべきであり、将来の人間がこれを見つけたとき、彼らはそれを単なる原始的な書き言葉だと思うかもしれません。
シンカウハングス14年

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

シバンを1バイトとしてカウントします。

これは、歴史家の答えの緩やかな翻訳です。

A..1x9少し奇妙です。これはの省略形です'A'..'111111111'。アキュムレータは実際には最終値に到達しません(大文字のみが含まれます)が、9文字より長くなると終了します。これは、たとえば、1x4代わりに使用してテストできます。


尊敬!なぜ私はそれを考えなかったのですか?;)
ザイド14

また、Rubyは、範囲全体を作成する必要がないことに注意してください。私のコメントのコードが非常に大量のメモリを必要とする唯一の理由は、範囲を配列に変換するためです(使用できるようにするためArray#-)。
Ventero 14

@Ventero Ahhはい、grepそうします。私はRubyに完全には流notではありません。
primo 14

6

Pyg(長すぎる、ゴルフ用に作られた言語の場合)

ささやき: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.

JSレイヤー(および配列を格納するのに十分なメモリ)として、ECMAScript 2017の標準実装を想定していArrayます。ここで、オブジェクトは最大の2**53-1長さを持つことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.