백준/ Gold 2 문제 , 백준 Node.js 자바스크립트 17822 원판 돌리기 [ 구현, 시뮬레이션 ]
✔️Check Point ! ( 해당사항 ✓체크 )
1. 막힘 없이 수월하게 풀린 문제인가?
2. 1시간이내로 풀렸던 문제인가?
3. 1시간 이상 or 며칠을 두고 풀어봤더니 풀린 문제인가?
4. 시간을 써도 도무지 풀 수 없는 문제인가?
5. 솔루션을 찾아봤는가?
-------------------------------------------------------------------------------------------
난이도 체감 🧑💻
1. 최상
2. 상
3. 중
4. 하
이해도 🙆♂️
1. 완벽히 이해
2. 다소 헷갈리는 부분들이 있음
3. 이해 못함
문제 출처 🏠
https://www.acmicpc.net/problem/17822
문제풀이 소감 🧑💻
되게 오랜만에 푼 문제이다! 그래서 감이 많이 떨어져있을까 싶었는데, 그래도 그 동안 400일 넘게 푼 노력이 헛되지는 않았는지
생각보다 쉽게 풀었던 문제였다.
문제를 처음에 접하면 '헉!' 할 수 도 있다. 되게 어려워보이는 그림과 함께 긴 설명이 있는데 겁먹지말자. 단순 구현문제이다.
문제에서 요구하는 부분만 잘 파악하면 어려운 부분은 없다.
다만, 삭제를 하는 부분에서 조금 조심해줘야할 부분이 있다.
아마 이 부분의 해결과정이 이 문제의 핵심이지 않을까 싶은데, 해결 전략에서 더 자세히 설명해 보겠다.
해결 전략 📝
이 문제에서 가장 주의해야할 부분은 인접한 숫자를 삭제하는 부분이다.
위에서 부터 1번 원판 ~ 4번원판이다.
위 숫자들은 회전을 한 이후이고 이제 삭제를 해줄 차례이다.
위 사진을 보고 어떤 숫자들을 삭제해야할지 잘 생각해보자.
문제의 조건에 따르면 기준이 되는 숫자에서 위아래양옆에 있는 숫자들을 지워주면된다.
대신 위아래와 양옆은 차이가 있다.
예를 들어 [0,0] 위치에 있는 2의 왼쪽은 [0,5] 위치에 있는 5이다.
- (i, 1)은 (i, 2), (i, M)과 인접하다.
라는 조건때문이다.
역으로 [0,5] 위치의 숫자 5의 오른쪽은 [0,0] 위치의 숫자 2이다.
하지만, 위아래의 인접한 숫자를 따질때는 이것이 적용되지 않는다.
[0,0] 위치의 숫자에서 위의 숫자는 [3,0] 인 7이 아니라는 것이다.
[0,0] 에서 위와 인접한 것은 없다.
따라서 위치를 이동시킬때 [-1,0] 같은 위치가 나온다면 이것은 계산하지 말고 넘어가야한다.
같은 이치로 [3,0] 위치의 7의숫자 아래의 숫자는 [0,0] 위치의 숫자 2가 아니고 없다는 것이다.
쉽게 설명하자면, 양옆의 인접한 숫자를 따질때만 0번인덱스와 M-1 번 인덱스가 바로 옆에 있다고 생각하고 접근해야한다.
따라서 위의 숫자들의 상태에서 인접해 삭제되어야할 숫자들은 위 사진의 빨간 표시로 되어있는 숫자들이다.
[1,0] 위치의 숫자 5는 [1,5] 위치의 숫자 5와 인접하기 때문에 삭제된다.
이 부분만 잘 해결한다면 다른 부분들은 단순 구현이다.
리팩터링 🔄️
1. 중복코드 제거
움직일 거리가 배열보다 길 경우 나머지를 구해서 위치를 조정해주는 부분이다.
rotateRight와 rotateLeft 내에서 동일한 코드가 똑같이 사용되고 있는데, 이 부분을 함수를 호출하는 부분으로 넣어주었다.
리팩터링 후이다.
나머지값을 자연스럽게 넣어주는 식으로 코드를 짜보았다.
rotateRight 과 rotateLeft를 rotate라는 함수로 합칠까도 생각해봤지만,
함수는 한 가지일만 한다 라는 특징을 살리기 위해 냅뒀다.
아무래도 이렇게 하는게 가독성이 더 낫지 않을까도 싶다.
for 문내에서도 삼항연산자를 일부러 사용하지 않았다. 가독성이 떨어져서 좋지 않았다.
정답 💯
const input = require('fs').readFileSync('/dev/stdin').toString().trim().split('\n');
const [inputN, inputM, inputT] = input.shift().split(' ').map(Number);
const inputNums = [];
const inputOrders = [];
for (let i = 0; i < inputN; i++) inputNums.push(input[i].split(' ').map(Number));
for (let j = inputN; j < inputN + inputT; j++) inputOrders.push(input[j].split(' ').map(Number));
const log = console.log;
function solution(N, M, T, nums, orders) {
const drX = [0, 1, 0, -1];
const drY = [1, 0, -1, 0];
const rotateRight = (nums, move) => {
const spliced = nums.splice(nums.length - move, nums.length);
return [...spliced, ...nums];
};
const rotateLeft = (nums, move) => {
const spliced = nums.splice(0, move);
return [...nums, ...spliced];
};
orders.forEach((order) => {
for (let i = order[0]; i <= N; i += order[0]) {
if (order[1] === 0) {
nums[i - 1] = rotateRight(nums[i - 1], order[2] % nums[i - 1].length);
} else {
nums[i - 1] = rotateLeft(nums[i - 1], order[2] % nums[i - 1].length);
}
}
const copy = JSON.parse(JSON.stringify(nums)); // DeepCopy
let del = false;
let [sum, cnt] = [0, 0];
for (let i = 0; i < N; i++) {
for (let j = 0; j < M; j++) {
if (!nums[i][j]) continue;
let check = false;
for (let k = 0; k < 4; k++) {
let [mx, my] = [i + drX[k], j + drY[k]];
if (mx === -1 || mx === N) continue;
else if (my === -1) my = M - 1;
else if (my === M) my = 0;
if (nums[i][j] === nums[mx][my]) {
check = true;
del = true;
copy[mx][my] = 0;
}
}
if (check) copy[i][j] = 0;
else {
cnt += 1;
sum += nums[i][j];
}
}
}
nums = copy;
// 인접한 것 없을 때 => 삭제
if (!del) {
const center = sum / cnt;
for (let i = 0; i < N; i++) {
for (let j = 0; j < M; j++) {
if (!nums[i][j]) continue;
if (nums[i][j] > center) nums[i][j] -= 1;
else if (nums[i][j] < center) nums[i][j] += 1;
}
}
}
});
let result = 0;
nums.forEach((v) => {
result += v.reduce((pre, cur) => pre + cur, 0);
});
return result;
}
log(solution(inputN, inputM, inputT, inputNums, inputOrders));