LoginSignup
2
1

More than 1 year has passed since last update.

AOJ ITP1_11_A: Dice I サイコロ問題

Last updated at Posted at 2019-05-14

ITP1_11_A

Dice I | Aizu Online Judge
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_11_A

問題は処理の部分
サイコロを一方向に回すとき
4面が動き
2面は固定
Nに1回動くときはSに3回動く
Wに1回動くときはEに3回動く

サイコロの面は配列として考え0-5までに当てはめる。
このプログラムは配列の添字をベースとして考え
動く前と動いたあとの数値を連鎖をさせながら考えている。

0, 1, 5, 4などのマジックワードが出てくるが、
これはサイコロの面の動きを原始的に考えているだけ。

Nに1回動かすと考え(X軸方向)
添字は
0 1 2 3 4 5 (初期値)から
1 5 2 3 0 4 と変化する
ここは紙の出番。
紙上で書きながら考える。
(自分には頭の中だけで考えるのは無理。)

2面と3面は固定しているのがわかる。(変化なし)
動いているのは4面
初期値の動く数字を見ていく
上面の0はtemporary(=一時退避)
0には1を入れる。
1の場所には5を入れる。
5の場所には4を入れる
4の場所には0 (=temporary)を入れる。

トップを一旦退避して、そこに数字を入れ、さらにそこに入れた数字を追いかけていきながら考える。
添字で考えているので6面サイコロならどんな数字でも対応可能。

これをプログラムとして書くと

dice.cpp
void roll_x() { roll(0, 1, 5, 4); }  // to N
void roll(int i, int j, int k, int l) {
    int t = f[i];
    f[i]  = f[j];
    f[j]  = f[k];
    f[k]  = f[l];
    f[l]  = t;
}

この考えを元にy軸方向とz軸方向でも考える。

Z軸
012345(初期値)
024135(0と5は固定)

Y軸
012345(初期値)
215043(1と4は固定)

dice.cpp
void roll_z() { roll(1, 2, 4, 3); }
void roll_y() { roll(0, 2, 5, 3); }  // to W

と答えが出る。

参考

オンラインジャッジではじめるC/C++プログラミング入門 p238

dice.cpp
# include <bits/stdc++.h>
using namespace std;

class Cube {
   public:
    int f[6];  //サイコロ
    Cube() {}  //コンストラクタ
    void roll_z() { roll(1, 2, 4, 3); }
    void roll_y() { roll(0, 2, 5, 3); }  // to W
    void roll_x() { roll(0, 1, 5, 4); }  // to N
    void roll(int i, int j, int k, int l) {
        int t = f[i];
        f[i]  = f[j];
        f[j]  = f[k];
        f[k]  = f[l];
        f[l]  = t;
    }
    void move(char ch) {
        if (ch == 'E')
            for (int i = 0; i < 3; i++) roll_y();  // Wを3回
        if (ch == 'W') roll_y();
        if (ch == 'N') roll_x();
        if (ch == 'S')
            for (int i = 0; i < 3; i++) roll_x();  // Nを3回
    }
};

int main() {
    Cube   c;    // サイコロ
    string com;  // 命令

    // 入力
    for (int i = 0; i < 6; i++) cin >> c.f[i];  // サイコロの面
    cin >> com;                                 // 命令

    // 処理
    for (int i = 0; i < com.size(); i++) {
        c.move(com[i]);
    }

    // 出力
    cout << c.f[0] << "\n";

    return 0;
}

感想

クラスを使うということでプログラミングへの心理的障壁は高かったが、中身を改めて見渡すと中学生でも簡単だと思えるレベルのものだった。
しかし、紙上でサイコロの面を追いかけながらどの数字がどこに入るかを追いかけていくのはかなりの時間がかかってしまった。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1