さいころを転がす

 投稿者:山中和義  投稿日:2008年11月18日(火)18時56分39秒
  私からも1つパズルを紹介します。

●問題
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
 

戻る