AIZU ONLINE JUDGE

AOJ ITP1 11_B(Dice II)を解く

AOJ_ITP1_11_B

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

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

問題(11_B:Dice II)

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

AOJ ITP1 11_B問題:Dice II

前回(11-A)に作成した Dice クラスを再利用して、問題を解きます。

考察

Dice クラスを変更せずにそのまま再利用します。クラスの仕様は、前回の記事を参照してください。

今回、問題として問われている右の面を返す関数 get_right は、クラスメソッドではなく、クラスの外の関数として実装することにしました。この関数が提供する機能は、クラスにこれから必要ではなく、この問題に特化した機能だと判断したためです。

解答案

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

今回、新設する関数 get_right は、3個の引数を持ちます。

  • Dice クラスのインスタンス d(対象となるサイコロ)
  • 上の面に位置させたい数 top
  • 前の面に位置させたい数 front

最初に top で指定された数を上の面(number[0])に移動させます。

次に front で指定された数を前の面(number[1])に roll を使って移動させます。roll を使うのは、上の面を変えないためです。最後に右の面(number[2])を返します。

もし、上の面を移動した後、下の面(number[5])に front があれば、-1 を返します。この場合は、上の面を top に、前の面を front とすることができません。

以下は、関数 get_right のプログラムです。

int get_right(Dice d, int top, int front)
{
	vector<int> number;
	number = d.get_number();

	if (top == number[1]) {
		d.N();
	} else if (top == number[2]) {
		d.W();
	} else if (top == number[3]) {
		d.E();
	} else if (top == number[4]) {
		d.S();
	} else if (top == number[5]) {
		d.N();
		d.N();
	}
	number = d.get_number();

	if (front == number[1]) {
		// do nothing
	} else if (front == number[2]) {
		d.roll();
	} else if (front == number[3]) {
		d.roll();
		d.roll();
		d.roll();
	} else if (front == number[4]) {
		d.roll();
		d.roll();
	} else {
		return -1;
	}
	number = d.get_number();

	return number[2];
}

サイコロの処理を Dice クラスおよび get_right 関数で処理しているため、main 自体は、以下のようにすっきりと書けています。

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

	Dice d(number);

	int q;
	cin >> q;
	for (int i = 0; i < q; ++i) {
		int top, front;
		cin >> top >> front;
		cout << get_right(d, top, front) << endl;
	}

	return 0;
}

長くなったためプログラム全体は、このブログ記事の最後に掲載しました。

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

Python 版の Dice クラスも、11_A 版とまったく同一です。C++ と同じ仕様で get_right 関数を追加で実装しました。

全体の 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


def get_right(d, top, front):
    number = d.get_number()

    if top == number[1]:
        d.N()
    elif top == number[2]:
        d.W()
    elif top == number[3]:
        d.E()
    elif top == number[4]:
        d.S()
    elif top == number[5]:
        d.N()
        d.N()
    number = d.get_number()

    if front == number[1]:
        pass
    elif front == number[2]:
        d.roll()
    elif front == number[3]:
        d.roll()
        d.roll()
        d.roll()
    elif front == number[4]:
        d.roll()
        d.roll()
    else:
        return -1
    number = d.get_number()

    return number[2]


number = list(map(int, input().split()))
d = Dice(number)
q = int(input())
for i in range(q):
    top, front = map(int, input().split())
    print(get_right(d, top, front))

この Python プログラムは、AOJ で「AC(Accepted=正解)」と判定されます。

最後に

C++ 版の Dice クラスは、94行です。そのプログラムを、1行も変更しないで再利用することができました。また、本来クラスは別ファイルで管理しますが、採点をするために1ファイルにしています。

また、追加する機能をクラスメソッドとして実装するのか、クラスの外の関数として実装するのか判断しました。これは、人によって判断が異なるかもしれません。

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

C++ 全体ソース(ITP1 11_B)

以下が、C++ 版の全体ソースコードとなります。

#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 get_right(Dice d, int top, int front)
{
	vector<int> number;
	number = d.get_number();

	if (top == number[1]) {
		d.N();
	} else if (top == number[2]) {
		d.W();
	} else if (top == number[3]) {
		d.E();
	} else if (top == number[4]) {
		d.S();
	} else if (top == number[5]) {
		d.N();
		d.N();
	}
	number = d.get_number();

	if (front == number[1]) {
		// do nothing
	} else if (front == number[2]) {
		d.roll();
	} else if (front == number[3]) {
		d.roll();
		d.roll();
		d.roll();
	} else if (front == number[4]) {
		d.roll();
		d.roll();
	} else {
		return -1;
	}
	number = d.get_number();

	return number[2];
}

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

	Dice d(number);

	int q;
	cin >> q;
	for (int i = 0; i < q; ++i) {
		int top, front;
		cin >> top >> front;
		cout << get_right(d, top, front) << endl;
	}

	return 0;
}

この C++ プログラムは、AOJ で「AC(Accepted=正解)」と判定されます。

COMMENT

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

CAPTCHA