プロローグ。 機械をプログラムします

Prologについての記事を読んだ後、私は2つの小さなタスクの形で小さな追加を書くことにしました。

ここにあります:

1. Brainfuck言語インタープリター

2.チューリングマシン



まず、 SWI-Prologといくつかの空き時間が必要です。



タスク1. Brainfuck言語インタープリター


Wikipediaからのコピーペーストから始めましょう。

Brainfuckは最も有名な難解なプログラミング言語の1つで、1993年にUrban Mullerが楽しみのために作り出したものです。 この言語には8つのコマンドがあり、各コマンドは1文字で記述されています。 Brainfuckプログラムのソースコードは、追加の構文のないこれらの文字のシーケンスです。

Brainfuckコマンドによって制御されるマシンは、順序付けられたセルのセットと、チューリングマシンのテープとヘッドに似た現在のセルへのポインタで構成されます。 また、入力ストリームと出力ストリームを介して外部と通信するためのデバイス(コマンドを参照してください。)を意味します。



コマンドとその説明:






テープはデータベースの形で提示されます

データ(アドレス、値)。

セルアドレスで表される頭

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、*]

終わり

本当



ソース:


  1. ブレインファック
  2. チューリングマシン
  3. プロローグ



All Articles