置換(Permutation)の計算 山中和義 2007/10/30 11:38:21 (修正1回) └つづき 山中和義 2007/10/30 11:39:25 (修正1回) ├サンプル(あみだくじ、カードのシャッフル... 山中和義 2007/10/30 11:42:06 (修正2回) │└!置換行列 山中和義 2007/10/31 19:32:35 ├!15パズルをつくる 山中和義 2007/10/30 21:46:16 (修正3回) └!ルービックキューブ(Rubik'scube、magicc... 山中和義 2007/11/01 21:07:01 (修正1回) └つづき 山中和義 2007/11/01 21:10:06 (修正1回)
置換(Permutation)の計算 山中和義 2007/10/30 11:38:21 (修正1回) ツリーへ
置換(Permutation)の計算 |
返事を書く ノートメニュー |
山中和義 <drdlxujciw> 2007/10/30 11:38:21 ** この記事は1回修正されてます | |
!補助ルーチン SUB PermPrintOut(A()) !表示する ※標準形(2行n列の行列表記する) PRINT "┌"; FOR i=1 TO UBOUND(A) PRINT USING "###": i; NEXT i PRINT " ┐" PRINT "└"; FOR i=1 TO UBOUND(A) PRINT USING "###": A(i); NEXT i PRINT " ┘" END SUB SUB PermCyclicPrintOut(A()) !巡回表示する ※(,,…,) PRINT "("; FOR i=1 TO UBOUND(A) PRINT USING "###": A(i); NEXT i PRINT " )" END SUB SUB PermCyclicMultiplyPrintOut(n,A(,)) !巡回置換の積の表示する ※(,,…,)(,,…,)…(,,…,) FOR i=1 TO n IF A(i,2)<0 THEN !終端記号なら(長さ1の置換)、表示しない ELSE PRINT "("; FOR j=1 TO UBOUND(A,2) IF A(i,j)<0 THEN EXIT FOR !終端記号なら PRINT USING "###": A(i,j); NEXT j PRINT " )"; END IF NEXT i END SUB !置換 SUB PermCyclicForm(A(), C(,),n) !巡回置換の積の形へ ※C(n,)…C(2,)C(1,) DIM flg(100) !作業用 FOR i=1 TO UBOUND(A) LET flg(i)=i NEXT i LET n=0 FOR i=1 TO UBOUND(A) IF flg(i)>0 THEN !含まれないなら LET j=1 !長さ LET k=i !最初の値 DO !リストを作成する ※(4 4)などの長さ1の置換も含む LET C(n+1,j)=k LET j=j+1 LET flg(k)=-1 !巡回に含まれる LET k=A(k) !次をトレースする LOOP UNTIL k=i !1周するまで LET C(n+1,j)=-1 !終端記号を付加する LET n=n+1 !次の組へ END IF NEXT i END SUB SUB PermIdentity(A()) !恒等置換 FOR i=1 TO UBOUND(A) LET A(i)=i NEXT i END SUB SUB PermInverse(A(), C()) !逆置換 FOR i=1 TO UBOUND(A) LET C(A(i))=i NEXT i END SUB FUNCTION PermIsIdentity(A()) !恒等置換か確認する LET PermIsIdentity=0 !false FOR i=1 TO UBOUND(A) IF A(i)<>i THEN EXIT FUNCTION NEXT i LET PermIsIdentity=-1 !true END FUNCTION SUB PermMultiply(A(),B(), C()) !積AB ※AB≠BA、A(BC)=(AB)C LET ua=UBOUND(A) LET ub=UBOUND(B) IF ua=ub THEN FOR i=1 TO ua LET C(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i)) NEXT i ELSE PRINT "次元が違います。A=";ua;" B=";ub STOP END IF END SUB FUNCTION PermSign(A()) !符号を得る ※Π(A(i)-A(j))/(i-j) 1≦i<j≦n LET cnt=0 !反転数 FOR i=1 TO UBOUND(A)-1 FOR j=i+1 TO UBOUND(A) IF A(i)>A(j) THEN LET cnt=cnt+1 !転位なら NEXT j NEXT i IF MOD(cnt,2)=0 THEN LET PermSign=1 ELSE LET PermSign=-1 END FUNCTION |
└つづき 山中和義 2007/10/30 11:39:25 (修正1回) ツリーへ
Re: 置換(Permutation)の計算 |
返事を書く ノートメニュー |
山中和義 <drdlxujciw> 2007/10/30 11:39:25 ** この記事は1回修正されてます | |
つづき
SUB PermTranspositionForm(A(), C(,),n) !互換の積の形へ ※C(n,)…C(2,)C(1,) DIM tmpA(100) FOR i=1 TO UBOUND(A) !作業変数へ LET tmpA(i)=A(i) NEXT i LET n=0 FOR i=1 TO UBOUND(A) FOR j=1 TO UBOUND(A)-1 IF tmpA(j)>tmpA(j+1) THEN !隣接交換 LET tmp=tmpA(j) LET tmpA(j)=tmpA(j+1) LET tmpA(j+1)=tmp LET n=n+1 !次の組へ LET C(n,1)=j LET C(n,2)=j+1 LET C(n,3)=-1 !終端記号 END IF NEXT j NEXT i FOR i=1 TO INT(n/2) !反転 FOR j=1 TO 3 !UBOUND(C,2) LET tmp=C(i,j) LET C(i,j)=C(n-i+1,j) LET C(n-i+1,j)=tmp NEXT j NEXT i END SUB !巡回置換 SUB PermCopy(n,Q(,),A()) !巡回置換の1組を得る FOR j=1 TO UBOUND(A) LET A(j)=Q(n,j) NEXT j IF Q(n,j)<0 THEN !終端記号なら ELSE PRINT "次元が違います。長さ=";j-1 STOP END IF END SUB SUB PermCyclic(C(),A()) !巡回置換の標準形を得る CALL PermIdentity(A) FOR i=1 TO UBOUND(C)-1 LET A(C(i))=C(i+1) NEXT i LET A(C(i))=C(1) END SUB FUNCTION PermCyclicSign(C()) !巡回置換の符号を得る LET PermCyclicSign=(-1)^(UBOUND(C)-1) END FUNCTION !互換 SUB PermTransposition(a,b, C()) !互換の標準形を得る CALL PermIdentity(C) LET C(a)=b LET C(b)=a END SUB !-------------------- ここまでがサブルーチン !main !A=┌ 1 2 3 4 ┐=(1 2 4 3) ※1行目の順番は固定とする ! └ 2 4 1 3 ┘ DATA 2,4,1,3 !配列変数の「添え字と値」に対応させる DIM A(4) MAT READ A CALL PermPrintOut(A) DIM Q5(5,5) CALL PermCyclicForm(A, Q5,n) !巡回置換の積へ CALL PermCyclicMultiplyPrintOut(n,Q5) PRINT PermSign(A) !符号 !B=┌ 1 2 3 4 ┐=(1 2 3) ! └ 2 3 1 4 ┘ DATA 2,3,1,4 DIM B(4) MAT READ B CALL PermPrintOut(B) CALL PermCyclicForm(B, Q5,n) !巡回置換の積へ CALL PermCyclicMultiplyPrintOut(n,Q5) PRINT PermSign(B) DIM C(4) CALL PermMultiply(A,B,C) !積AB CALL PermPrintOut(C) DIM InvB(4) CALL PermInverse(B,InvB) !逆置換b CALL PermPrintOut(InvB) CALL PermMultiply(B,InvB, C) !Bb=E CALL PermPrintOut(C) END |
├サンプル(あみだくじ、カードのシャッフル... 山中和義 2007/10/30 11:42:06 (修正2回) ツリーへ
Re: つづき |
返事を書く ノートメニュー |
山中和義 <drdlxujciw> 2007/10/30 11:42:06 ** この記事は2回修正されてます | |
サンプル(あみだくじ、カードのシャッフル)
サブルーチン部分は省略 !main !5本のあみだくじをつくる !A=(2 3)(1 2)(3 4)(2 3)(4 5)(3 4)(2 3) DIM A(5),B(5) PRINT "1 2 3 4 5" !上から順に、 PRINT "│││││" CALL PermIdentity(A) PRINT "│├┤││" !2本目と3本目に横線を引く CALL PermTransposition(2,3,B) CALL PermMultiply(B,A, A) PRINT "││├┤│" !3本目と4本目に CALL PermTransposition(3,4,B) CALL PermMultiply(B,A, A) PRINT "│││├┤" !4本目と5本目に CALL PermTransposition(4,5,B) CALL PermMultiply(B,A, A) PRINT "│├┤││" !2本目と3本目に CALL PermTransposition(2,3,B) CALL PermMultiply(B,A, A) PRINT "││├┤│" !3本目と4本目に CALL PermTransposition(3,4,B) CALL PermMultiply(B,A, A) PRINT "├┤│││" !1本目と2本目に CALL PermTransposition(1,2,B) CALL PermMultiply(B,A, A) PRINT "│├┤││" !2本目と3本目に CALL PermTransposition(2,3,B) CALL PermMultiply(B,A, A) PRINT "│││││" CALL PermPrintOut(A) DIM Q(20,20) CALL PermCyclicForm(A, Q,n) !巡回置換の積へ CALL PermCyclicMultiplyPrintOut(n,Q) DIM T(20,3) CALL PermTranspositionForm(A, T,n) !(隣接)互換の積へ CALL PermCyclicMultiplyPrintOut(n,T) !トランプカードのリフルシャッフル(左右のカードを1枚ずつ交互に重ねていく) LET m=52 !枚数 !1枚目のカードは、1枚目へ !2枚目のカードは、3枚目へ !3枚目のカードは、5枚目へ ! : !52枚目のカードは、52枚目へ !のように、移動先を記述する。 DATA 1,3,5,7,9,11,13,15,17,19, 21,23,25,27,29,31,33,35,37,39, 41,43,45,47,49,51 DATA 2,4,6,8,10,12,14,16,18,20, 22,24,26,28,30,32,34,36,38,40, 42,44,46,48,50,52 !LET m=20 !DATA 1,3,5,7,9,11,13,15,17,19, 2,4,6,8,10,12,14,16,18,20 DIM s(m) MAT READ s DIM ss(m) CALL PermIdentity(ss) !初期値 FOR k=1 TO 20 !回数 CALL PermMultiply(s,ss,ss) !シャッフル PRINT "K=";k CALL PermPrintOut(ss) !何回か実行すると元に戻る NEXT k END |
│└!置換行列 山中和義 2007/10/31 19:32:35 ツリーへ
Re: サンプル(あみだくじ、カードのシャッフル... |
返事を書く ノートメニュー |
山中和義 <drdlxujciw> 2007/10/31 19:32:35 | |
!置換行列
SUB PermToMatrix(A(), M(,)) !置換行列を得る MAT M=ZER FOR i=1 TO UBOUND(A) LET M(i,A(i))=1 NEXT i END SUB SUB PermTranspositionToMatrix(i,j, M(,)) !基本変形を行う基本行列を得る MAT M=IDN LET M(i,i)=0 LET M(j,j)=0 LET M(i,j)=1 LET M(j,i)=1 END SUB !main !5本のあみだくじをつくる !A=(2 3)(1 2)(3 4)(2 3)(4 5)(3 4)(2 3) DIM A(5),B(5,5) PRINT "1 2 3 4 5" !上から順に、 PRINT "│││││" FOR i=1 TO UBOUND(A) !CALL PermIdentity(A) LET A(i)=i NEXT i PRINT "│├┤││" !2本目と3本目に横線を引く CALL PermTranspositionToMatrix(2,3,B) !CALL PermTransposition(2,3,B) MAT A=B*A !CALL PermMultiply(B,A, A) PRINT "││├┤│" !3本目と4本目に CALL PermTranspositionToMatrix(3,4,B) MAT A=B*A PRINT "│││├┤" !4本目と5本目に CALL PermTranspositionToMatrix(4,5,B) MAT A=B*A PRINT "│├┤││" !2本目と3本目に CALL PermTranspositionToMatrix(2,3,B) MAT A=B*A PRINT "││├┤│" !3本目と4本目に CALL PermTranspositionToMatrix(3,4,B) MAT A=B*A PRINT "├┤│││" !1本目と2本目に CALL PermTranspositionToMatrix(1,2,B) MAT A=B*A PRINT "│├┤││" !2本目と3本目に CALL PermTranspositionToMatrix(2,3,B) MAT A=B*A PRINT "│││││" MAT PRINT USING REPEAT$("# ",52): A !CALL PermPrintOut(A) !トランプカードのリフルシャッフル(左右のカードを1枚ずつ交互に重ねていく) LET m=52 !枚数 !1枚目のカードは、1枚目へ移動先する !2枚目のカードは、3枚目へ移動先する !3枚目のカードは、5枚目へ移動先する ! : !52枚目のカードは、52枚目へ移動先する DATA 1,3,5,7,9,11,13,15,17,19, 21,23,25,27,29,31,33,35,37,39, 41,43,45,47,49,51 DATA 2,4,6,8,10,12,14,16,18,20, 22,24,26,28,30,32,34,36,38,40, 42,44,46,48,50,52 !LET m=20 !DATA 1,3,5,7,9,11,13,15,17,19, 2,4,6,8,10,12,14,16,18,20 DIM s(m) MAT READ s DIM x(m,m) !置換行列 CALL PermToMatrix(s,x) DIM ss(m) FOR i=1 TO UBOUND(ss) !整列したカードを用意する LET ss(i)=i NEXT i FOR k=1 TO 20 !回数 MAT ss=x*ss !シャッフル PRINT "K=";k MAT PRINT USING REPEAT$("## ",m): ss !何回か実行すると元に戻る NEXT k END |
├!15パズルをつくる 山中和義 2007/10/30 21:46:16 (修正3回) ツリーへ
Re: つづき |
返事を書く ノートメニュー |
山中和義 <drdlxujciw> 2007/10/30 21:46:16 ** この記事は3回修正されてます | |
!15パズルをつくる
!main LET N=4 !縦横の数 N×N LET N2=N*N !空白のピース番号 DATA 1, 2, 3, 4 !初期値 DATA 5, 6, 7, 8 DATA 9,10,11,12 DATA 15,13,14,16 !※16は空白の意、空白は最後に! !DATA 13,15,14,16 DIM p(N2) !ピースの配置 MAT READ p CALL PrintOut(p) !結果を表示する IF PermSign(p)<0 THEN !パリティチェック PRINT "解法不能です。" STOP END IF DIM op(N2) !置換で表す DO DO INPUT pNo !移動するピース番号を指定する IF pNo>0 AND pNo<N2 THEN !ピース番号なら FOR i=1 TO UBOUND(p) !配置位置へ変換する IF pNo=p(i) THEN EXIT FOR NEXT i LET x=i IF x>N AND p(x-N)=N2 THEN EXIT DO !1つ上が空白なら移動させる IF MOD(x,N)<>1 AND p(x-1)=N2 THEN EXIT DO !左 IF MOD(x,N)<>0 AND p(x+1)=N2 THEN EXIT DO !右 IF x<N2-N+1 AND p(x+N)=N2 THEN EXIT DO !下 END IF LOOP CALL PermTransposition(pNo,N2, op) !配置上での隣接交換 CALL PermMultiply(op,p,p) CALL PrintOut(p) !結果を表示する LOOP UNTIL PermIsIdentity(p)<0 !整列したら PRINT "完成です!" SUB PrintOut(p()) !配置を表示する FOR i=1 TO N2 IF p(i)=N2 THEN PRINT " "; ELSE PRINT USING "###": p(i); IF MOD(i,N)=0 THEN PRINT NEXT i END SUB END |
└!ルービックキューブ(Rubik'scube、magicc... 山中和義 2007/11/01 21:07:01 (修正1回) ツリーへ
Re: つづき |
返事を書く ノートメニュー |
山中和義 <drdlxujciw> 2007/11/01 21:07:01 ** この記事は1回修正されてます | |
!ルービックキューブ(Rubik's cube、magic cube)のシミュレーション
SUB PermIdentity(A()) !恒等置換 FOR i=1 TO UBOUND(A) LET A(i)=i NEXT i END SUB SUB PermCyclicToMatrix(C(), M(,)) !巡回置換の行列を得る MAT M=IDN FOR i=1 TO UBOUND(C)-1 LET M(C(i),C(i))=0 LET M(C(i),C(i+1))=1 NEXT i LET M(C(i),C(i))=0 LET M(C(i),C(1))=1 END SUB PICTURE PlotOut !展開図の表示(中央の配置を固定) SET DRAW mode hidden !ちらつき防止(開始) CLEAR DRAW plane(1) WITH SHIFT(3,3) !正面 DRAW plane(9) WITH SHIFT(9,3) !裏面 DRAW plane(17) WITH SHIFT(3,6) !上面 DRAW plane(25) WITH SHIFT(3,0) !下面 DRAW plane(33) WITH SHIFT(0,3) !左面 DRAW plane(41) WITH SHIFT(6,3) !右面 SET DRAW mode explicit !ちらつき防止(終了) END PICTURE PICTURE plane(n) !n番目から始まる1面(3×3)を表示する FOR i=0 TO 3 !前半 SET AREA COLOR INT((B(n+i)-1)/8)+2 !色 DRAW block(STR$(B(n+i))) WITH SHIFT(MOD(i,3),INT(i/3)) NEXT i SET AREA COLOR INT((n-1)/8)+2 !中央 DRAW block(s$(INT((n-1)/8)+1)) WITH SHIFT(MOD(4,3),INT(4/3)) FOR i=5 TO 8 !後半 SET AREA COLOR INT((B(n+i-1)-1)/8)+2 !色 DRAW block(STR$(B(n+i-1))) WITH SHIFT(MOD(i,3),INT(i/3)) NEXT i END PICTURE PICTURE block(n$) !ブロックの表示 PLOT AREA: 0,0; 1,0; 1,1; 0,1 PLOT LINES: 0,0; 1,0; 1,1; 0,1; 0,0 !縁 SET TEXT HEIGHT 0.5 !番号 PLOT TEXT ,AT 0.2,0.2: n$ END PICTURE !main SET WINDOW -0.1,1.3, -0.3,1.1!表示領域を設定する DIM B(48),savB(48) !ブロックの配置 CALL PermIdentity(B) !整列させる MAT savB=B DIM s$(7) !メニュー項目 DATA "正","裏","上","下","左","右","1つ戻す" MAT READ s$ DO DRAW PlotOut WITH SCALE(0.1) !結果を表示する LOCATE CHOICE(s$): p !メニューを選択する IF p=7 THEN MAT B=savB !戻す ELSE MAT savB=B CALL op(p) !回転する END IF PRINT s$(p) !トレース LOOP SUB op(p) !操作 IF p=1 THEN RESTORE 100 !各面の回転 IF p=2 THEN RESTORE 200 IF p=3 THEN RESTORE 300 IF p=4 THEN RESTORE 400 IF p=5 THEN RESTORE 500 IF p=6 THEN RESTORE 600 DIM C(4),M(48,48) !巡回置換、置換行列 MAT M=IDN FOR k=1 TO 5 !5つで1組 MAT READ C !巡回置換を読み込む CALL PermCyclicToMatrix(C, M) !対応する行列へ MAT B=M*B !置換 NEXT k END SUB |
└つづき 山中和義 2007/11/01 21:10:06 (修正1回) ツリーへ
Re: !ルービックキューブ(Rubik'scube、magicc... |
返事を書く ノートメニュー |
山中和義 <drdlxujciw> 2007/11/01 21:10:06 ** この記事は1回修正されてます | |
つづき
!「正面を右回転」の巡回置換を定義する。 100 DATA 1,3,8,6 !その面 ※5つの巡回置換は互いに素のためどの順でもよい DATA 2,5,7,4 DATA 17,35,32,46 !まわりの面 DATA 18,37,31,44 DATA 19,40,30,41 !「裏面を右回転」の場合 200 DATA 9,11,16,14, 10,13,15,12 !その面 DATA 22,48,27,33, 23,45,26,36, 24,43,25,38 !まわりの面 !「上面を右回転」の場合 300 DATA 17,19,24,22, 18,21,23,20 !その面 DATA 6,46,14,38, 7,47,15,39, 8,48,16,40 !まわりの面 !「下面を右回転」の場合 400 DATA 25,27,32,30, 26,29,31,28 !その面 DATA 1,33,9,41, 2,34,10,42, 3,35,11,43 !まわりの面 !「左側面を右回転」の場合 500 DATA 33,35,40,38, 34,37,39,36 !その面 DATA 1,17,16,25, 4,20,13,28, 6,22,11,30 !まわりの面 !「右側面を右回転」の場合 600 DATA 41,43,48,46, 42,45,47,44 !その面 DATA 3,27,14,19, 5,29,12,21, 8,32,9,24 !まわりの面 END |