
const fs = require('fs');
const path = process.platform === 'linux' ? '/dev/stdin' : 'input.txt';
const inputs = fs
.readFileSync(path)
.toString()
.trim()
.split('\n')
.map((it) => it.split(' ').map(Number));
const [n, m, t] = inputs[0];
const map = inputs.slice(1, n + 1);
for (const [x, d, k] of inputs.splice(n + 1)) {
// 원판 돌리기
for (let i = x; i <= n; i += x) {
for (let _ = 0; _ < k; _++) {
if (d === 0) map[i - 1].unshift(map[i - 1].pop());
else map[i - 1].push(map[i - 1].shift());
}
}
// 인접한 수 확인
const deleteXY = [];
let sum = 0;
let cnt = 0;
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (map[i][j] === 'x') continue;
if (i !== n - 1 && map[i][j] === map[i + 1][j]) deleteXY.push([i, j], [i + 1, j]);
if (j !== m - 1 && map[i][j] === map[i][j + 1]) deleteXY.push([i, j], [i, j + 1]);
if (j === m - 1 && map[i][j] === map[i][0]) deleteXY.push([i, j], [i, 0]);
sum += map[i][j];
cnt += 1;
}
}
// 지울 수 있으면 지우고, 아니면 평균을 구함
const avg = sum / cnt;
if (deleteXY.length === 0) {
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (map[i][j] > avg) map[i][j] -= 1;
else if (map[i][j] < avg) map[i][j] += 1;
}
}
} //
else {
for (const [dX, dY] of deleteXY) {
map[dX][dY] = 'x';
}
}
}
let ans = 0;
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (map[i][j] === 'x') continue;
ans += map[i][j];
}
}
console.log(ans);
⏰ 소요한 시간 : -
시뮬레이션 유형의 문제다.
원판에 있는 수를 2차원 배열로 관리하면서 요구사항대로 구현해주면 된다.
원판 돌리기
먼저 x의 배수의 원판을 d방향으로로 k칸 회전해준다. (0일때 시계, 1일때 반시계)
회전 방식은 push, unshift, pop, shift를 적절히 활용했다.
인접한 수 확인
모든 좌표를 순회하면서 인접하면서 수가 같은 것을 모두 찾아야 한다.
인접하면서 수가 같은 것은 추후 지울 예정으므로 deleteXY라는 배열에 넣어줬다.
현재 위치에서 x방향(좌우)이든, y방향(상하)이든 내 다음좌표랑 값이 같으면 deleteXY에 추가한다. 이 때 시작값과 겹치는 좌표나, 다음좌표가 없는 경계값을 잘 체크해준다.
그리고 인접하면서 같은 수가 없으면 평균을 구해야하므로 원판의 모든 수를 순회할 때 누적 합 sum과 개수 cnt도 체크해준다.
지울 수 있으면 지우고, 아니면 평균과 비교하여 +-1
deleteXY배열의 길이가 0이면 지울 수 있는 수가 없다는 뜻이므로 원판에 적힌 모든 수를 순회하며 평균보다 큰 수에는 1을 빼고, 평균보다 작은 수에는 1을 더해준다.
deleteXY배열의 길이가 0보다 크면 지울 수 있는 수가 있으므로 해당 좌표들을 순회하며 값을 x로 바꿔줬다.
위의 과정을 T번 반복한 뒤, 모든 원판을 순회하며 합계를 구해주면 끝