!「さいころの回転」のシミュレーション
!置換(Permutation)の計算
SUB PermPrintOut(A()) !表示する
MAT PRINT USING(REPEAT$(" ##",UBOUND(A))): A;
PRINT
END SUB
SUB PermIdentity(A()) !恒等置換
FOR i=1 TO UBOUND(A)
LET A(i)=i
NEXT i
END SUB
SUB PermInverse(A(), iA()) !逆置換 ※iAはA以外の配列を指定すること
FOR i=1 TO UBOUND(A)
LET iA(A(i))=i
NEXT i
END SUB
SUB PermMultiply(A(),B(), AB()) !積AB ※ABはAかつB以外の配列を指定すること
LET ua=UBOUND(A)
LET ub=UBOUND(B)
IF ua=ub THEN
FOR i=1 TO ua
LET AB(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i))
NEXT i
ELSE
PRINT "次元が違います。A=";ua;" B=";ub
STOP
END IF
END SUB
!-------------------- ここまでがサブルーチン
LET N=6
!展開図の配置と面番号(配列の添え字)との関係
! □ 後 1
!□□□□ 左上右下 2345
! □ 正 6
!---------- ↓↓↓↓↓ ----------
DIM A(N)
DATA 5,4,1,3,6,2 !目の配置 ※展開図参照
MAT READ A
!LET s$="DRDRDR" !手順 1
!LET s$="RRRDDD" !手順 2
!LET s$="RRDDDR" !手順 3
!LET s$="RRDRDD" !手順 4
!LET s$="RDDDRR" !手順 5
LET s$="RDLDRRRD" !手順 6
!---------- ↑↑↑↑↑ ----------
DIM U(N),D(N),L(N),R(N) !置換
! 1,2,3,4,5,6
DATA 3,2,6,4,1,5 !上 ※正面を上面にするの(図での水平軸)回転
!!!DATA 5,2,1,4,6,3 !下
DATA 1,3,4,5,2,6 !左
!!!DATA 1,5,2,3,4,6 !右
MAT READ U
CALL PermInverse(U,D)
!!!MAT READ D
MAT READ L
CALL PermInverse(L,R)
!!!MAT READ R
SET WINDOW -1,5,5,-1 !表示領域
DRAW grid !格子
DIM T(N),TT(N) !作業配列
LET x=0.5 !左上
LET y=0.5
MAT T=A !初期状態を表示する
CALL disp(T)
FOR k=1 TO LEN(s$) !スクリプトを実行する
PLOT LINES: x,y; !経路の結線 始点
SELECT CASE UCASE$(s$(k:k)) !各方向へ
CASE "U","N"
CALL PermMultiply(T,U,TT)
LET y=y-1
CASE "D","S"
CALL PermMultiply(T,D,TT)
LET y=y+1
CASE "L","W"
CALL PermMultiply(T,L,TT)
LET x=x-1
CASE "R","E"
CALL PermMultiply(T,R,TT)
LET x=x+1
CASE ELSE
END SELECT
MAT T=TT !次へ
PLOT LINES: x,y; !終点
CALL disp(T)
NEXT k
SUB disp(T()) !現在の状態を表示する
CALL PermPrintOut(T)
LET nm=T(3) !グラフィックスによる
IF nm=1 THEN !中央
DRAW eye(4) WITH SHIFT(x,y)
END IF
IF nm=3 OR nm=5 THEN
DRAW eye(1) WITH SHIFT(x,y)
END IF
IF nm=2 OR nm=4 OR nm=5 OR nm=6 THEN !左斜め
DRAW eye(1) WITH SHIFT(x+0.25,y+0.25)
DRAW eye(1) WITH SHIFT(x-0.25,y-0.25)
END IF
IF nm=3 OR nm=4 OR nm=5 OR nm=6 THEN !右斜め
DRAW eye(1) WITH SHIFT(x+0.25,y-0.25)
DRAW eye(1) WITH SHIFT(x-0.25,y+0.25)
END IF
IF nm=6 THEN !中段
DRAW eye(1) WITH SHIFT(x+0.25,y)
DRAW eye(1) WITH SHIFT(x-0.25,y)
END IF
!!!SET TEXT JUSTIFY "center","half"
!!!PLOT TEXT ,AT x,y: STR$(T(3))
END SUB
PICTURE eye(c) !目の1つを表示する
SET AREA COLOR c
DRAW disk WITH SCALE(0.1)
END PICTURE
END
さいころを転がす
投稿者:山中和義 投稿日:2008年11月18日(火)18時56分39秒●問題
4×4の格子がある。左上をスタート、右下をゴールの位置とする。
さいころの目「1」を上にしてスタートに置き、ゴールに向けて転がす。
このとき、ゴールでの目の数が1~6になる転がし方(経路)を求める。
経路の決め方に、重複通過、迂回、通過点などの制限を設けてもよい。
シミュレータをつくって確認してみました。他にもあると思います。
!「さいころの回転」のシミュレーション !置換(Permutation)の計算 SUB PermPrintOut(A()) !表示する MAT PRINT USING(REPEAT$(" ##",UBOUND(A))): A; PRINT END SUB SUB PermIdentity(A()) !恒等置換 FOR i=1 TO UBOUND(A) LET A(i)=i NEXT i END SUB SUB PermInverse(A(), iA()) !逆置換 ※iAはA以外の配列を指定すること FOR i=1 TO UBOUND(A) LET iA(A(i))=i NEXT i END SUB SUB PermMultiply(A(),B(), AB()) !積AB ※ABはAかつB以外の配列を指定すること LET ua=UBOUND(A) LET ub=UBOUND(B) IF ua=ub THEN FOR i=1 TO ua LET AB(i)=A(B(i)) !※合成写像(AB)(i)=A(B(i)) NEXT i ELSE PRINT "次元が違います。A=";ua;" B=";ub STOP END IF END SUB !-------------------- ここまでがサブルーチン LET N=6 !展開図の配置と面番号(配列の添え字)との関係 ! □ 後 1 !□□□□ 左上右下 2345 ! □ 正 6 !---------- ↓↓↓↓↓ ---------- DIM A(N) DATA 5,4,1,3,6,2 !目の配置 ※展開図参照 MAT READ A !LET s$="DRDRDR" !手順 1 !LET s$="RRRDDD" !手順 2 !LET s$="RRDDDR" !手順 3 !LET s$="RRDRDD" !手順 4 !LET s$="RDDDRR" !手順 5 LET s$="RDLDRRRD" !手順 6 !---------- ↑↑↑↑↑ ---------- DIM U(N),D(N),L(N),R(N) !置換 ! 1,2,3,4,5,6 DATA 3,2,6,4,1,5 !上 ※正面を上面にするの(図での水平軸)回転 !!!DATA 5,2,1,4,6,3 !下 DATA 1,3,4,5,2,6 !左 !!!DATA 1,5,2,3,4,6 !右 MAT READ U CALL PermInverse(U,D) !!!MAT READ D MAT READ L CALL PermInverse(L,R) !!!MAT READ R SET WINDOW -1,5,5,-1 !表示領域 DRAW grid !格子 DIM T(N),TT(N) !作業配列 LET x=0.5 !左上 LET y=0.5 MAT T=A !初期状態を表示する CALL disp(T) FOR k=1 TO LEN(s$) !スクリプトを実行する PLOT LINES: x,y; !経路の結線 始点 SELECT CASE UCASE$(s$(k:k)) !各方向へ CASE "U","N" CALL PermMultiply(T,U,TT) LET y=y-1 CASE "D","S" CALL PermMultiply(T,D,TT) LET y=y+1 CASE "L","W" CALL PermMultiply(T,L,TT) LET x=x-1 CASE "R","E" CALL PermMultiply(T,R,TT) LET x=x+1 CASE ELSE END SELECT MAT T=TT !次へ PLOT LINES: x,y; !終点 CALL disp(T) NEXT k SUB disp(T()) !現在の状態を表示する CALL PermPrintOut(T) LET nm=T(3) !グラフィックスによる IF nm=1 THEN !中央 DRAW eye(4) WITH SHIFT(x,y) END IF IF nm=3 OR nm=5 THEN DRAW eye(1) WITH SHIFT(x,y) END IF IF nm=2 OR nm=4 OR nm=5 OR nm=6 THEN !左斜め DRAW eye(1) WITH SHIFT(x+0.25,y+0.25) DRAW eye(1) WITH SHIFT(x-0.25,y-0.25) END IF IF nm=3 OR nm=4 OR nm=5 OR nm=6 THEN !右斜め DRAW eye(1) WITH SHIFT(x+0.25,y-0.25) DRAW eye(1) WITH SHIFT(x-0.25,y+0.25) END IF IF nm=6 THEN !中段 DRAW eye(1) WITH SHIFT(x+0.25,y) DRAW eye(1) WITH SHIFT(x-0.25,y) END IF !!!SET TEXT JUSTIFY "center","half" !!!PLOT TEXT ,AT x,y: STR$(T(3)) END SUB PICTURE eye(c) !目の1つを表示する SET AREA COLOR c DRAW disk WITH SCALE(0.1) END PICTURE END