プログラミンコンテストでは、サイコロを回転させていき、出目の遷移がどのようになったか?というような問題が出されることがあります。
 そこで今回は、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 の機能を使って回転させる方法です。