필요한 개념
- 시뮬레이션
- list 메소드
문제 분석
문제를 풀기 위해서는 2차원 배열에서의 탐색이 필요하다.
이후에는 주어지는 폭탄 데이터를 입력 받아 문제의 요구 사항대로 구현하면 된다.
모든 폭탄이 떨어진 이후에, 배열에서 가장 큰 값을 찾아야 한다.
반복문으로 찾을 수 있지만, 배열의 단계를 낮춰주는 메소드를 사용해서 해결할 수 있다.
- 폭탄이 떨어지면, 떨어진 위치를 기준으로 십자가 영역의 폭탄 값이 조건에 따라서 증가
- # 는 폭탄 값의 영향을 받지 않음
- 0 이면 폭탄 값이 1만큼 증가
- @ 라면 폭탄 값이 2만큼 증가
- 모든 폭탄이 떨어진 이후에 폭탄 앖이 가장 높은 값을 출력
데이터의 입력
// 입력
4 4
0 0 @ 0
0 0 0 0
0 # 0 0
0 0 0 @
2 2
2 3
1 4
1 4
이 문제는 위의 데이터를 입력 받아야 하기 때문에 복잡하다.
입력을 받으면서 바로 변수를 갱신해줘야 한다.
기존에 선언된 N, K를 입력과 동시에 할당해주고, 입력의 길이가 N + M + 1만큼 되면 rl.close() 를 호출한다.
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
let input = [];
let N, K;
rl.on('line', (line) => {
if (input.length === 0){
input.push(line);
[N, K] = input[0].split(' ').map(Number)
}else{
input.push(line.trim());
}
if (input.length === N + K + 1){
rl.close();
}
})
점수 행렬 만들기
특정 값으로 채워져 있는 행렬을 선언하는 이유는 현재 땅의 상태를 수정할 수 없기 때문에 점수만 기록할 행렬을 따로 선언해준다.
이 행렬의 모든 초기 값은 0이므로, 한 변의 길이가 N이고 0으로 채워져 있는 배열을 만든다.
- Array.from
let score = Array.from({ length: N }, () => Array(N).fill(0));
- 반복문 사용
let score = new Array(N);
for(let i = 0; i < N; i++) {
score[i] = new Array(N).fill(0);
}
탐색 구현하기
우선 폭탄을 한 번 떨어트리는 코드가 필요하다.
하나의 폭탄이 떨어지면 상하좌우에 폭탄의 영향을 끼치고, 영향을 받은 위치의 값에 따라서 영향을 끼치는 정도가 달라진다.
그리고 폭탄의 영향은 떨어진 위치도 받기 때문에, dx/dy 기법에서는 원래 위치와 더불어 상하좌우를 탐색할 수 있도록 코드를 작성한다.
// 원래 위치와 상하좌우
let dx = [0, 0, 0, 1, -1];
let dy = [0, 1, -1, 0, 0];
구현과 탐색을 할 때 중요한 점은 탐색을 해도 되는 부분인지 확인해야 한다.
이 문제에서 행렬의 범위를 넘어가는 경우와, 행렬의 값이 # 이라면 탐색하지 않아도 문제가 없다.
그래서 현재의 (x, y)에서 탐색을 진행했을 때, 범위를 나가거나 matrix[nx][ny] 의 값이 # 이라면 탐색을 하지 않도록 한다.
rl.on('close', () => {
// matrix, score 행렬 선언 부분
..code
// 탐색 및 구현 부분
for (let i = N+1; i <= N+K ; i++){
// 떨어지는 폭탄의 위치를 [x, y]에 할당
let [x, y] = input[i].trim().split(' ').map(Number);
// 인덱스 조정
x -= 1;
y -= 1;
// dx/dy가 5곳을 탐색하기 때문에 반복문의 길이도 5
for ( let j = 0 ; j < 5 ; j++){
let nx = x + dx[j];
let ny = y + dy[j];
// 행렬의 범위를 나가거나, 탐색할 행렬의 값이 #이라면 탐색하지 않음
if (nx >= 0 && nx < N && ny >= 0 && ny < N && matrix[nx][ny] !== '#') {
// 폭탄 값의 영향을 받는 경우의 구현
}
}
process.exit();
}
폭탄 구현하기
마지막으로 구현할 부분은 아래와 같다.
- 땅의 상태가 0 이라면 폭탄 값은 1 증가한다.
- 땅의 상태가 @ 이라면 폭탄 값은 2 증가한다.
땅의 상태는 matrix 에서 조회하고, 폭탄 값은 score 에서 조회하면 된다.
- matirx[nx][ny] 의 값이 @ 일 때, score[nx][ny] 의 값을 2 추가합니다.
- matirx[nx][ny] 의 값이 0일 때, score[nx][ny] 의 값을 1 추가합니다.
rl.on('close', () => {
..code
for (let i = N+1; i <= N+K ; i++){
let [x, y] = input[i].trim().split(' ').map(Number);
x -= 1;
y -= 1;
for ( let j = 0 ; j < 5 ; j++){
let nx = x + dx[j];
let ny = y + dy[j];
if (nx >= 0 && nx < N && ny >= 0 && ny < N && matrix[nx][ny] !== '#') {
//matrix[nx][ny]의 값이 @ 일때, score[nx][ny] 값을 +2 을 한다.
if (matrix[nx][ny] === '@') {
score[nx][ny] += 2;
}
// matrix[nx][ny]값이 @가 아니라면, score[nx][ny] 값을 +1 을 한다.
} else {
score[nx][ny] += 1;
}
}
}
}
console.log(score);
process.exit();
})
행렬을 배열로
score 행렬에 모든 폭탄 값들이 저장되어 있는데, 최대 폭탄 값을 찾는 방법은 두 가지 이다.
- 배열을 순회하면서 찾기
let max = -1; // 초기 최대값을 가장 작은 수로 설정
for (let i = 0; i < score.length; i++) {
for (let j = 0; j < score[i].length; j++) {
if (score[i][j] > max) {
max = score[i][j];
}
}
}
const result = max
- list.flat() 사용
list.flat() 은 행렬을 배열로 바꿔준다.
배열의 요소로 또 다른 배열이 있다면, 그 배열을 한 단계 낮춰준다.
그리고 나서 Math.max() 를 사용하면 배열의 요소 중 최대 값을 간단하게 찾을 수 있다.
let arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
let arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
const result = Math.max(...score.flat())
dx/dy 문제를 한 번 풀어봤는데도 막상 구현하려고 하니 아직은 쉽지 않았다.
그리고 이번엔, 조건에 맞게 점수를 바꿔줘야 해서 더 어렵게 느껴졌다.
어떤 것을 구현해야 할지 정리하고 하나씩 해나가는 과정을 정리하고 나니 어렵지 않은데, 아직은 문제를 분석하는 연습이 부족하다고 느껴진다.
구름톤 챌린지를 하면서 문제를 풀어보고 해설을 자세히 확인할 수 있어 복습하고 정리하면서 도움이 되는 것 같다.
'JavaScript' 카테고리의 다른 글
[구름톤 챌린지] 3주차_작은 노드 (0) | 2023.09.01 |
---|---|
[구름톤 챌린지] 3주차_발전기 (0) | 2023.08.30 |
[구름톤 챌린지] 2주차_문자열 나누기 (0) | 2023.08.22 |
[구름톤 챌린지] 1주차_완벽한 햄버거 만들기 (0) | 2023.08.18 |
[구름톤 챌린지] 1주차_프로젝트 매니징 (0) | 2023.08.17 |