ここにあります:
1. Brainfuck言語インタープリター
2.チューリングマシン
まず、 SWI-Prologといくつかの空き時間が必要です。
タスク1. Brainfuck言語インタープリター
Wikipediaからのコピーペーストから始めましょう。
Brainfuckは最も有名な難解なプログラミング言語の1つで、1993年にUrban Mullerが楽しみのために作り出したものです。 この言語には8つのコマンドがあり、各コマンドは1文字で記述されています。 Brainfuckプログラムのソースコードは、追加の構文のないこれらの文字のシーケンスです。
Brainfuckコマンドによって制御されるマシンは、順序付けられたセルのセットと、チューリングマシンのテープとヘッドに似た現在のセルへのポインタで構成されます。 また、入力ストリームと出力ストリームを介して外部と通信するためのデバイス(コマンドを参照してください。)を意味します。
コマンドとその説明:
- >次のセルに移動
- <前のセルに移動
- +現在のセルの値を1増やす
- -現在のセルの値を1減らす
- 。 現在のセルから値を出力
- 、外部から値を入力し、現在のセルに保存します
- [現在のセルの値がゼロの場合、プログラムテキストで対応するセルの次のセルに進みます](ネストを含む)
- ]現在のセルの値がゼロでない場合、プログラムテキストで記号[(ネストを考慮に入れて)に戻る
テープはデータベースの形で提示されます
データ(アドレス、値)。
セルアドレスで表される頭
pos(アドレス)。
実際にコメント付きのコード:
% , cout:- % pos(Addr), % data(Addr,Value), % put_char([Value]). % . cin:- % pos(Addr), % retract(data(Addr,_)), % get_single_char(Value), % assert(data(Addr,Value)). % + - add(AddValue):- % pos(Addr), % retract(data(Addr,Value)), % 1 NewValue is Value+AddValue, % assert(data(Addr,NewValue)). % > < addr(Side):- % retract(pos(Addr)), % NewAddr is Addr+Side, % assert(pos(NewAddr)), % (data(NewAddr,_),!;assert(data(NewAddr,0))). % ] goto:- % pos(Addr), % 0 data(Addr,Value),Value==0,!, % 0, retract(circle([_|L])), % assert(circle(L)). goto:- % circle([[N,_]|_]), seeing(Stream), seek(Stream,N,bof,_). % [ loop:- % retract(circle(L)), seeing(Stream), % character_count(Stream,Pos), % %( = 0, ) pos(Addr), data(Addr,Value), assert(circle([[Pos,Value]|L])). do:- % get_char(X), % step(X), % not(at_end_of_stream),!, do. do:- % , seeing(Stream), close(Stream), seen. step('['):-loop,!. step(']'):-goto,!. % " " %( ) step(_):-circle([[_,StartValue]|_]),StartValue==0,!. step('>'):-addr( 1),!. step('<'):-addr(-1),!. step(','):-cin,!. step('.'):-cout,!. step('+'):-add( 1),!. step('-'):-add(-1),!. step(_). run(Path):- see(Path), % ( ) retractall(pos(_)), retractall(data(_,_)), retractall(circle(_)), % assert(pos(1)), % 0 assert(data(1,0)), assert(circle([])),do.
ターミナルをチェックインするには、次のように記述します。
最も自由なPC:$ swipl -s <path.tofile>
?-run( 'Path.to.Brainfuck.code')。
Wikiの例をテストします。
Hello World! ブレインファックで
++++++++++ [> +++++++> +++++++++++ +++> + <<<<-]> ++
。> +。+++++++ .. +++。> ++。<< +++++++++++++++。>。+++。
------.--------。> +。>。
このような何かが出てくるはずです:
最も自由な@ PC:/ media / C6984667984655D9 $ swipl -s bf.pro
%ライブラリ(swi_hooks)をpce_swi_hooksにコンパイル0.00秒、2,224バイト
%/media/C6984667984655D9/bf.proコンパイル0.00秒、4,676バイト
SWI-Prologへようこそ(マルチスレッド、32ビット、バージョン5.10.4)
Copyright©1990-2011アムステルダム大学、VUアムステルダム
SWI-Prologには完全に無保証です。 これはフリーソフトウェアです。
特定の条件下で再配布することもできます。
詳細については、 www.swi-prolog.orgをご覧ください。
ヘルプについては、使用しますか?-ヘルプ(トピック)。 または?-apropos(Word)。
?-実行( 'a.txt')。
Hello World!
本当
?-
問題2.チューリングマシン
再びウィキから少し理論
チューリングマシン(MT)-抽象的な実行者(抽象的なコンピューティングマシン)。 アルゴリズムの概念を形式化するために1936年にアランチューリングによって提案されました。
チューリングマシンは有限状態マシンの拡張であり、チャーチチューリングテーゼによれば、(遷移ルールを設定することにより)計算の各ステップがかなり基本的なステップバイステップの計算プロセスを何らかの方法で実装する他のすべての実行者をシミュレートできます。
特定のチューリングマシンは、アルファベットAの文字のセット、状態Qのセット、およびマシンが動作するルールのセットの要素をリストすることによって定義されます。 qiaj→qi1aj1dk(頭部がqi状態にあり、文字ajがモニター対象セルに書き込まれ、頭部がqi1状態になり、aj1がajの代わりにセルに書き込まれる場合、頭部はdkを移動します。 (L)、右のセルへ®、そのまま(N)のまま。 可能な構成<qi、aj>ごとに、ルールが1つだけあります。 一度マシンが停止する最終状態にのみルールはありません。 さらに、最終状態と初期状態、テープ上の初期構成、およびマシンヘッドの位置を示す必要があります。
Vikaが提案したMTを使用します
q0 *→q0 * R
q01→q01R
q0×→q1×R
q11→q2aR
q21→q21L
q2a→q2aL
q2 =→q2 = L
q2×→q3×L
q31→q4aR
q3a→q3aL
q3 *→q6 * R
q4×→q4×R
q4a→q4aR
q4 =→q4 = R
q41→q41R
q4 *→q51R
q5 *→q2 * L
q6a→q61R
q6×→q7×R
q7a→q7aR
q71→q2aR
q7 =→q8 = L
q8a→q81L
q8×→q9H
データ(L、V、R)-テープの表現(L-左側、R-右、V-現在のセル)。
... [1] [2] [3] [ 4 ] [5] [6] [7] ...
L = [3,2,1] V = 4 R = [5,6,7]
空のセル値-*
% revers([],R,R):-!. revers([H|T],L,R):-revers(T,[H|L],R). % l:- % (retract(data([Hl|Tl],V,R)),!; % , (*) retract(data([],V,R)),Hl=(*),Tl=[]), % assert(data(Tl,Hl,[V|R])). r:- % (retract(data(L,V,[Hr|Tr])),!; % , (*) retract(data(L,V,[])),Hr=(*),Tr=[]), % assert(data([V|L],Hr,Tr)). % n. % . %revers ( data). initData(L,V,R):- % ( ) retractall(data(_,_,_)), % ( ) revers(L,[],Lr), % . assert(data(Lr,V,R)). % input(Value):- % , . retract(data(L,_,R)), % . assert(data(L,Value,R)). % info(Q:A:Qn:An:D):- % write(Q:A),nl, write(Qn:An:D),nl, % « » data(L,Value,R),revers(L,[],Lr),append(Lr,[[Value]|R],Data), write(Data),nl. % %(, , , ). % q0(*,q0,*,r). q0(1,q0,1,r). q0(x,q1,x,r). q1(1,q2,a,r). q2(1,q2,1,l). q2(a,q2,a,l). q2(=,q2,=,l). q2(x,q3,x,l). q3(1,q4,a,r). q3(a,q3,a,l). q3(*,q6,*,r). q4(x,q4,x,r). q4(a,q4,a,r). q4(=,q4,=,r). q4(1,q4,1,r). q4(*,q5,1,r). q5(*,q2,*,l). q6(a,q6,1,r). q6(x,q7,x,r). q7(a,q7,a,r). q7(1,q2,a,r). q7(=,q8,=,l). q8(a,q8,1,l). q8(x,e,x,n). %e — . start(e):-write(end),!. % Q start(Q):- % data(_,A,_), % apply(Q,[A,Qn,An,D]), % info(Q:A:Qn:An:D), % input(An), % call(D), % start(Qn).
MTを開始
$ swipl -s 1.pro
?-initData([]、*、[1,1,1、x、1,1、=、*])。
?-開始(q0)。
そして、これが結果です。
$ swipl -s 1.pro
...
?-initData([]、*、[1,1,1、x、1,1、=、*])。
本当
?-開始(q0)。
q0:(*)
q0:(*):r
[[*]、1,1,1、x、1,1、=、*]
q0:1
q0:1:r
[*、[1]、1,1、x、1,1、=、*]
...
...
...
q8:a
q8:1:l
[*、1,1,1、x、[a]、1、=、1,1,1,1,1,1,1、*]
q8:x
e:x:n
[*、1,1,1、[x]、1,1、=、1,1,1,1,1,1,1、*]
終わり
本当