プログラミンコンテストでは、サイコロを回転させていき、出目の遷移がどのようになったか?というような問題が出されることがあります。
そこで今回は、1〜6までの目を持つ、いわゆる普通のサイコロを回転させる方法を紹介します。
全体的なコード
はじめにコードの全体像を以下に示します。一番上の行で、numpy を import しているように、今回は numpy で用意されている、numpy.roll( ) を使って、簡単に処理をしています。
import numpy as np
# 1)右回転させる関数
def right_rotate(dice, times):
dice[1] = np.roll(dice[1], times)
dice[3][1] = dice[1][3]
return dice
# 2)左回転させる関数
def left_rotate(dice, times):
dice[1] = np.roll(dice[1], times*-1)
dice[3][1] = dice[1][3]
return dice
# 3)上回転させる関数
def up_rotate(dice, times):
dice[:, 1] = np.roll(dice[:, 1], times*-1)
dice[1][3] = dice[3][1]
return dice
# 4)下回転させる関数
def down_rotate(dice, times):
dice[:, 1] = np.roll(dice[:, 1], times)
dice[1][3] = dice[3][1]
return dice
# 5)サイコロの展開図
dice = np.array([
[0, 2, 0, 0],
[3, 1, 4, 6],
[0, 5, 0, 0],
[0, 6, 0, 0]
])
#回転させる例
dice = right_rotate(dice, 1)
print(dice)
# --> [[0 2 0 0]
# [6 3 1 4]
# [0 5 0 0]
# [0 4 0 0]]
dice = left_rotate(dice, 2)
print(dice)
# --> [[0 2 0 0]
# [1 4 6 3]
# [0 5 0 0]
# [0 3 0 0]]
dice = up_rotate(dice, 1)
print(dice)
# --> [[0 4 0 0]
# [1 5 6 2]
# [0 3 0 0]
# [0 2 0 0]]
dice = down_rotate(dice, 2)
print(dice)
# --> [[0 3 0 0]
# [1 2 6 5]
# [0 4 0 0]
# [0 5 0 0]]
サイコロの展開図
上記コードの 5)サイコロの展開図を確認して下さい。ここではサイコロの初期状態を入力します。先述のようにnumpy.roll( )を使いたいので、np.array としています。
dice = np.array([
[0, 2, 0, 0],
[3, 1, 4, 6],
[0, 5, 0, 0],
[0, 6, 0, 0]
])
またここでは np.array[1][1] を上面、np.array[1][3]および をnp.array[3][1]を底面としています。底面の情報を重複させている部分が実際の展開図と異なります。また np.array[2][1]が手前に来る側面、そして np.array[0][1] が奥にくる側面としています。
左右回転
右回転は、def right_rotate(dice, times)、左回転は def left_rotate(dice, times) でそれぞれ定義しています。右回転を例に、中身を説明します。
# 1)右回転
def right_rotate(dice, times):
dice[1] = np.roll(dice[1], times) # a)回転部
dice[3][1] = dice[1][3] # b)底面の補正
return dice
まず、引数に dice と times を与えます。dice は上で定義したサイコロの展開図そのもので、これを本関数内で変換して、最後に return で返します。また times については 何回転させるか?であり、任意の数だけ回転することができるようにしています。
実際に回転操作を行うのは a) の部分で np.roll(dice[1], times) と記述するだけで、簡単に回転を実現できます。また dice[1] としているのは、左右回転に関する情報は np.array である dice の 1行目にしか記述していないからです。
そしてこの操作では、上下方向に対する操作は何もしていませんので、重複させて持たせている dice[3][1]の底面の値が変更されません。よって、b) の部分で底面の情報を更新しています。
左回転、def left_rotate(dice, times) では、 a) の部分の timesをマイナスの符号にすれば逆方向に回転させてくれますので、
dice[1] = np.roll(dice[1], times*-1)
としています。
上下回転
# 3)上回転
def up_rotate(dice, times):
dice[:, 1] = np.roll(dice[:, 1], times*-1) # c)
dice[1][3] = dice[3][1]
return dice
上下回転についても、基本的には左右回転と同じです。ただし、今回はdice の1列目を回転させなくてはなりません。この操作についても numpy.array では簡単にでき、c) の部分のように、dice[:, 1] と記述するだけで1列目を抽出できます。
以上が、普通のサイコロを numpy の機能を使って回転させる方法です。