//
/* -------------------------------------------------------------------------------------------------------- turing.java チューリングマシン ver. 1.00 (JDK 1.02) ueyama@infonet.co.jp 2009.03.14 -------------------------------------------------------------------------------------------------------- */ import java.applet.*; import java.awt.*; import java.util.*; public class turing extends Applet implements Runnable { int Hx; // ヘッド表示X座標 int Ty=38; // テープ表示Y座標 int Bx[]={18,278,308,338,398,428,458,518,748,660,660}; // ボタン表示X座標 int By[]={90, 90, 90, 90, 90, 90, 90, 90, 90,344,370}; // ボタン表示Y座標 int Kx=405; // キー表示X座標 int Ky[]={154,204,240,266,292}; // キー表示Y座標 int Kq[]={26,8,8,2,26}; // 入力キーの数 int Kn=-1; // 入力可能キー列No. int Kc=-1; // クリックされたキーNo. int Tape[]=new int[512]; // テープのデータ int Rt[][]=new int[256][5]; // ルール int Rq=0; // ルール数 int Rx=-1, Ry=-1; // ルール表編集位置 int Rm=-1, Rn=-1; // ルール表旧編集位置 int Td=239; // テープの表示開始No. int Rd=0; // ルールの表示開始No. int Hp; // ヘッドの位置 int Hs=0; // ヘッドの状態 int Ra; // 適用されるルール No. int Pn=0; // プログラム No. int Sp=0; // 実行ステップ数 int Te=-1; // 編集テープNo. int Dx=-1,Dy=-1; // ドラッグの処理用 int Mc=-1; // 0:Head, 1:Tape, 2:Btn, 3:Tbl, 4:Rule int Mx=0; int Wait=256; int Bgc; Thread th=null; boolean Run=false; boolean Err=false; TextArea Rtxt=new TextArea(3,30); Image Img; // Ar[n][0]: ルールNo. [1]: ルール表示開始No. [2]: テープ表示開始No. [3]: ヘッド位置 [4]: テープデータ int Ar[][]=new int[256][5]; // 履歴データ // Rule[0]: テープデータ件数 (8bit), テープの表示開始位置 (8bit), ヘッドの位置 (8bit), 状態 (8bit) // Rule[1]〜 テープデータ: テープ位置 (任意), データ (8bit) // Rule[] 以後ルールデータ: 状態 (8), 入力 (4), 出力 (4), 移動 (4), 次の状態 (8bit) // Rule[] 最後 負の数 int Rule[][]=new int[5][256]; String Rstr[]={"03efff00,fd01,fe00,ff01,0061101,0001101,0010000,0166019,0100101,0111101", // インクリメント "04efff00,fc01,fd00,fe01,ff01,0001000,0010000,0066101,0166019,0177101", // 否定 "0ce9ff00,f301,f401,f500,f601,f701,f800,fa00,fb01,fc00,fd01,fe01,ff01,0066108,0002001,0013003,0077108,0166002,0100001,0111001,0262106,0202106,0213106,0222002,0233002,0366004,0300003,0311003,0463106,0403106,0412005,0422004,0433004,0561106,0501106,0510005,0666107,0677106,0700107,0711107,0722000,0733000,0866009,0877108,096600a,0900109,0911109,0926009,0936009,0a6610b,0a0010b,0a1110b,0a2000a,0a3100a,0b66019,0b7710b", // 加算 "08eafc00,f401,f501,f600,f701,f900,fa01,fb01,fc00,0001000,0010000,0066101,0166002,0177101,0261103,0201103,0210002,0300103,0311103,0366004,046610c,0402005,0413007,047710c,0566006,0500005,0511005,066210a,060210a,061310a,0622006,0633006,0766008,0700007,0711007,086310a,080310a,0812009,0822008,0833008,096110a,090110a,0910009,0a6610b,0a7710a,0b0010b,0b1110b,0b22004,0b33004,0c6600d,0c7710c,0d6600e,0d0010d,0d1110d,0d2600d,0d3600d,0e6610f,0e0010f,0e1110f,0e2000e,0e3100e,0f66010,0f7710f,1066111,1077010,1116112,1266019,1277112"}; // 減算 public void init() // 初期設定 { int i,j; String q; String bg=getParameter("bgcolor"); Bgc=Integer.valueOf(bg,16).intValue(); setBackground(new Color(Bgc)); MediaTracker mt=new MediaTracker(this); Img=getImage(getCodeBase(), getParameter("figure")); setLayout(null); add(Rtxt); Rtxt.reshape(405,345,240,48); mt.addImage(Img, 0); try { mt.waitForID(0); } catch(InterruptedException e){}; for(i=0;i<4;i++) // ルールデータの設定 { StringTokenizer st=new StringTokenizer(Rstr[i],","); for(j=0; st.hasMoreTokens(); j++) { q=st.nextToken(); Rule[i][j]=Integer.valueOf(q,16).intValue(); // ルール } } rule_init(Pn); } public void rule_init(int c) // ルールの初期化 { int i,m,n; m=Rule[c][0]; Hs=m%256; m/=256; // ヘッドの初期状態 Hp=m%256; m/=256; // ヘッドの位置 Td=m%256; // テープの表示開始位置 n=m/=256; // テープデータ件数 for(i=0; i<512;i++) Tape[i]=6; // テープのクリア for(i=0; i<256;i++) Rt[i][0]=-1; // ルールのクリア for(i=0;i0; i++) // ルールデータの読み込み { m=Rule[c][i+n+1]; Rt[i][4]=m%256; m/=256; Rt[i][3]=m%16; m/=16; Rt[i][2]=m%16; m/=16; Rt[i][1]=m%16; m/=16; Rt[i][0]=m%256; } Rq=i; // ルール数 Sp=0; Err=false; } public void start() { if(th==null) { th=new Thread(this); th.start(); } } public boolean inside(int x, int a, int b) // マウスの位置座標チェック { return (x<=Math.max(a,b) && x>=Math.min(a,b)) ? true:false; } public void dsp_g(int x, int y, int m, int n, int e, int c) // 画像の表示 { int w=0, h=0, ox=0, oy=0; Graphics gx=getGraphics(); switch(c) { case 0: w= 15; h= 11; ox= 66; oy= 24; break; // キー 状態用数字 case 1: w= 8; h= 13; ox= 456; oy= 24; break; // キー テープ用記号 case 2: w= 26; h= 20; ox= 0; oy= 38; break; // キー case 4: w= 33; h= 38; ox= 0; oy= 0; break; // ヘッド case 5: w= 25; h= 22; ox= 520; oy= 70; break; // テープ case 6: w= 18; h= 12; ox= 66; oy= 0; break; // 状態用数字 case 7: w= 60; h= 13; ox= 52; oy= 57; break; // "状態 入力 出力 移動 次の状態" case 8: w= 26; h= 23; ox= 52; oy= 70; break; // ボタン case 9: w= 59; h= 16; ox= 52; oy=116; break; // ルール表の編集表示 case 10: w= 24; h= 4; ox= 351; oy= 63; break; // 速度表示用ドット case 11: w=104; h= 15; ox= 757; oy= 0; break; // ポップアップメニュー選択項目 case 12: w= 83; h= 15; ox= 757; oy= 0; break; // ポップアップメニュー選択項目 case 13: w=106; h= 98; ox= 545; oy= 0; break; // ポップアップメニュー case 14: w= 33; h= 9; ox= 0; oy=116; break; // ボタン説明 } gx.clipRect(x, y, w, h); if(e>0) gx.clearRect(x, y, w, h); gx.drawImage(Img,x-(ox+m*w),y-(oy+n*h),this); gx.dispose(); } public void paint(Graphics g) // 画面の表示 { int i,j,m; g.clearRect(0, 0, size().width, size().height); g.setColor(new Color (0x000000)); for(i=0; i<34; i++) g.drawRect(i*24-12,Ty,24,21); // テープの表示 dsp_tape(); // テープデータの表示 dsp_head(); // ヘッドの表示 dsp_g(70,93,0,0,1,13); // ポップアップメニューの表示 dsp_g(72,96,0,Pn,1,12); // メニュー選択項目の表示 dsp_tbl(); // 表の罫線の表示 dsp_rules(); // ルール表 の表示 for(i=0;i<11;i++) dsp_btn(i,0); // ボタンの表示 for(i=0;i<9;i++) dsp_g(Bx[i]-4,118,(i==6)?9:i,0,0,14); // ボタンの説明表示 dsp_g(Bx[1]+Mx*10+32,84,0,0,1,10); // 実行速度表示用ドットの表示 for(i=0;i<5;i++) dsp_g(Kx-85+((i==4 || i==0)?15:0),Ky[i]+4,i,0,1,7); // キーの説明の表示 for(i=0;i<5;i++) dsp_keys(i,0); // キーの表示 } public void dsp_head() // ヘッドの表示 { Hx=(Hp-Td)*24+8; // ヘッド表示座標 dsp_g(Hx,0,0,0,1,4); // ヘッドの表示 dsp_g(Hx+7,8,Hs,0,1,6); // ヘッドの状態の表示 } public void dsp_tape() // テープデータの表示 { int i,m; for(i=0;i<32;i++) // テープデータの表示 { dsp_g(i*24+12,Ty,0,0,1,5); // テープの表示 m=Tape[Td+i]; dsp_g(i*24+20,Ty+5,(m==6)?8:m,1,1,1); // (m==6)?8:m は空白の処理 } } public void dsp_rule(int m, int n) // ルールの表示 { int j=Rt[m][n], k=(Ra==m)?2:1; // ルールNo. if(Rt[m][0]>=0) { if(m>Rq) dsp_g(23+n*60,172+(m-Rd)*17+1,8,k,1,1); // 状態 else { if(n==0 || n==4) dsp_g(23+n*60,172+(m-Rd)*17+1,j,k,1,0); // 状態 else if(n==3) dsp_g(26+n*60,172+(m-Rd)*17,j+9,k,1,1); // 移動 else dsp_g(26+n*60,172+(m-Rd)*17,j,k,1,1); // 入出力 } } } public void dsp_rules() // ルール表 の表示 { int i,j; Ra=-1; Err=false; for(i=0;i 12)?Ra-6:0; for(i=0;i<13;i++) for(j=0;j<5;j++) if(i+Rd 0 && Hs<25)?2:0; break; // Rule Clear case 1: m=6; n=1; k=(Wait<4096)?0:2; break; // Slow case 2: m=3; n=(Run)?1:0; k=(Hs==25 || Err)?2:0; break; // Run case 3: m=9; n=1; k=(Wait>16)?0:2; break; // Fast case 4: m=0; n=0; k=(Sp==0)?2:0; break; // Back case 5: m=6; n=0; k=(Hs==25 || Err)?2:0; break; // Step // case 6: m=12; n=1; k=(Sp==0)?2:0; break; // Reset case 6: m=0; n=1; k=(Sp==0)?2:0; break; // Reset case 7: m=9; n=0; k=(Sp==0)?2:0; break; // Clear case 8: m=12; n=0; k=(Sp>0 && Hs<25)?2:0; break; // Tape Clear case 9: m=15; n=1; k=(Sp>0 && Hs<25)?2:0; break; // Write case 10: m=15; n=0; k=(Sp>0 && Hs<25)?2:0; break; // Read } dsp_g(Bx[i],By[i],m+((c==0)?k:c),n,1,8); // ボタンの表示 } public void dsp_key(int m, int n, int c) // キー(1個)の表示 { int j=n%13, k=n/13; switch(m) { case 0: dsp_g(Kx+j*30,Ky[0]+k*24,1,c,1,2); // 状態キーの表示 dsp_g(Kx+j*30+6,Ky[0]+k*24+4,n,0,0,0); break; // 文字の表示 case 1: dsp_g(Kx+n*30,Ky[1],1,c,1,2); // 入力キーの表示 dsp_g(Kx+n*30+10,Ky[1]+3,n,0,0,1); break; // 文字の表示 case 2: dsp_g(Kx+n*30,Ky[2],0,c,1,2); // 出力キーの表示 dsp_g(Kx+n*30+10,Ky[2]+3,n,0,0,1); break; // 文字の表示 case 3: dsp_g(Kx+n*30,Ky[3],0,c,1,2); // 移動キーの表示 dsp_g(Kx+n*30+10,Ky[3]+3,n+9,0,0,1); break; // 文字の表示 case 4: dsp_g(Kx+j*30,Ky[4]+k*24,0,c,1,2); // 状態キーの表示 dsp_g(Kx+j*30+6,Ky[4]+k*24+4,n,0,0,0); break; // 文字の表示 } } public void dsp_keys(int m, int c) // キー(一組)の表示 { int i; switch(m) { case 0: for(i=0;i<26;i++) dsp_key(m,i,c); break; // 状態キーの表示 case 1: for(i=0;i<8;i++) dsp_key(m,i,c); break; // 入力キーの表示 case 2: for(i=0;i<8;i++) dsp_key(m,i,c); break; // 出力キーの表示 case 3: for(i=0;i<2;i++) dsp_key(m,i,c); break; // 移動キーの表示 case 4: for(i=0;i<26;i++) dsp_key(m,i,c); break; // 状態キーの表示 } } public void dsp_tbl() // ルール表 (罫線) の表示 { int i; for(i=0;i<5;i++) dsp_g(i*60, 152,i,0,1,7); // 表の見出しの表示 Graphics gx=getGraphics(); gx.clearRect(0,169,300,221); gx.setColor(new Color(0xcccccc)); // 表 (罫線) を描く for(i=0;i<12;i++) gx.drawLine(0,186+i*17,300,186+i*17); for(i=1;i<5;i++) { gx.setColor(new Color((i==2)?0:0xcccccc)); gx.drawLine(i*60,170,i*60,390); } gx.setColor(new Color(0x000000)); gx.drawRect(0,169,300,221); gx.dispose(); } public void draw_rect(int x, int y, int m, int c) // テープ、ルール表入力位置の表示 { Graphics gx=getGraphics(); gx.setColor(new Color((c==0)?Bgc:0xff9999)); // switch(m) { case 0: gx.drawRect(x,y,22,19); break; // テープ case 1: gx.drawRect(x,y,58,15); break; // ルール表 } gx.dispose(); } public void run() { int i; while(true) { try { th.sleep(Wait); } catch (InterruptedException e){} if(Run) { tur_calc(); dsp_g(Hx,0,1,0,1,4); // ヘッドの消去 dsp_head(); dsp_tape(); // テープデータの表示 dsp_rules(); // ルール表 の表示 if(Hs==25) // 停止 (H) { Run=false; for(i=0;i<11;i++) dsp_btn(i,0); // ボタンの表示 } } } } public void stop() { if(th!=null) { th.stop(); th=null; } } public void tur_calc() // 計算の実行 { int i, m=-1; Ar[Sp][0]=Ra; // 履歴:ルール No. Ar[Sp][1]=Rd; // ルールの表示開始位置 Ar[Sp][2]=Td; // テープの表示開始位置 Ar[Sp][3]=Hp; // ヘッドの位置 Ar[Sp][4]=Tape[Hp]; // テープのデータ for(i=0; i =0) Tape[Hp]=Rt[Ra][2]; // テープデータ Hs=Rt[Ra][4]; // ヘッドの状態 Hp+=(Rt[Ra][3]==0)?-1:1; // ヘッドの位置 Sp++; } public boolean mouseDown(Event e, int mx, int my) // マウスがクリックされたときの処理 { int i, j, k, l, m=-1, n=0; String p,q,s; boolean f=false; Kc=-1; Dx=mx; Dy=my; if(Mc==1 && Te>=0) // テープクリック後であれば… { draw_rect((Te-Td)*24+13,Ty+1,0,0); // テープの編集位置表示を消す } if(Mc==3) draw_rect(Rm*60+1,170+Rn*17,1,0); // ルール編集位置赤表示を元に戻す for(i=0;i<5;i++) dsp_keys(i,(i==Rx)?1:0); // 入力キーを元に戻す if(inside(my,38,58)) // テープをクリック { Mc=1; Te=(mx+12)/24+Td-1; // テープ編集位置 draw_rect((Te-Td)*24+13,Ty+1,0,1); // テープの編集位置表示 Rx=1; } if(inside(mx,Hx,Hx+33) && my<38) Mc=0; // ヘッドをクリック if(inside(mx,70,176) && inside(my,93,114)) // ポップアップメニューをクリック { Mc=4; Dy=my; dsp_g(70,93,1,0,1,13); // ポップアップメニューの表示 dsp_g(72,96,0,Pn,1,12); // メニュー選択項目の表示 for(i=0; i<5; i++) dsp_g(71,115+i*15,(i==Pn)?1:0,i,1,11); // メニューリストの表示 } if(inside(mx,71,175) && inside(my,115,190)) // メニューリストをクリック { Mc=-1; Pn=(my-115)/15; dsp_g(70,93,0,0,1,13); // ポップアップメニューの表示 dsp_g(72,96,0,Pn,1,12); // メニュー選択項目の表示 rule_init(Pn); dsp_g(Hx,0,1,0,1,4); // ヘッドの消去 dsp_head(); dsp_tape(); // テープデータの表示 dsp_tbl(); dsp_rules(); // ルール表 の表示 for(i=0;i<11;i++) dsp_btn(i,0); // ボタンの表示 } for(m=0;m<11;m++) if(inside(mx,Bx[m],Bx[m]+26) && inside(my,By[m],By[m]+23)) // ボタンをクリック? { Mc=2; Rx=-1; switch(m) { case 0: // ルールのクリア dsp_btn(m,1); for(i=0;i<256;i++) Rt[i][0]=-1; // ルールのクリア dsp_rules(); break; case 1: if(Wait<4096) { // Slow ボタンをクリック Wait*=2; Mx--; dsp_btn(m,1); dsp_g(Bx[1]+Mx*10+32,84,0,0,1,10);} break; // ドットの表示 case 2: if(Hs<25 && !Err) { // RUN ボタンをクリック dsp_g(Bx[2],By[2],4,(Run)?1:0,1,8); // ボタンの表示 Run=!Run;} break; case 3: if(Wait>16) { // Fast ボタンをクリック Wait/=2; Mx++; dsp_btn(m,1); dsp_g(Bx[1]+Mx*10+32,84,0,0,1,10);} break; // ドットの表示 case 4: if(Sp>0) {Sp--; // 戻るボタンをクリック Ra=Ar[Sp][0]; // 履歴:ルール No. Rd=Ar[Sp][1]; // ルールの表示開始位置 Td=Ar[Sp][2]; // テープの表示開始位置 Hp=Ar[Sp][3]; // ヘッドの位置 Hs=Rt[Ra][0]; // ヘッドの状態 Tape[Hp]=Ar[Sp][4]; // テープのデータ Err=false; f=true;} break; case 5: if(Hs<25 && !Err) { // ステップボタンをクリック tur_calc(); // 計算の実行 f=true;} break; /* case 6: if(Sp>0) { // リセットボタンをクリック for(i=0;i<34;i++) dsp_g(i*24-12,Ty,0,0,1,3); // テープの表示 for(i=0;i<24;i++) dsp_g(i*33,0,1,0,1,4); // ヘッドの消去 Sp=0; Err=false; f=true;} break; */ case 7: if(Sp>0) { // クリアボタンをクリック rule_init(Pn); for(i=0; i<24; i++) dsp_g(i*33,0,1,0,1,4); // ヘッドの消去 Sp=0; Err=false; f=true;} break; case 8: dsp_btn(m,1); for(i=0; i<512;i++) Tape[i]=6; // テープのクリア dsp_tape(); // テープデータの表示 break; case 9: dsp_btn(m,1); for(i=0,j=0;i<512;i++) if(Tape[i]!=6) j++; s=Integer.toString(Hs+Hp*0x100+Td*0x10000+j*0x1000000,16); for(j=s.length();j<8;j++) s="0"+s; Rtxt.appendText(s+"\n"); for(i=0;i<512;i++) { if(Tape[i]!=6) { s=Integer.toString(i*0x100+Tape[i],16); for(j=s.length();j<5;j++) s="0"+s; Rtxt.appendText(s+"\n"); } } for(i=0;i 170) // ルール表をクリック { Mc=3; // ルール表をクリック Rx=mx/60; Ry=(my-170)/17; draw_rect(Rx*60+1,170+Ry*17,1,1); // 編集位置を赤表示 for(i=0;i<5;i++) dsp_keys(i,(i==Rx)?1:0); // キーの表示 } if(mx>Kx && my>Ky[0] && Rx>=0) // キーをクリック { for(i=0;i =0) { Rx++; Rx%=5; if(Rx==0) Ry++; if(Ry==13) { Rd++; Ry--; for(i=0;i<13;i++) for(j=0;j<5;j++) if(i+Rd 戻る