Aizu Online Judge(AOJ)が提供している「プログラミング入門」(ITP1)の11_C問題をC++とPython で解いてみました。
ITP1 のトピック11では、構造体とクラスについて学びます。「構造体やクラスによって独自の型を定義し、プログラムで利用します。」とあります。この学習コースを通じて、Python に慣れていきたいと考えています。
問題(11_C:Dice III)
問題はリンク先をご覧ください。
前回(11-A)に作成した Dice クラスに機能を追加して、問題を解きます。
考察
ベースとなるクラスの仕様は、11_Aの記事を参照してください。
今回は、サイコロの目(number)を正規化する norm メソッドを追加します。正規化は、サイコロの数字の並びをある規則で並べ直します。norm は、11_B で実装した get_right と処理が似ています。
以下は、norm の実装方針です。これは正規化の定義にもなっています。
- サイコロの一番小さな数を上の面(number[0])に移動させる。
- 2番目に小さな数を前の面(number[1])に移動させる。
- 2番目に小さな数が下の面(number[5])の場合、3番目に小さな数を前の面(number[1])に移動させる。
解答案
C++ プログラム例(ITP1 11_C)
以下は、考察で扱った norm メソッドのプログラムです。
vector<int> norm(void)
{
vector<int> temp(6);
temp = number;
sort(temp.begin(), temp.end());
if (temp[0] == number[1]) {
this->N();
} else if (temp[0] == number[2]) {
this->W();
} else if (temp[0] == number[3]) {
this->E();
} else if (temp[0] == number[4]) {
this->S();
} else if (temp[0] == number[5]) {
this->N();
this->N();
}
if (temp[1] == number[2]) {
this->roll();
} else if (temp[1] == number[3]) {
this->roll();
this->roll();
this->roll();
} else if (temp[1] == number[4]) {
this->roll();
this->roll();
} else if (temp[1] == number[5]) {
if (temp[2] == number[2]) {
this->roll();
} else if (temp[2] == number[3]) {
this->roll();
this->roll();
this->roll();
} else if (temp[2] == number[4]) {
this->roll();
this->roll();
}
}
return number;
}
サイコロの処理を Dice クラスで処理しているため、main 自体は、以下のようにすっきりと書けています。
int main()
{
vector<int> number1(6);
for (int i = 0; i < 6; ++i) {
cin >> number1[i];
}
vector<int> number2(6);
for (int i = 0; i < 6; ++i) {
cin >> number2[i];
}
Dice d1(number1);
Dice d2(number2);
if (d1.norm() == d2.norm()) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
return 0;
}
プログラム全体は、このブログ記事の最後に掲載しました。
Python プログラム例(ITP1 11_C)
Python 版の Dice クラスにも、同じようにクラスメソッドを追加します。追加した norm メソッドは、以下となります。
def norm(self):
temp = self.n.copy()
temp.sort()
if temp[0] == self.n[1]:
self.N()
elif temp[0] == self.n[2]:
self.W()
elif temp[0] == self.n[3]:
self.E()
elif temp[0] == self.n[4]:
self.S()
elif temp[0] == self.n[5]:
self.N()
self.N()
if temp[1] == self.n[2]:
self.roll()
elif temp[1] == self.n[3]:
self.roll()
self.roll()
self.roll()
elif temp[1] == self.n[4]:
self.roll()
self.roll()
elif temp[1] == self.n[5]:
if temp[2] == self.n[2]:
self.roll()
elif temp[2] == self.n[3]:
self.roll()
self.roll()
self.roll()
elif temp[2] == self.n[4]:
self.roll()
self.roll()
return self.n
インスタンス変数 n を一時的なリスト temp にコピーしています。ただの代入では、参照がコピーされるだけなので、うまく動作しません(temp を sort すると、self.n も sort されます)。このため copy メソッドを使っています(2行目)。
処理の本体は、以下となります。処理を Dice クラスにまかせているため、3行で書けています。
d1 = Dice(list(map(int, input().split())))
d2 = Dice(list(map(int, input().split())))
print("Yes" if d1.norm() == d2.norm() else "No")
プログラム全体は、このブログ記事の最後に掲載しました。
最後に
今回は、Dice クラスのメソッドを追加しました。このメソッドを追加した効果は、次回の問題を解くときに発揮されます。
次回が ITP1 最後の問題となります。
C++ 全体ソース(ITP1 11_C)
以下が、C++ 版の全体ソースコードとなります。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
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;
}
vector<int> norm(void)
{
vector<int> temp(6);
temp = number;
sort(temp.begin(), temp.end());
if (temp[0] == number[1]) {
this->N();
} else if (temp[0] == number[2]) {
this->W();
} else if (temp[0] == number[3]) {
this->E();
} else if (temp[0] == number[4]) {
this->S();
} else if (temp[0] == number[5]) {
this->N();
this->N();
}
if (temp[1] == number[2]) {
this->roll();
} else if (temp[1] == number[3]) {
this->roll();
this->roll();
this->roll();
} else if (temp[1] == number[4]) {
this->roll();
this->roll();
} else if (temp[1] == number[5]) {
if (temp[2] == number[2]) {
this->roll();
} else if (temp[2] == number[3]) {
this->roll();
this->roll();
this->roll();
} else if (temp[2] == number[4]) {
this->roll();
this->roll();
}
}
return number;
}
};
int main()
{
vector<int> number1(6);
for (int i = 0; i < 6; ++i) {
cin >> number1[i];
}
vector<int> number2(6);
for (int i = 0; i < 6; ++i) {
cin >> number2[i];
}
Dice d1(number1);
Dice d2(number2);
if (d1.norm() == d2.norm()) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
return 0;
}
Python 全体ソース(ITP1 11_C)
以下が、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 norm(self):
temp = self.n.copy()
temp.sort()
if temp[0] == self.n[1]:
self.N()
elif temp[0] == self.n[2]:
self.W()
elif temp[0] == self.n[3]:
self.E()
elif temp[0] == self.n[4]:
self.S()
elif temp[0] == self.n[5]:
self.N()
self.N()
if temp[1] == self.n[2]:
self.roll()
elif temp[1] == self.n[3]:
self.roll()
self.roll()
self.roll()
elif temp[1] == self.n[4]:
self.roll()
self.roll()
elif temp[1] == self.n[5]:
if temp[2] == self.n[2]:
self.roll()
elif temp[2] == self.n[3]:
self.roll()
self.roll()
self.roll()
elif temp[2] == self.n[4]:
self.roll()
self.roll()
return self.n
d1 = Dice(list(map(int, input().split())))
d2 = Dice(list(map(int, input().split())))
print("Yes" if d1.norm() == d2.norm() else "No")
上記プログラムは、どちらも AOJ で「AC(Accepted=正解)」と判定されます。