# APCS實作題2020年7月第2題:骰子
> 日期:2023年9月13日
> 作者:王一哲
> 題目來源:109年7月實作題第2題
> [ZeroJudge 題目連結](https://zerojudge.tw/ShowProblem?problemid=f580)
<br />
## 題目
### 問題描述
給定 $n$ 個骰子排成一列,一開始都是點數 $1$ 朝上,點數 $4$ 朝前,點數 $2$ 朝右 (如圖1所示),另外骰子的展開圖如圖2所示。
<img height="55%" width="55%" src="https://imgur.com/fOiAuY6.png" style="display: block; margin-left: auto; margin-right: auto;"/>
<div style="text-align:center">圖1</div>
<br />
<img height="30%" width="30%" src="https://imgur.com/Ni0TjdI.png" style="display: block; margin-left: auto; margin-right: auto;"/>
<div style="text-align:center">圖2</div>
<br />
接下來有 $m$ 次修改操作,每個操作包含兩個整數 $a$、$b$
- 若 $a$、$b$ 都是正整數,交換編號 $a$ 與編號 $b$ 的骰子的位置。
- 若 $b$ 為 $-1$,將編號 $a$ 的骰子**向前**旋轉。
- 若 $b$ 為 $-2$,將編號 $a$ 的骰子**向右**旋轉。
<img height="35%" width="35%" src="https://imgur.com/km7kecG.png" style="display: block; margin-left: auto; margin-right: auto;"/>
<div style="text-align:center">向前旋轉</div>
<br />
<img height="35%" width="35%" src="https://imgur.com/zAWZOv0.png" style="display: block; margin-left: auto; margin-right: auto;"/>
<div style="text-align:center">向右旋轉</div>
<br />
在 $m$ 次操作結束之後,依序輸出編號 $1$ 到編號 $n$ 的骰子朝上的點數。
<br />
### 輸入格式
第一行包含兩個正整數 $n$、$m$($1 \leq n \leq 20, ~1 \leq m \leq 100$)。
接下來 $m$ 行每行有兩個整數,第 $i$ 行的兩個正整數表示第 $i$ 次操作。
<br />
### 輸出格式
在一行輸出 $n$ 個數字以空格分隔,第 $i$ 個數字表示編號 $i$ 的骰子最後朝上的點數。
<br />
### 範例一:輸入
```
1 2
1 -2
1 -1
```
### 範例一:正確輸出
```
3
```
<br />
### 範例二:輸入
```
3 3
2 -1
3 -2
3 1
```
### 範例二:正確輸出
```
5 3 1
```
<br />
## Python 程式碼
### 方法1:使用二維串列
於 ZeroJudge 測試結果,最長運算時間約為 43 ms,使用記憶體最多約為 3.4 MB,通過測試。
```python=
# 自訂函式向前旋轉
def rotateF(dice):
tmp = dice[0]
dice[0] = dice[4]
dice[4] = dice[1]
dice[1] = dice[2]
dice[2] = tmp
return dice
# 自訂函式向右旋轉
def rotateR(dice):
tmp = dice[0]
dice[0] = dice[5]
dice[5] = dice[1]
dice[1] = dice[3]
dice[3] = tmp
return dice
# 解題過程
n, m = map(int, input().split()) # 讀取資料 n, m
dices = [[1, 6, 4, 2, 3, 5] for _ in range(n)] # 儲存骰子每面數值的二維串列,順序為上、下、前、右、後、左
for _ in range(m): # 讀取 m 行操作資料
a, b = map(int, input().split())
if b > 0: # 交換骰子
dices[a-1], dices[b-1] = dices[b-1], dices[a-1]
elif b == -1: # 向前旋轉
dices[a-1] = rotateF(dices[a-1])
elif b == -2: # 向右旋轉
dices[a-1] = rotateR(dices[a-1])
for i in range(n): # 印出每顆骰子朝上的點數
print(dices[i][0], end=" " if i < n-1 else "\n")
```
<br /><br />
### 方法2:使用自訂類別
於 ZeroJudge 測試結果,最長運算時間約為 21 ms,使用記憶體最多約為 3.4 MB,通過測試。
```python=
# 自訂類別
class Dice:
def __init__(self):
self.top = 1
self.bottom = 6
self.front = 4
self.right = 2
self.back = 3
self.left = 5
def rotateF(self): # 自訂函式向前旋轉
tmp = self.top
self.top = self.back
self.back = self.bottom
self.bottom = self.front
self.front = tmp
def rotateR(self): # 自訂函式向右旋轉
tmp = self.top
self.top = self.left
self.left = self.bottom
self.bottom = self.right
self.right = tmp
# 解題過程
n, m = map(int, input().split()) # 讀取資料 n, m
dices = [Dice() for _ in range(n)] # 儲存骰子資料的一維串列
for _ in range(m): # 讀取 m 行操作資料
a, b = map(int, input().split())
if b > 0: # 交換骰子
dices[a-1], dices[b-1] = dices[b-1], dices[a-1]
elif b == -1: # 向前旋轉
dices[a-1].rotateF()
elif b == -2: # 向右旋轉
dices[a-1].rotateR()
for i in range(n): # 印出每顆骰子朝上的點數
print(dices[i].top, end=" " if i < n-1 else "\n")
```
<br /><br />
## C++ 程式碼
### 方法1:使用二維陣列
於 ZeroJudge 測試結果,最長運算時間約為 3 ms,使用記憶體最多約為 328 kB,通過測試。
```cpp=
#include <iostream>
#include <algorithm>
using namespace std;
// 自訂函式向前旋轉
void rotateF(int* dice) {
int tmp = dice[0];
dice[0] = dice[4];
dice[4] = dice[1];
dice[1] = dice[2];
dice[2] = tmp;
}
// 自訂函式向右旋轉
void rotateR(int* dice) {
int tmp = dice[0];
dice[0] = dice[5];
dice[5] = dice[1];
dice[1] = dice[3];
dice[3] = tmp;
}
int main() {
// 解題過程
int n, m; cin >> n >> m; // 讀取資料 n, m
int dices[n][6];
for(int i=0; i<n; i++) { // 儲存骰子每面數值的二維陣列,順序為上、下、前、右、後、左
dices[i][0] = 1; dices[i][1] = 6;
dices[i][2] = 4; dices[i][3] = 2;
dices[i][4] = 3; dices[i][5] = 5;
}
for(int i=0; i<m; i++) { // 讀取 m 行操作資料
int a, b; cin >> a >> b;
if (b > 0) { // 交換骰子
swap(dices[a-1], dices[b-1]);
} else if (b == -1) { // 向前旋轉
rotateF(dices[a-1]);
} else if (b == -2) { // 向右旋轉
rotateR(dices[a-1]);
}
}
for(int i=0; i<n; i++) { // 印出每顆骰子朝上的點數
cout << dices[i][0] << " \n"[i == n-1];
}
return 0;
}
```
<br /><br />
### 方法2:使用自訂類別
於 ZeroJudge 測試結果,最長運算時間約為 3 ms,使用記憶體最多約為 340 kB,通過測試。
```cpp=
#include <iostream>
#include <algorithm>
using namespace std;
class Dice {
public:
int top = 1, bottom = 6, front = 4, right = 2, back = 3, left = 5;
// 自訂函式向前旋轉
void rotateF() {
int tmp = top;
top = back;
back = bottom;
bottom = front;
front = tmp;
}
// 自訂函式向右旋轉
void rotateR() {
int tmp = top;
top = left;
left = bottom;
bottom = right;
right = tmp;
}
};
int main() {
// 解題過程
int n, m; cin >> n >> m; // 讀取資料 n, m
Dice dices[n];
for(int i=0; i<m; i++) { // 讀取 m 行操作資料
int a, b; cin >> a >> b;
if (b > 0) { // 交換骰子
swap(dices[a-1], dices[b-1]);
} else if (b == -1) { // 向前旋轉
dices[a-1].rotateF();
} else if (b == -2) { // 向右旋轉
dices[a-1].rotateR();
}
}
for(int i=0; i<n; i++) { // 印出每顆骰子朝上的點數
cout << dices[i].top << " \n"[i == n-1];
}
return 0;
}
```
<br /><br />
---
###### tags:`APCS`、`Python`、`C++`