チューリング完全言語通訳


42

私はそれは非常にクールだと思っ挑戦は作ることですインタプリタのためのチューリング完全お好みの言語を。

ルールは簡単です:

  1. このチャレンジよりも新しい言語であっても、任意の言語を使用してこのインタープリターを作成できます。
  2. チューリング完全言語は、記述している言語と同じでない限り使用できます。
  3. eval関数を使用するなど、コードを単純に評価することはできません。
  4. あなたがこれにどのようにアプローチしたかの説明は素晴らしいでしょうが、必須ではありません。
  5. これはバイト単位で記録されます。
  6. 各提出物は完全に機能している必要があります。つまり、選択した言語のすべての機能が存在する必要があります。

簡単に言えば:

あなたの仕事は、あなたが選んだ言語でチューリング完全言語用の実用的なインタプリタを作成することです。

幸運を!


3
また、些細evalな解決策を防ぐために、実装言語は実装に使用する言語とは異なる必要があるというルールを推奨します。
ETHproductions

1
実際、eval一部の言語には別の言語のコードを評価するためのビルトイン機能があるため、コマンド/機能を禁止することもできます。
ETHproductions

2
@arodebaugh将来の課題については、アイデアをサンドボックスに投稿して、フィードバックを取得し、そのような詳細を解決してから、課題を公開して回答を得ることができます。
マーティンエンダー

1
OK、おそらくもう少し具体的になり、Bash + perlのような他の些細な答えを避けるために、「何らかの方法でコードを単純に実行することはできません」のようなことを言うべきです。
ETHproductions

回答:


16

Brachylog(2)→ 通信問題の投稿、9バイト

~h=∋ᵐ\cᵐ=

オンラインでお試しください!

入力は、文字列のリストのリストです。(Wikipediaで定義されているPost通信の問題では、内部リストにはそれぞれ2つの要素がありますが、このプログラムは実際には任意の数の要素への一般化を処理できます。)解決策が見つかりました。Post通信の問題は、チューリングマシンをシミュレートできることが知られており、したがって、それに対するブルートフォースソリューションはチューリング完全です。プログラムではなく関数として実行すると、実際には意味のある出力も生成されます。

上記のTIOリンクのプログラムは、[["a","baa"],["ab","aa"],["bba","bb"]]Wikipediaからコピーしたものです。解決策(プログラムがかなり迅速に見つける)は["bbaabbbaa","bbaabbbaa"]です。

説明

これは、Post通信の問題をBrachylogに直接変換したものです。

~h=∋ᵐ\cᵐ=
~h         Find {the shortest possible} list which starts with {the input}
  =        and for which all elements are equal
   ∋ᵐ      such that taking an element of each element,
     \cᵐ   and concatenating elements in corresponding positions,
        =  produces a list all of whose elements are equal.

基本的に、入力を繰り返しコピーするリストを作成し(可能な限り少なく、ブルートフォースするときに可能性を見逃さないことを意味します)、各コピーから1つの要素を取得し、対応する要素を連結します(Post通信のように)問題)。


1
そして、通常の「意味があり、バイトを節約するものの、Brachylogインタープリターはそれを処理できない」ことの要約:最初の5バイトは~dp、チューリング完全)、ただし、Brachylogインタープリターはdまだ反転する方法を知りません。

12

ゼリー →「トランスポーズに最小値を追加」、5 4バイト

+"Ṃẞ

オンラインでお試しください!(タイムアウトを回避するために、1回のみの反復を実行します)

非常に単純なチューリング完全な構成:正方行列をプログラムとして使用し、辞書編集的に最小の行を特定し、最初の行の各要素を辞書編集的に最小の最初の要素、2番目の行の各要素ずつ増やして永久にループします辞書編集的に最小の2番目の要素など。(Jellyプログラムは「+"対応する要素を{入力と} 最小{元の} ループを追加」します。これは、Z+ṂZßまったく同じことをした以前のプログラムより1バイト短いです。明らかに、ゴルフに集中する必要がありました。ジェリー、実装された言語をただゴルフするだけではありません。)

結果の言語はカンガルーとほぼ同じ理由でチューリング完全です。各行の最初の要素はスキップカウントのように機能します(各コマンドのスキップカウントがスキップされる時間を減らす代わりに、実行される各コマンドのスキップカウントを増やし、スキップカウントが最も低いコマンドを探します)スキップカウントがゼロのコマンドよりも、これは同じことです)。この最初の要素が他の要素(各コマンドのマルチセットに各コマンドが表示される回数を表す)よりも高いことを確認して、最初の行が最小になることがないようにします。最初の行の残りの部分はガベージになります。残っている唯一の問題は、スキップカウントが等しいコマンドが順番に周期的に実行される方法をモデル化することですが、すべてのスキップカウントに大きな定数を掛けてから、小さな「初期」タイブレークとして機能する最初の列までカウントをスキップします。これにより、「スキップされないコマンドが順番に周期的に実行される」のではなく、「最初のスキップされないコマンドが実行される」タイブレークが得られますが、カンガルーのチューリング完全性の構築はこの違いを気にしません。


10

ConwayのGame of Life、64バイトを解釈するMathematica

CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}~Nest~##&

ConwayのGame of Lifeはチューリング完全であることが知られています。そしてセルオートマトンは、スティーブン・ウルフラムの真の強迫観念です。CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}ConwayのGame of Lifeの1ステップに従って、0と1の2次元配列を変換するルールです。(デフォルトの振る舞いは、この配列がそのエッジの周りをラップするので、実際には離散トーラスです)。~Nest~##&このルールを関数に変換しnます。nGame of Lifeルールの反復の結果。

あなた自身の楽しみのために、ラップされたバージョンを使用することができます

b = RandomInteger[1,{50,50}];
Manipulate[ArrayPlot[
  CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}~Nest~##&
    [b, n] ]
, {{n,0}, 0, 100, 1}]

50x50のボードで100世代にわたってスクロールします。


私が正しく理解している場合、これは固定ボードサイズを持っていますか?その場合、チューリング完全にすることはできないと思いますか?
DLosc

関数への特定の呼び出しは、ボードサイズが固定されていますが、そのボードサイズは任意に大きくすることができます。(投稿の後半では、実際のコード自体ではなく、動作中のコードを観察する例を説明していることに注意してください。)
グレッグマーティン

私が言っていることは、GoLがチューリング完全であるためには、無限に成長するパターンに対応しなければならないということです。(グライダーガンなど。)この実装が配列をあるステップから別のステップに拡大できず、代わりにトロイダルにラップする場合、無限成長テストに失敗します。
DLosc

確かに、それは合理的な視点です。しかし、物理コンピューターでのプログラミング言語の実装は、そのテストさえ満足しません!1つは、ますます多くのメモリを備えた(仮想の)一連の物理コンピューターに満足し、それぞれがその計算可能な関数のもう1つの値を計算できることです。ただし、その時点では、そのようなGoLプログラムへの(仮説的な)入力シーケンスに等しく満足する必要があります。
グレッグマーティン

9

CTを解釈するタートルード、49バイト

これをゴルフできるかもしれない

また、これは有用なものを何も出力しません。指定されたCTプログラムが停止した場合にのみ、停止します。

これは私が実際に少し前に作ったものです(そして今、いくつかのゴルフをしました)

!-l[*+.r_]' !l[ l]r[ u.(;d' u)d(1[ r].[ l])( r)+]

使い方:

Turtlèdはグリッドセルを使用します。「グリッドに何かを書く」と言うとき、文字の連続したグループがグリッドに配置されることを意味します。例

[ ][ ][ ][ ][ ][ ][ ]
[ ][H][E][L][L][O][ ]
[ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ]

プログラムに

データが最初に入力されます。

!-l[*+.r_]' 

これは本質的に猫のプログラムです。入力をグリッドに書き込みます。

その後、コマンドが入力されます:

!

これらのコマンドで行うこと:

これらのコマンドは「プロダクション」です。左端のデータビットが1の場合、プロダクションをデータ文字列の末尾にコピーします。それ以外の場合は何も起こりません。次に、左端のデータビットが削除され、次の左端のデータビットを持つ次のプロダクションが使用されます。データ文字列にビットがない場合、プログラムは停止します。これらのプロダクションを実行する方法は、プロダクションのビットとエンドを別々に処理することです。これが私たちのプログラムが行うことです。コマンド文字列からデータ文字列の最後にビットを個別にコピーし、データ文字列からビットを個別に削除します

このプログラムがどのように行うかについて。コマンドを入力した後、タートル/グリッドポインターはデータ文字列の左端のビットに戻ります。その後、ループに入ります

[ u.(;d' u)d(1[ r].[ l])( r)+]

このループで行われることは、左端のデータ文字列から上に移動し、現在のコマンド文字(u。)を書き留めることです。プロダクションの最後である;の場合、下に移動し、その下の左端のデータビットを削除し、上に戻ります((;d' u))。その後、いずれにせよ、1つ下に移動します(d)。ビットが削除されていない場合、最後のコマンドからビットをコピーするかどうかを確認する必要があることを意味します。したがって、左端のデータビットであるか、この文字であった文字が1の場合、データ文字列の右端の最後に移動し、コマンド文字列からビットをコピーし、左端のデータの左のスペースに戻りますビット((1[ r].[ l]))。現在は、左端のデータビット(ゼロ)または左端のデータビットの左側にあります。そのため、スペース(( r))。次に、コマンドポインターをインクリメントして、ループの次の反復で次のコマンドを書き留めます。データ文字列がもうない場合、これはスペース上にあり、ループが終了することを意味します。それ以外の場合は、ループを再実行します。


これ以上ゴルフしてみてください!
アロデボー

9

PerlThree Star Programmerバリアント、26 + 1 = 27バイト

++$a[$a[$a[$_]]]for@F;redo

オンラインでお試しください!(このリンクには、TIOがタイムアウトしないように設定された回数の反復後にプログラムを終了するヘッダーが含まれ、反復ごとに内部状態を出力します(そのため、観察可能なことを行います)。)

で実行します-a(1バイトのペナルティ。-M5.010生成する前に適合することができるため-aM5.010)。

具体的には、これはコマンドがスペースで区切られ、I / O拡張なしでファイルにコメントが許可されないThree Star Programmerを実装します。(これらの変更は、明らかに言語のチューリング完全性に影響を与えません。)オンラインの3つ星プログラマーのチューリング完全性の証明はありませんが、チューリング完全です(チューリング完全性のスケッチ証明を共有しています) -他のesoprogrammerとの完全性。ただし、最初のショックを乗り越えてから実際にプログラムするのはかなり簡単だとわかったときに、言語の作業を停止しました。

プログラムはあまり説明する必要はありません。Three Star Programmerの仕様は非常に単純であり、これはそれを直接翻訳したものです。唯一の微妙な点@Fは、配列形式でのプログラムへの入力です(これはの結果です-a)。そしてredo、それは暗黙のループ(のも結果にだとして、プログラム全体を繰り返すことになります-a)。


1
矢印が「解釈」よりも「に還元」を意味する方が理にかなっていると思います。
キントピア

9

x86アセンブリ(Intel構文/ MASM)-Brainfuck 2127バイト。

まだゴルフできる

.386
.model flat,stdcall
.stack 4096
include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib
ExitProcess proto,dwExitCode:dword
.data
bfsrc BYTE 200 dup(0) 
bfcells BYTE 100 dup(0) 
loopStack DD 5 dup(0) 
charBuf BYTE 5 dup(0) 
newline BYTE 10,0 
prompt BYTE "$",0 
hr BYTE 50 dup('-'),0 
space BYTE ' ',0
.code
EvalBf proc
    start:
    invoke StdOut, addr prompt
    invoke StdIn, addr bfsrc,200
    cmp bfsrc,0
    je exit
    mov eax,0 
    mov ebx,0 
    mov ecx,0 
    processInstruction:
    cmp BYTE PTR bfsrc[ebx], '+'
    je plus
    cmp BYTE PTR bfsrc[ebx], '-'
    je minus
    cmp BYTE PTR bfsrc[ebx], '>'
    je fwd
    cmp BYTE PTR bfsrc[ebx], '<'
    je back
    cmp BYTE PTR bfsrc[ebx], '['
    je open
    cmp BYTE PTR bfsrc[ebx], ']'
    je close
    cmp BYTE PTR bfsrc[ebx], '.'
    je dot
    jmp processNextInstruction
    plus:
    inc BYTE PTR bfcells[eax]
    jmp processNextInstruction
    minus:
    dec BYTE PTR bfcells[eax]
    jmp processNextInstruction
    fwd:
    inc eax
    jmp processNextInstruction
    back:
    dec eax
    jmp processNextInstruction
    open:
    mov loopStack[ecx*4],ebx
    inc ecx
    jmp processNextInstruction
    close:
    dec ecx
    cmp BYTE PTR bfcells[eax], 0
    je processNextInstruction
    mov ebx,loopStack[ecx*4]
    inc ecx
    jmp processNextInstruction
    dot:
    mov dl, BYTE PTR bfcells[eax]
    mov BYTE PTR charBuf[0], dl
    mov BYTE PTR charBuf[1],0anything
    push eax
    push ecx
    invoke StdOut, addr charBuf
    pop ecx
    pop eax
    jmp processNextInstruction
    processNextInstruction:
    inc ebx
    cmp BYTE PTR bfsrc[ebx], 0
    je done
    jmp processInstruction
    done:
    invoke StdOut, addr newline
    mov eax, 0
    printNext:
    cmp eax, 100
    jge reset
    push eax
    invoke dwtoa, BYTE PTR bfcells[eax], addr charBuf
    invoke StdOut, addr charBuf
    invoke StdOut, addr space
    pop eax
    inc eax
    jmp printNext
    reset:
    invoke StdOut, addr newline
    invoke StdOut, addr hr
    invoke StdOut, addr newline
    jmp start

    exit:
    invoke ExitProcess,0
EvalBf endp
end EvalBf

3
通常、アセンブリの回答は、生成されるマシンコードのサイズでカウントされるため、アセンブリをまったくゴルフする必要はなく、命令の数/サイズを最小化するだけです。
ロバートフレイザー

@RobertFraserうーん、それを数える方法がわからない:P-
クリストファー

3
実際、最初は「Brainfuckで実装されたx86 asm」とタイトルを読んで、少し感銘を受けました:)
ケツァルコアトル

@ケツァルコアトルそれは印象的だろう
クリストファー

1
plsゴルフ変数/ラベル名ty
ASCIIのみ

8

PIP解釈環状タグシステム、16のバイト

YqWyyPBg@++vXPOy

タグシステムのプロダクションをコマンドライン引数として受け取り、stdinからの初期データ文字列を取得します。

上記のコードは出力を生成しないため、確認が困難です(したがって、観察可能な動作は「終了」と「終了しない」だけです)。したがって、各ステップの後にデータ文字列を出力し、20ステップ後に終了するようにTIOが無限ループからの大量の出力を処理する必要がないように、次のようなバージョンがあります。

サイクリックタグシステム

サイクリックタグシステムは、非常にシンプルでありながらチューリング完全な計算モデルです。それらはデータ文字列の操作を定義するプロダクションのリストから成ります。プロダクションとデータ文字列は1と0で構成されます。

各ステップで、データ文字列の左端の文字が削除されます。

  • 文字が1の場合、現在のプロダクションがデータ文字列の右側に追加されます。
  • 文字が0の場合、何も追加されません。

いずれの場合も、現在の生産はリスト内の次の生産に循環的に移動します。最後の生産にいた場合は、最初の生産にループします。データ文字列が空になるまで実行が継続されます。

説明

                  g is list of cmdline args; v is -1 (implicit)
 q                Read a line of stdin for the data string
Y                 and yank it into the y variable
  Wy              While data string is nonempty:
       g@++v       Retrieve the next production from g (using cyclic indexing)
             POy   Pop the first character of y
            X      String-multiply: result is the production if the first character of y
                   was 1, or empty string if it was 0
    yPB            Push that string to the back end of y

ちょっと、データ文字列を入力する必要がないことを思い出しました。単に1ソースになります:このarxiv.org/abs/1312.6700へのesolangsリンク。私はすぐに答えを編集します、そしてこれがあなたの答えに役立つなら(あなたの入力は実際には十分にゴルフっぽいようです)
破壊可能なレモン

8

反復一般化Collat​​z関数 -> Python 2、46バイト

a,b,x,m=input()
while-~x%m:x=x/m*a[x%m]+b[x%m]

m-1 aとbのリスト、開始値x、および除数mを使用してこの関数を呼び出します。これらはまとめてIGCFの「プログラム」を構成します。3番目の配列を使用して停止するモジュラスを示すのではなく、モジュラスがm-1のときはいつでも停止します。この単純化により、特定のFractranプログラムをこの亜種に変換するのに余分な労力が必要になる場合がありますが、インタープリターの数バイトが節約されます。

オンラインでお試しください!このTIOは、この言語で5 + 5を追加する方法を示しています。プログラムa = [3]、b = [0]、m = 2は加算を行い、7776 = 2 ^ 5 * 3 ^ 5で開始すると最終的に59049 = 3 ^ 10になります。


いい仕事だ。私は懸賞金が、良い仕事勝つことを望んでいた
クリストファー

7

ResPlicateバリアント-> Python 2、47バイト

l=input()
while l:l=l[2+l[0]:]+l[2:2+l[0]]*l[1]

この関数はResPlicateのバリアントを解釈します

  • プログラムは、偶数のインデックスで偶数の要素を持つ偶数の長さのpythonリストです。
  • I / Oなし。
  • キューの残りに存在する値よりも多くの値をコピーしようとすると、単にキューの残りがコピーされます(つまり、コピーされたビットには必要な長さまでゼロが埋め込まれません)。

最後の変更は、一部のResPlicateプログラム(最初の条件を満たす)がこのバリアントで同じ動作をしないことを意味しますが、幸いなことに、BCTインタープリターは削除された機能を必要としないため、言語はTCのままです。

オンラインでお試しください!このTIOには、動作することを示すために印刷が挿入されており、1秒後にプログラムを強制終了するヘッダーと、TIOがその1秒間で処理できるよりも多くの出力を生成する例があります。


2
どうしてl=input()?1バイト短くなります。
-feersum

7

Perl -aI / Dマシン、24バイト

$p=$a[$p]+=$_ for@F;redo

オンラインでお試しください!(内部状態を出力し、10回の反復後に停止するヘッダーが含まれているため、動作を確認できます)

言語について

過去数日間、I / Dマシンでの作業に費やしました。これは、非常に単純なプログラミング言語に対する私の最新のアイデアの1つです。次のように機能します。データストレージは無制限のRAMで構成され、最初はすべてゼロです。各要素は無制限の整数を格納できます(実際には、ほとんどのI / Dマシンプログラムはそれらのほとんどに小さな整数のみを格納し、大きなアドレスを持つセルをアドレス指定する方法としてのみ無制限の整数を使用します)。セルを指すデータポインターもあります(つまり、アドレスをセルとして保持します)。最初はゼロです。

次の2つのコマンドのみがあります。

  • I:データポインターが指すセルをインクリメントします。(データポインター自体は変更されません。)
  • D:データポインターを逆参照します。つまり、データポインターが指すセルの値を読み取ります。次に、読み直した結果の値をデータポインターに保存します。

実行とは、プログラムをループ内で永久に繰り返し実行することです。

この単純な言語がチューリング完全であることはかなり驚くべきことなので、私はそれを証明しようと取り組んできました。これが証拠です。これは、非常によく似た言語であるThree Star Programmerの証明にかなり似ています(ただし、よりシンプルです)(実際、このサブミッションは、プログラムの周りの同じ基本OISC "シェル"を使用します。実装される実際の命令のみが異なります)。

プログラムについて

使用法

入力は標準入力で指定する必要があり、コメントなしのRLE / OISC構​​文を使用したI / Dマシンプログラムです。(I / Dマシンには2つの異なる同等の構文がありますが、ゴルフのために、このプログラムはそのうちの1つのみをサポートします。)この構文では、プログラムはIコマンド間のDコマンドの実行の長さを表す10進数のシーケンスです。(2つ以上の連続したDコマンドを指定するにはI、それらの間に「0 コマンドの実行」を配置します。そのため、構文は完全に一般的です。)

説明

プログラムからわかるように、これはIおよびDコマンドを個別に実装していません。実際、これは(ごくわずかな)最適化インタープリターです(純粋にこの方法で記述した方が短いためです)。重要なのは、n個のインクリメントコマンドを実行すると、データポインターのターゲットがn回インクリメントされる、つまりnが追加されることを確認することです。また、メモリに0を追加しても効果がないため、0インクリメントコマンドの実行もこの方法で実装できます。したがって、実際に実装する操作は、run-of- Isとaの実装を交互に行うことDです。または、言い換えると、「nデータポインタが指す値に(データポインタが指す値に格納する)、データポインタが指す値を読み取り、データポインタに格納します。これは明らかに必要以上に冗長です。そして、「データポインターが指す値にnを追加し、その値をデータポインターのターゲットとデータポインターの両方に格納する」ことで、これをさらに簡素化できます。

それが私たちのプログラムの中核になります。$aRAMを格納するために配列を使用$pし、データポインターとして(配列へのインデックス):

$p=$a[$p]+=$_
         + $_  add {the run length}
   $a[$p]      to the element of $a pointed to by $p
   $a[$p] =    storing the result back into that element
$p=            and also in the pointer itself

便利なことに、Perlは、初期化されていない配列要素を数字のように扱うと0として解釈するため、必要な明示的なコードがなくても、配列はゼロに遅延初期化されます。(潜在的な問題の1つは、数値が大きくなったときの数値の精度です。ただし、使用されている配列の量がマシンのアドレススペース(Perl整数はポインターを保持するのに十分な大きさ)を超えた場合にのみ発生します)理想的なマシンで。)

最後に、このプログラムをいくつかのループに配置するだけです。for@F組み合わせるループ、-aコマンドラインオプション、標準入力の分野にわたる意志ループ(ここでは「フィールド」のデフォルトの定義は空白で分割されます)。redoループは、I / Dマシンの意味で必要とされるプログラムは、繰り返しループ内で実行するようになります(標準入力の読み取り、便利、以外の)暗黙のループでプログラム全体を配置します。


お帰りなさい!インタプリタのフラグをスコアリングする必要がなくなりました-a。これは「Perl with 」であることに注意してください。codegolf.meta.stackexchange.com/a/14339/9365
Dom Hastings

6

ゼリー2タグシステム、8バイト

µḢị⁴⁸;Ḋß

オンラインでお試しください!

実用的な言語を好む賞金がありますが、元のタスクを達成しようとしている間に勝つことを試みることもできます(自分の賞金を正確に獲得できないため)。

チューリングの完全性には必要ないため、停止状態のないタグシステムのバリアントを実装します。状態には1から連続して番号が付けられ、最初の文字列はプログラムの前に来ます。

例えば、ウィキペディアは、タグシステムの例を示し、{ abc}、{ abcbacaaa}の初期文字列とaaa、この入力フォーマットで、それはです[1,1,1][[2,3],[1],[1,1,1]]。(タグシステムには固定構文がありません。これは合理的な方法のようです。)

TIOリンクには、プログラムが実際に動作していることを示すために、追加(「内部状態と改行を標準出力に書き込む」)があります。

説明

µḢị⁴⁸;Ḋß
           {implicit: initialise internal state from first argument}
µ          Disregard the second command-line argument by default
 Ḣ         Take the first element, removing it from the internal state
  ị⁴       Use the value to index into the second argument
    ⁸;     Prepend (the rest of) the internal state
      Ḋ    Discard the first element of the internal state
       ß   Loop forever

6

チューリングマシンに実装されたBF / P」、842バイト

遷移表(長さのためにリンクされています)

遷移表、ゴルフの少ないバージョン

使用したチューリングマシンシミュレータ

これは確かに長い間賞を獲得するものではありませんが、BFはチューリングマシンに非常に似ているため、私がずっとやりたかったことです。各セルには0x0- からの値が格納されます0xF。ただし、幅はブラウザをクラッシュさせることなくTuring MachineのWebサイトで使用できる範囲です。,そして.、それはもう少し真BFよりP」のようですので、機能(入力および出力)は、定義されていません。

実行するには、遷移表をチューリングマシンシミュレータに貼り付け、入力をBFコードに設定して、実行を押します。

TMのテープには、BFコードとBFデータの両方が保存され、中央に1つのスペースがあります。現在実行中の文字([-> (など)を変更することでコード内の位置^と、セルの前にあるデータ内の位置を追跡します。コマンド文字を読み取ると、キャレットに達するまで移動し、1つのセルを右に移動して、適切な機能を実行します。それから戻って、BFコードで「変更された」コマンド文字の1つを探し、次の文字に進み、プロセス全体を繰り返します。コードがなくなると停止します。

それがどのように機能するかを理解する最良の方法は、非ゴルフバージョンを実行し、それをステップモードにし、どの行が他の人につながり、各状態/行のブロックが何をするかを見ることです。

ゴルフバージョンと非ゴルフバージョンは、動作方法がまったく同じですが、非ゴルフバージョンはより人間にわかりやすい名前を持ち、セクションに分かれています。


1
ポストの長さの制限は、遷移表を合わせてより十分にある
ASCIIのみ

6

(2,3)チューリングマシンを実装するC 、236 205バイト(扱いにくい入力を気にしない場合は46 31少ない)

-11バイトのAppleshell、-12バイトのVisualMelon、-7バイトのJohan du Toitに感謝します。

CeilingCatは、144バイトのみを使用するバージョンを作成しました。こちらを参照してください

(ここにいくつかの改行を追加したので、スクロールする必要はありませんが、通常はそれらのほとんどが削除されます)

#define c char
j;i;k;c s,d[256];c main(){c*p=d+128;gets(d);
for(;k<256&&d[k];)d[k++]-=48;for(;++j<256;)
{c t=*p;*p=-t*t+(2-s)*t+1+s;p+=(s^t==0)*2-1;s=s?t%2:!t%3;
for(i=0;++i<256;)printf("%d",d[i]);puts("");}}

オンラインでお試しください!

使用方法:最大256個の1、0、2の文字列を入力して、テープを初期化します。初期化されていない値はゼロになります。(0、1、および2以外の値は未定義の動作を引き起こす可能性があります。)プログラムは256ステップを反復します。反復するステップの数は、コードを変更することで増やすことができますが、明らかに多くの文字が必要になります。

かなり長いエントリですが、これらのいずれかを行うのは初めてで、専用のゴルフ言語を使用しませんでした。予想以上に長くなったとしても、とても楽しかったです。

多くのバイトは入出力の処理からのものであり、NUL、SOH、STXの代わりに0、1、および2を受け入れるようにしたため、全体で42バイトが失われました。(これを変更するにk;は、先頭とfor(;k<256&&d[k];)d[k++]-=48;2行目から削除します。)

トランジションテーブル、特にライン*p=-t*t+(2-s)*t+1+s;(テープの値を設定する)もおそらく圧縮される可能性があります。


1
わあ、これがここでの最初のコードゴルフです!素晴らしい!
ザカリー

次のようにグローバル変数宣言を短縮できます:k,j;c s,d[256];intCで暗黙的です。その後、さらにi3バイトを節約するためにグローバル宣言に移動できます)
-Appleshell

@Appleshellありがとう、それをやる。
a52

forループ内で文字列のヌルターミナルチェックを移動できます。インライニングk++と削除{}カップルより節約バイト:for(;k<256&d[k];)d[k++]-=-48;のでj(値が使用されることはありません)あなたはそれを置き換える(とすることができますちょうどタイムキーパーであるiと)k逆方向にカウントして:あなたが知っているk==256最初のループの後なので、第二にゼロにカウントダウンfor(;k>0;)、これは去るk==-1ので、最後のループはfor(;++k<256;)。(免責事項:私は通常ゴルフC#をしていますが、これはコンパイルされたようです)。
VisualMelon

1
@VisualMelon私は問題を特定しました。で評価されていたためk<256&&d[k]、使用する必要がありました。また、ループの後にあることが保証されなくなったため、256ステップを保証するために、後でループをリセットする必要がありました。(もしあなた(つまり、VisualMelon)に他の提案があれば、おそらくコメントを入れすぎないようにチャットに入れるべきです)&d[k]k==256k256
-a52

5

Fractranを実装するローダ114 112 106バイト

パラメータを再配置することにより、@ fergusqのおかげで1バイト節約

f&n,a{x=1{x=0;(a/" ")()|[_/`/`]|[parseInteger(_[0],_1[1])]|{|q,w|{n*=q/w;x=1}if[n%w<1,x<1]}_,_}while[x>0]}

オンラインでお試しください!

次のように関数を呼び出しますf reference_to_input program。出力は、の場所に保存されinputます。


セミコロンの後e[1]は冗長です。また、パラメーターの順序を変更することで1バイトを節約できますf&n,a
fergusq

@fergusq f&n,aトリックをありがとう、そしてコメントしたときにそのセミコロンを削除しようとしていた:)
Kritixi Lithos

5

Clojure、82 81バイト(チューリングマシン)

更新:からスペースを削除しましたt{} s

#(loop[p 0 t{}s 1](if-let[[S M N](%[(or(t p)0)s])](recur(+ p M)(assoc t p S)N)t))

チューリングマシンをループとして実装し、停止状態に達するとテープを返します。状態遷移規則では、これは遷移状態を省略することで示されます。対応する状態遷移が入力hash-mapから見つからないNためnil、これはsettins になり、後続のものif-letは中止されます%。実際、この状態の値は:abort、0、-1などです。

例3ステート2シンボル忙しいビーバーとUngolfed ウィキペディア

(def f #(loop[pos 0 tape {} state 1]
          (if-let [[sym move next-state](%[(get tape pos 0)state])]
            (do (println [pos tape state])
                (recur(+ pos move)(assoc tape pos sym)next-state))
            tape)))

(f {[0 1] [1  1 2]
    [0 2] [1 -1 1]
    [0 3] [1 -1 2] 
    [1 1] [1 -1 3]
    [1 2] [1  1 2]
    [1 3] [1  1]})

{0 1, 1 1, -1 1, -2 1, -3 1, 2 1}

オンラインでお試しください

6700Kのシングルコアでは、これは5ステートの2シンボルビジービーバー(4,710万ステップ)を約29秒、つまり160万ステップ/秒で実行します。


5

Mヒント、4バイト

Ṅ×ịß

オンラインでお試しください!

TIOリンクは、Esolangページに示されているサンプルTipプログラムで関数を呼び出すためのフッターを追加します(Mの「自動ラッパー」は、関数が有理数または固定小数点数を処理できないかのように関数を呼び出します。どのようにそれを伝えるかを理解していないので、それを実行できるようにするには、関数を完全なプログラムに手動で作成する必要があります。)

これは実際に有用なデバッグ出力を出力します。正確に3つのダイアドで構成されるプログラムがパーサーで特別なケースをトリガーするため、プログラムをMで3バイトで書き込むことはできません。そのため、特別なケースを回避するために追加のコマンドを追加する必要がありました。少なくともそれを作成(改行で印刷)することは、少なくとも有用な目的を与えます。

ıi=1

I / Oを実装しません(halt / no-haltを除く)。I / Oは、Tipの拡張機能であり(言語自体の一部ではありません)、チューリング完全性には必要ありません。

説明/背景

Ṅ×ịß
Ṅ     Print {the left argument} and a newline; also resolves a parser ambiguity
  ị   {The left argument}th element of {the right argument}, wrapping on OoB
 ×    Multiply {the left argument} by {the chosen element}
   ß  Recursive call; arguments: {the product} and {the same right argument}

[1,2,3][1,2,3,1,2,3,1,2,3,…]rx+s、これは多項式であり、多くのゴルフ言語に組み込まれている「ベース変換」は、実際には偽装の汎用多項式評価者です。それで、私たちがしなければならないのは、数字のリストのリストにインデックスを付け、それらをベース変換するだけです。

xx

x(xy)xy。もちろん、チェーンの動作を必要に応じてほぼすべてオーバーライドできますが、これには1バイトのコストがかかり、この質問へのゴルフ言語のエントリは非常に短くなり、1バイトが多くなります。

だから私は振り返り、少し再評価しました。多項式評価の代わりに使用できる演算はありますか?理想的には、可換であるため、引数の順序を心配する必要はありませんか?その後すぐに、Collat​​z関数が必要以上に複雑であることに気付きました。

s

そしてもちろん、ベース変換()とは異なり、乗算(×)は可換であり、したがって引数の順序は関係ありません。したがって、記述する必要があるのは×ị、そしてプログラムを無限再帰に配置するß、そして、チューリング完全な言語があります。右?

(xy)(xy)¹×ịß¹¹ 有用なデバッグ出力を生成するため、適切な選択です。

3バイトは可能ですか?実装および実装された言語のこの特定の選択ではなく、私が何かを見逃していない限り、4、非常に多くのチューリング完全でそれを行うための非常に多くの方法があるので、この時点では確かに何らかの方法で可能だ実装できる言語。


これについてもう少し考えた後、and ではなく×and を使用して、これを3バイトに減らすことができました。結果の言語はTipとまったく同じ言語ではありませんが、同じ理由でかなり似ており、ほぼ確実にチューリング完全です。残念ながら、Mには実装されていません。また、入力のいずれかが非整数の実数である場合、Jellyに任意精度の計算を行わせる方法は見つかりません。ただし、この構造が機能する他のゴルフ言語を知っている人がいれば、気軽に試してみてください。
ais523


4

Brainf ***を解釈するLua、467バイト

b,r,a,i,n,s=0,io.read,{0},1,1,"><+-.,[]"c,f=r(),{function()n=n+1;a[n]=a[n]or 0;end,function()n=n-1;a[n]=a[n]or 0;end,function()a[n]=a[n]+1;end,function()a[n]=a[n]-1;end,function()io.write(string.char(a[n]))end,function()a[n]=io.read():byte()end,function()i=a[n]~=0 and i or c:find("]",i)end,function()if a[n]~=0 then b,x=1,""repeat i=i-1 x=c:sub(i,i)b=x=="["and b-1 or x=="]"and b+1 or b until b==0 and x=="["end end}repeat f[s:find(c:sub(i,i),1,1)]()i=i+1 until i>#c

後でできるスリム化がまだあることはわかっていますが、ここで最初のパスが終了しました。標準入力からBrainfコードを取得します。


2
の+1は、brainsゴルファーが変数のリストに割り当てると常に楽しいものになります。
ザカリー

4

CJam→ResPlicate Variant、15 14 13バイト

@ ais523のおかげで-1バイト

l~{(/((*+e_}h

バリアントはこの回答のバリアントと同じですが、キューから取り出されるアイテムの数がキューの先頭の数より1つ少ない点が異なります。

l~{ ... }h部分だけ入力として配列を受け取り、その配列が空になるまで繰り返します。

メインループの説明:

    e# Stack:             | [3 2 1 1 2 2 2 1]
(   e# Pop first element: | [2 1 1 2 2 2 1] 3
/   e# Split chunks:      | [[2 1 1] [2 2 2] [1]]
(   e# Pop first:         | [[2 2 2] [1]] [2 1 1]
(   e# Pop first:         | [[2 2 2] [1]] [1 1] 2
*   e# Repeat array:      | [[2 2 2] [1]] [1 1 1 1]
+   e# Concatenate:       | [[2 2 2] [1] 1 1 1 1]
e_  e# Flatten:           | [2 2 2 1 1 1 1 1]

ここで実際に増分する必要はありません。元のプログラムでブロックの長さを1増やすように指定するだけです。ResPlicateのチューリング完全性を損なうことはありません(ブロック長と繰り返しカウントが互いに混ざらないTC構造があります)。

3

チップ、20 + 3 = 23バイト(ルール110)

AZZ
>}/a
`)\'E~Zte*f

+3フラグ -z

オンラインでお試しください!

チップには(まだ)ループ機能がないため、この送信は完全ではありません。そのため、出力を入力として渡して、複数の世代をシミュレートする必要があります(もちろん、このループを無期限に実行できますが、 Chipは任意の長い入力を処理できるため、この組み合わせはチューリング完了です。

この実装は、入力を受け取り、ASCII 0sおよび1sの形式で出力を受け取ります。ここでのロジックは次のとおりです。

p := value of left neighbor cell    AZZ
q := value of current cell          AZ
r := value of right neighbor cell   A

q' := ((r xor q) and p) or          >}/a
      ((r or q) and ~p)             `)\'

残りの要素はハウスキーピング用ですe*f。ASCII数字を出力し、E~Zt入力が使い果たされた後2バイト実行を終了します(幅が世代ごとに2ずつ増加するため)。


3

Clojure、75バイト(サイクリックタグシステム)

更新1:に置き換えられsome?ましたnil?

更新2:のSelseブランチの欠落を修正しましたif s

#(loop[[p & P](cycle %)[s & S]%2](if(nil? s)S(recur P(if s(concat S p)S))))

循環タグシステムを実装しnil、プログラムが停止した場合に戻り、それ以外の場合は永久にループします。Clojureは、無限の遅延シーケンス(cycleなど)と破壊で本当に輝いています。1と0は、真と偽の値として示されます。データ文字列がなくなるsとになりnilます。

ゴルフをしていない:

(def f #(loop[[p & P] (cycle %) [s & S] %2 i 5]
          (do
            (pprint [p (concat [s] S)])
            (if (and (some? s) (pos? i))
              (recur P (if s (concat S p) S) (dec i))))))

結果の例:

(f [[false]] [true true])
[[false] (true true)]
[[false] (true false)]
[[false] (false false)]
[[false] (false)]
[[false] (nil)]

(f [[false true true] [true false] [true false true]] [true])
[[false true true] (true)]
[[true false]      (false true true)]
[[true false true] (true true)]
[[false true true] (true true false true)]
[[true false]      (true false true false true true)]
[[true false true] (false true false true true true false)]

2

JavaScript解釈ルール 110、131バイト(99バイト?、28バイト?)

a=(p,q,r)=>q+r+q*r+p*q*r
b=l=>{r="";for(i=0;i<l.length-2;i++)r+=a(l[i],+l[i+1],+l[i+2])%2;return r}
c=(l,n)=>!n?l:c(b(0+l+0),n-1)

あなたが見ることができるように、コードは、3つの機能を定義しabそしてc。おそらく1つの関数にバイトを組み合わせることでバイトを節約することは可能ですが(方法はわかりません)、それらがそれぞれ何らかの意味ですでにこの課題を達成しているので、そこに分離するのは良いことです。

関数aは入力として3つの数値を受け取り、それらの奇妙な多項式を計算します。これらの3つの数値が存在する0場合1、またはそれらが規則110のセルとして見られる場合。の出力のパリティは、a次世代の中間セルの値と見なすことができます。そのため、ある意味では、この単純な関数はすでにルール110の「インタープリター」(28バイト)です。

a=(p,q,r)=>(q+r+q*r+p*q*r)%2

その後、1と0の文字列のすべての文字bを評価する新しい関数を作成できますa。これbは、より良い意味でa、Rule 110インタープリターです。括弧の評価後にmod 2を使用すると、括弧(99バイト)が保存されます。

a=(p,q,r)=>q+r+q*r+p*q*r
b=l=>{r="";for(i=0;i<l.length-2;i++)r+=a(l[i],+l[i+1],+l[i+2])%2;return r}

ルール110を使用して関数を実際に計算するには、ユーザーは開始状態と世代数を指定してから、出力が「表示」されるようにする必要があります。c1と0の文字列と正の整数を受け取る3番目の関数を作成し、それを文字列でn評価bしますn。このように、ルール110はプログラミング言語として実際に見ることができます。プログラムは初期状態と数値nであり、出力はn世代後の状態です。関数cは現在、そのプログラミング言語の実際のインタープリターであるため、この課題の最終的なコードは上記で示したものです。


これは適切なバックグラウンドで110を計算しますか?私の以前の回答は、背景がないため削除されました。
小麦ウィザード

@WheatWizard背景は入力の一部であり、あなたの答えは、そのために削除nbeenてはいけない
イェンスは、レンダリング

背景は無限である必要がありますが、無限に入力できますか?
ウィートウィザード

それは無限である必要はありdoes notの@WheatWizard、それは任意に大きな行うことができなければならない、そしてそれができる
イェンスはレンダリング

1
事前に世代を決定している場合、ルール110はチューリング完全ではなく、私が知っている構成では無限の入力が必要です。誰かが有限の初期状態の構造を見つけたとしても、プログラムを実行する前に必要なメモリや時間を知ることはできません。その場合、停止問題を解決できるからです。
Ørjanヨハンセン

2

JS->改行854バイト

(function(d){var b=0;var n=!0;var c=[];var h=[];var e=0;var l=[];var m=0;var f=2;var a=0;var g=!1;var k=function(a){if(a===1)return!1;if(a%2===0&&a!==2)return!1;if(a%3===0&&a!==3)return!1;if(a%5===0&&a!==5)return!1;if(a%7===0&&a!==7)return!1;for(var b=7;b<d.round(d.sqrt(a))+1;b++)if(a%b===0)return!1;return f=a,!0;};var j=0;var i=0;var o=function(q){var o=d.__split(q,'\n');d.println(o);for(var n=0;n<o.length;n++)if(n>=f^2&&n<=f+1^2&&k(n)){f=n;for(var p=0;p<o[n].length;p++){if(o[n]==='+'&&(a+=c[b],b++),o[n]==='-')if(g===!0&&a<=0)break;else a-=c[b],b++;if(o[n]==='*'&&(a*=c[b],b++),o[n]==='/'&&(a/=c[b],b++),o[n]==='s'&&(a=d.sqrt(a)),o[n]==='%'&&(a%=c[b],b++),o[n]==='a'&&l.push(a),o[n]==='g'&&(a=c[b],b++),o[n]==='q'&&c.push(a),o[n]==='i'&&a++,o[n]==='d')if(g===!0&&a<=0)break;else a--;o[n]==='r'&&(g=!0),o[n]==='w'&&(g=!1),o[n]==='['&&(j=n),o[n]===']'&&a>0&&(n=j,h[e]--),o[n]==='{'&&(i=n),o[n]==='}'&&h[e]>0&&(n=i,h[e]--),m=a,o[n]==='k'&&e++;}}};});

グーグルのおかげでスーパーゴルフ。


この答えを間違った課題に投稿したと思います。このチャレンジに投稿するつもりでしたか?

1
その場合、異なる勝利条件を目指すために実装を変更する必要があります。これは人気のコンテストではなくコードゴルフです。たとえば、明らかに短くなる可能性のある変数名がたくさんあるため、このソリューションは深刻な候補ではありません。とりあえず削除してから、ゴルフをする時間があるときに元に戻してください。

1
それにもかかわらず、勝利条件のために最適化するための真剣な試みをしない答えは規則に反しています。これは、ルールに準拠させるまで削除するのに十分な理由です。

1
あなたはすべて組み合わせることができvar文を:var b=0,n=!0,c=[],h=[],e=0,l=[],m=0,f=2,a=0,g=!1;
Esolangingフルーツ

1
Plsはすべて削除varTYを
ASCIIのみ

1

Clojure、87バイト(ルール110)

パリティコードのクレジットはJens Rendersに送られます!私はこれをどう表現するかについて本当に苦労し[p q r]ていたので、バイナリから整数に変換してルックアップテーブルを使用しました。

#(iterate(fn[S](for[[p q r](partition 3 1(concat[0]S[0]))](mod(+ q(* q(+ 1 p)r)r)2)))%)

ここでpartition、Clojureの構造化により、ロジックアプリケーションは非常に単純になります。この関数は状態の無限のシーケンスを返すため、呼び出し側はtake必要な数だけnth、または特定の状態にスキップするだけです。ゼロのパディングが1つではなく2つの要素であった場合、境界の問題を回避して、テープは常に大きくなります。現在は元の幅のままです。

例:

(def f #(iterate(fn[S](for[[p q r](partition 3 1(concat[0]S[0]))](mod(+ q(* q(+ 1 p)r)r)2)))%))

(pprint (take 5 (f '(0 0 0 0 0 1 1 1 0 0 1 0 0))))
((0 0 0 0 0 1 1 1 0 0 1 0 0)
 (0 0 0 0 1 1 0 1 0 1 1 0 0)
 (0 0 0 1 1 1 1 1 1 1 1 0 0)
 (0 0 1 1 0 0 0 0 0 0 1 0 0)
 (0 1 1 1 0 0 0 0 0 1 1 0 0))

1
元の幅でしか作業しない場合、これはチューリング完全にはなりえません。これは、メモリストレージが有限であるためです。(実際、ルール110の既知のチューリング完全性の構造はすべて、プログラムがユーザー入力から指定されたパターンを持つように幅を拡張するために使用される「パディング」を必要とします。ゼロを使​​用します。)

それで、そのシミュレーションはかなり難しくなります。Clojure cycleは無限のパディングパターンを構築できますが、最初のステップの実行には無限の時間がかかります:/
NikoNyrh

考えてみると、これらのパディングパターンを追加の引数として使用し、シミュレートされたテープを左右に1ブロックずつ拡張するのはそれほど難しくありません。ここでの情報の速度は1ブロック/反復なので、非対称構造を持つ中央ブロックの周りの「ライトコーン」をシミュレートするだけです。(CMIIW)
ニコニール

1

APL(Dyalog)Fractranバリアント、15バイト

(⊃0~⍨××0=1|×)⍣≡

オンラインでお試しください!

この関数は、分子と分母を含む2つのリストではなく、数値のリストとして有理数を取り、プログラムが終了した場合に結果を出力します。これにより、プログラムの最後に合理的な1/1(= 1)を持つFractranのバリアントが実装されます。1がチューリング完全性に影響を与えることはありません(私が理解している限り)。プログラムへの入力は、他の合理性が機能しない場合にのみ1に到達し、機能する場合、入力は変更されません。これは、関数がいつ終了するかを知るためにのみ使用されます。

TIOリンクは、最初の入力で(プログラムが終了しないように出力を確認できるように)2回繰り返し関数を実行し、完了するまで2番目の入力を実行し、その後出力を返します。

(⊃0~⍨××0=1|×)⍣≡ と呼ばれる左引数として有理数のリストを取り、⊢と呼ばれる右引数として入力を取ります

(⊃0~⍨××0=1|×) ファンクショントレイン

  • 1|××⊣とproductの積の小数点以下の部分(モジュロ1)を取得します

  • 0= 0に等しいですか?

  • ×× この結果に⊣×⊢を掛けます。有理×⊢が整数でない場合は、0に置き換えられます

  • 0~⍨ すべての0を削除します

  • 最初の要素を取得する

入力が変更されなくなるまでループします。その結果は(⊃0~⍨××0=1|×)入力として再利用されるため、(最後の1の結果として)変更が停止すると、プログラムは停止します。


1

JavaScript:ラムダ計算(123 114)

DuplesでDebruijn Indiciesを使用して表されます。

V=function b(c,d){if(!isNaN(c)){for(;--c;)d=d[1];return d[0]}return 0==c[0]?e=>b(c[1],[e,d]):b(c[0],d)(b(c[1],d))}

Sコンビネータは [0, [0, [0, [[3, 1], [2, 1]]]]]

Kは [0, [0, 2]]

私は [0, 1]

編集:に置き換え"number"==typeof cて9バイトを削った!isNaN(c)


0

APL(Dyalog Unicode)、15 バイトSBCS

一般化された1次元セルラーオートマトンエグゼキューターを実装する完全なプログラム。これには、チューリング完全なルール110が含まれます。初期状態、反復回数(または安定{⍵≡⎕←⍺}するまで続行するか、安定するまですべての中間値を表示する)、およびルールセットの入力を求めます。

⎕∊⍨∘(⊢∘⊂⌺3)⍣⎕⊢⎕

オンラインでお試しください!(ルール110の4回の繰り返し)

 初期状態のプロンプト

 それをもたらす(状態を反復回数から分離する)

⍣⎕ 反復回数の入力を求め、次の関数を何度も適用します。

() 次の暗黙関数を適用します。

  ⌺3 すべての長さ3の近傍を取得し(エッジにあるかどうかに関する情報を含む)、次の暗黙関数を各ペアに適用します。

    近所を囲む

    そして

    それをもたらす(端にいることに関する情報を捨てる)

 それから

∊⍨ 彼らがのメンバーであるかどうかを確認してください

 次の反復でオンになる近隣のリストのプロンプト

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