AIZU ONLINE JUDGE

AOJ ITP1 11_A(Dice I)を解く

AOJ_ITP1_11_A

Aizu Online Judge(AOJ)が提供している「プログラミング入門」(ITP1)の11_A問題をC++とPython で解いてみました。

ITP1 のトピック11では、構造体とクラスについて学びます。「構造体やクラスによって独自の型を定義し、プログラムで利用します。」とあります。この学習コースを通じて、Python に慣れていきたいと考えています。

問題(11_A:Dice I)

問題はリンク先をご覧ください。

AOJ ITP1 11_A問題:Dice I

トピック11を通じて利用する Dice クラスを設計、プログラムします。

Dice クラスの設計

サイコロを表現する Dice クラスを設計します。

まず、サイコロを表す6個の数字を以下の図の順番で番号を付けます。また、転がす方法を表す図も示します。

AOJ ITP1 11_A の問題から借用しました。
AOJ ITP1 11_A の問題から借用しました。
この図は、AOJ ITP1 の11_A問題のページから借用させていただきました。

問題が求めている E方向、N方向、S方向、W方向の転がし、文字による転がし、その時点での数字の取得をクラスメソッドとして実装します。これらに加えて、上から見た時に時計回りに転がす roll も実装します。

以下は、Dice クラスが持つメソッド一覧です。

メソッド名メソッドの説明
コンストラクタクラスインスタンスを生成する。6個の数字を引数に与える。
EE方向にサイコロを90度転がす
NN方向にサイコロを90度転がす
SS方向にサイコロを90度転がす
WW方向にサイコロを90度転がす
roll上から見て、時計周りに90度転がす
moveENSWの文字列を与えると、その方向に90度転がす。
get_number今のサイコロの数字(向き)を返す。

解答案

C++ プログラム例(ITP1 11_A)

設計したメソッドを実装します。図の数字は、1から始めていますが、vector 型のコンテナの添え字は、0 から始めます。転がすメソッドは、もっと上手くプログラムする方法があるかもしれませんが、地道に書きました。

コンストラクタを呼び出し、インスタンスを生成します(109行目)。インスタンスを経由してメソッドを呼び出しています(114、117行目)。

かなり長くなりましたが、全体のプログラムは以下となります。

#include <iostream>
#include <vector>
#include <string>

using namespace std;

class Dice {
	vector<int> number;

public:
	Dice(vector<int> num)
	{
		number = num;
	}

	void E(void)
	{
		vector<int> temp(6);
		temp[2] = number[0];
		temp[1] = number[1];
		temp[5] = number[2];
		temp[0] = number[3];
		temp[4] = number[4];
		temp[3] = number[5];
		number = temp;
	}

	void N(void)
	{
		vector<int> temp(6);
		temp[4] = number[0];
		temp[0] = number[1];
		temp[2] = number[2];
		temp[3] = number[3];
		temp[5] = number[4];
		temp[1] = number[5];
		number = temp;
	}

	void S(void)
	{
		vector<int> temp(6);
		temp[1] = number[0];
		temp[5] = number[1];
		temp[2] = number[2];
		temp[3] = number[3];
		temp[0] = number[4];
		temp[4] = number[5];
		number = temp;
	}

	void W(void)
	{
		vector<int> temp(6);
		temp[3] = number[0];
		temp[1] = number[1];
		temp[0] = number[2];
		temp[5] = number[3];
		temp[4] = number[4];
		temp[2] = number[5];
		number = temp;
	}

	void roll(void)
	{
		vector<int> temp(6);
		temp[0] = number[0];
		temp[3] = number[1];
		temp[1] = number[2];
		temp[4] = number[3];
		temp[2] = number[4];
		temp[5] = number[5];
		number = temp;
	}

	void move(char ch)
	{
		switch (ch) {
		case 'E':
			this->E();
		    break;
		case 'N':
			this->N();
		    break;
		case 'S':
			this->S();
		    break;
		case 'W':
			this->W();
		    break;
		default:
		    break;
		}
	}

	vector<int> get_number(void)
	{
		return number;
	}
};

int main()
{
	vector<int> number(6);
	for (int i = 0; i < 6; ++i) {
		cin >> number[i];
	}

	Dice d(number);

	string s;
	cin >> s;
	for (int i = 0; i < s.length(); ++i) {
		d.move(s[i]);
	}

	number = d.get_number();
	cout << number[0] << endl;

	return 0;
}

Python プログラム例(ITP1 11_A)

Python でもクラスを使うことができます。

  • クラス名は、慣例で大文字から始めます。
  • コンストラクタは、__init__ になります。
  • メソッドの第一引数は、クラスのインスタンスを指定します。慣例で self としています。第二引数以降で、メソッドの引数を受け取ります。

Dice クラスを定義した後、39行目からが本文となります。コンストラクタを呼び出し、Dice クラスのインスタンス d を生成しています(40行目)。生成したインスタンスからメソッドを呼び出しています(43、45行目)。

以下が、Python のプログラムとなります。

class Dice:
    def __init__(self, number):
        self.n = number.copy()

    def E(self):
        self.n[2], self.n[5], self.n[0], self.n[3] = \
            self.n[0], self.n[2], self.n[3], self.n[5]

    def N(self):
        self.n[4], self.n[0], self.n[5], self.n[1] = \
            self.n[0], self.n[1], self.n[4], self.n[5]

    def S(self):
        self.n[1], self.n[5], self.n[0], self.n[4] = \
            self.n[0], self.n[1], self.n[4], self.n[5]

    def W(self):
        self.n[3], self.n[0], self.n[5], self.n[2] = \
            self.n[0], self.n[2], self.n[3], self.n[5]

    def roll(self):
        self.n[3], self.n[1], self.n[4], self.n[2] = \
            self.n[1], self.n[2], self.n[3], self.n[4]

    def move(self, ch):
        if ch == 'E':
            self.E()
        elif ch == 'N':
            self.N()
        elif ch == 'S':
            self.S()
        elif ch == 'W':
            self.W()

    def get_number(self):
        return self.n


number = list(map(int, input().split()))
d = Dice(number)
s = input()
for i, ch in enumerate(s):
    d.move(ch)

number = d.get_number()
print(number[0])

上記プログラムは、すべて AOJ で「AC(Accepted=正解)」と判定されます。

最後に

クラスを取り扱うトピック11は、トピック10までと比較して難易度が上がりました。

クラスは、関数と比較して、より大規模な再利用を可能にします。今回、作成した Dice クラスは、トピック11を通じて、再利用していきます。

引き続き、ITP1 の問題を紹介していきます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA