BOJ[14499] - 주사위 굴리기 by JavaScript
주사위 굴리기
문제
언어
- JavaScript
순서도
- 주사위를 굴리는 함수 구현
- 주사위 정보와 지도 정보 구현
- 주어진 명령에 따라서 주사위 굴리기
문제 풀이 step 1
- 구현 문제로서, 문제에서 주어진 설명대로 구현하는 문제입니다.
- 우선 주사위를 어떻게 굴려야 하며, 굴렸을 때 주사위 정보는 어떻게 저장을 해야하는지 고민을 해야합니다.
- 저는 문제에서 제공된 주사위의 전개도 사진을 참고해서 주사위 정보를 저장했습니다.
- 2 차원 배열을 이용해서, 주사위의 전개도 모양 만큼만 주사위 정보를 저장했습니다.
- 이 때, 바닥면은 (1, 1) 이고, 상단면은 (3, 1) 입니다.
문제 풀이 step 2
- 주사위 정보를 저장한 후에, 주사위를 굴리는 로직을 구현해야 합니다.
- 1 번 명령 : 동쪽 이동
- 첫 번째 사진에서 주사위를 동쪽으로 굴리면 이런 모양이 나옵니다.
- 왼쪽에는 주사위에 적힌 수의 이동 변화를, 오른쪽에는 좌표값의 이동 변화를 적었습니다.
- 이를 소스코드로 나타내면,
[dice[1][0], dice[1][1], dice[1][2], dice[3][1]] = [ dice[1][1], dice[1][2], dice[3][1], dice[1][0], ];
- 2번 명령 : 서쪽 이동
- 첫 번째 사진에서 주사위를 서쪽으로 굴리면 이런 모양이 나옵니다.
[dice[1][0], dice[1][1], dice[1][2], dice[3][1]] = [ dice[3][1], dice[1][0], dice[1][1], dice[1][2], ];
- 첫 번째 사진에서 주사위를 서쪽으로 굴리면 이런 모양이 나옵니다.
- 3번 명령 : 북쪽 명령
- 첫 번째 사진에서 주사위를 북쪽으로 굴리면 이런 모양이 나옵니다.
[dice[0][1], dice[1][1], dice[2][1], dice[3][1]] = [ dice[3][1], dice[0][1], dice[1][1], dice[2][1], ];
- 첫 번째 사진에서 주사위를 북쪽으로 굴리면 이런 모양이 나옵니다.
- 4번 명령 : 남쪽 명령
- 첫 번째 사진에서 주사위를 남쪽으로 굴리면 이런 모양이 나옵니다.
[dice[0][1], dice[1][1], dice[2][1], dice[3][1]] = [ dice[1][1], dice[2][1], dice[3][1], dice[0][1], ];
- 첫 번째 사진에서 주사위를 남쪽으로 굴리면 이런 모양이 나옵니다.
문제 풀이 step 3
- 주사위를 굴리는 로직을 다 구현했으면, 주어진 명령에 맞게 주사위를 굴리면서 주사위의 상단면을 기록해서 출력하면 정답입니다.
- 이 때, 다음과 같은 조건들이 있는데,
- 주사위와 맞닿은 지도의 수가 0 이면, 주사위의 바닥면의 수가 지도로 복사
- 주사위와 맞닿은 지도의 수가 0 이 아니면, 지도의 수가 바닥면으로 복사 후 지도의 수는 0 으로 변환
- 위 조건들을 만족하면서 주사위를 굴리면 되겠습니다.
후기
- 문제를 풀기 시작할 때는 정말 막막했는데, 문제 안에 힌트가 있었습니다.
- 바로 주사위 전개도 사진입니다. 이 사진 덕분에 풀 수 있었습니다.
- 이런 유형의 문제는 실제로 그려보면서, 배열의 idnex 변화 추이를 살펴보면 문제 해결의 열쇠에 가까워지는 것 같습니다.
- 고민하는 과정 속에서 떠오르는 아이디어들을 실현하기 어려울 것 같다고 생각해서 섣부르게 버렸었는데, 우선은 적어놓는 것이 문제 해결에 더욱 가까워지는 것 같습니다.
소스 코드
const input = require("fs")
.readFileSync("/dev/stdin")
.toString()
.trim()
.split("\n");
const isPossibleRoute = (n, m, x, y) => 0 <= x && x < n && 0 <= y && y < m;
const moveDice = (dice, command) => {
if (command <= 1) {
[dice[1][0], dice[1][1], dice[1][2], dice[3][1]] = [
dice[1][1],
dice[1][2],
dice[3][1],
dice[1][0],
];
} else if (command <= 2) {
[dice[1][0], dice[1][1], dice[1][2], dice[3][1]] = [
dice[3][1],
dice[1][0],
dice[1][1],
dice[1][2],
];
} else if (command <= 3) {
[dice[0][1], dice[1][1], dice[2][1], dice[3][1]] = [
dice[3][1],
dice[0][1],
dice[1][1],
dice[2][1],
];
} else {
[dice[0][1], dice[1][1], dice[2][1], dice[3][1]] = [
dice[1][1],
dice[2][1],
dice[3][1],
dice[0][1],
];
}
};
const solution = (input) => {
let [n, m, x, y, k] = input[0].split(" ").map(Number);
let arr = input.slice(1, n + 1).map((v) => v.split(" ").map(Number));
let commands = input[n + 1].split(" ").map(Number);
// 주사위 초기화
const dice = [
[null, 0, null],
[0, 0, 0],
[null, 0, null],
[null, 0, null],
];
let diceBot = [1, 1];
let diceTop = [3, 1];
// 이동 정의
const cx = [null, 0, 0, -1, 1];
const cy = [null, 1, -1, 0, 0];
// 각 명령에 맞게 이동
let res = "";
for (let i = 0; i < k; i++) {
const command = commands[i];
const [nx, ny] = [x + cx[command], y + cy[command]];
// 지도에서 이동을 통한 좌표 변경
if (!isPossibleRoute(n, m, nx, ny)) continue;
[x, y] = [nx, ny];
// 주사위 이동
moveDice(dice, command);
if (arr[x][y] === 0) {
// 주사위와 맞닿은 지도의 수가 0 이면, 주사위의 바닥면의 수가 지도로 복사
arr[x][y] = dice[diceBot[0]][diceBot[1]];
} else {
// 주사위와 맞닿은 지도의 수가 0 이 아니면, 지도의 수가 바닥면으로 복사 후 지도의 수는 0
dice[diceBot[0]][diceBot[1]] = arr[x][y];
arr[x][y] = 0;
}
// 이때의 top 값을 res 에 추가
res += dice[diceTop[0]][diceTop[1]] + "\n";
}
return res;
};
console.log(solution(input));