카테고리 없음

알고리즘 테스트[지뢰찾기] feat. continue

stella0905 2023. 4. 13. 23:54

😃 설명) windows에서 지원하는 지뢰 찾기 게임을 한번쯤은 해 보았을 것이다. 특히 르탄이는 지뢰찾기의 매니아로 알려져 있다. 지뢰 찾기 map은 N*N의 정사각형 모양으로 각 칸에는 숫자가 들어가 있거나 지뢰가 들어가 있다. 빈 칸에는 숫자 0이 들어있다고 생각하자.

map의 어떤 칸에 적혀 있는 숫자는, 그 칸과 인접해 있는 여덟 개의 칸 중에서 지뢰가 들어 있는 칸이 몇 개인지를 나타내 준다. 물론 인접한 칸이 map 내부에 있는 경우에 대해서만 생각하면 된다. 예제를 보면 더 잘 이해할 수 있을 것이다.

이번 문제는 조금 업그레이드 된 지뢰 찾기로, 한 칸에 한 개의 지뢰가 있는 것이 아니고, 한 칸에 여러 개(1 이상 9 이하)의 지뢰가 묻혀 있는 게임이다. 따라서 map의 어떤 칸에 적혀 있는 숫자는, 그 칸과 인접해 있는 여덟 개의 칸들에 들어 있는 지뢰의 총 개수가 된다.

이미 windows 지뢰찾기 같은 것을 마스터한 르탄이는, map에서 지뢰에 대한 정보만이 주어졌을 때, 르탄이는 map을 완성하고 싶다고 한다. N과 지뢰의 위치가 주어졌을 때, 르탄이를 도와서 지뢰 찾기 map을 완성하는 프로그램을 작성하시오.

(단, 1 ≤ N ≤ 1,000 이며, 배열의 각 요소에는 지뢰 찾기 map에 대한 정보가 주어지는데 '.' 또는 숫자로 이루어진 문자열이 들어온다. '.'는 지뢰가 없는 것이고 숫자는 지뢰가 있는 경우로 그 칸의 지뢰의 개수이다. 한 줄은 N개의 문자로 이루어져 있다.)


입출력 예 

let N = 5;
let arr1 = [
  ["1", ".", ".", ".", "."],
  [".", ".", "3", ".", "."],
  [".", ".", ".", ".", "."],
  [".", "4", ".", ".", "."],
  [".", ".", ".", "9", "."],
];
console.log(solution(N, arr1));

N = 4;
arr1 = [
  ["2", ".", ".", "."],
  [".", ".", "9", "."],
  [".", "3", ".", "2"],
  [".", "4", ".", "."],
];

console.log(solution(N, arr1));

출력

N개의 줄에 걸쳐서 완성된 지뢰 찾기 map을 출력한다. 지뢰는 ''로 출력하며. 10 이상인 경우는 'M'(Many)으로 출력하면 된다. map은 숫자 또는 'M' 또는 ''로만 이루어져 있어야 한다.

int N = 4; 
char[][] chars= 
{{'2', '.', '.', '.',},        
 {'.', '.', '9', '.'},        
 {'.', '3', '.', '2'},        
 {'.', '4', '.', '.'}};
 
 //결과값
 
 
[[*, M, 9, 9], [5, M, *, M], [7, *, M, *], [7, *, 9, 2]]
int N = 5
char[][] chars = 
{{'1', '.', '.', '.', '.'},        
 {'.', '.', '3', '.', '.'},        
 {'.', '.', '.', '.', '.'},        
 {'.', '4', '.', '.', '.'},        
 {'.', '.', '.', '9', '.'}};
 
 //결과값
 
 
[[*, 4, 3, 3, 0], [1, 4, *, 3, 0], [4, 7, 7, 3, 0], [4, *, M, 9, 9], [4, 4, M, *, 9]]

진짜 이문제는 이해하는데만 30분이 넘게 걸렸다..

결국 그렸더니 이해가 갔다.. 

이제 어떤식으로 해야 답이나오는지 이해는 됬으나 이제는 이걸로 코드를 짜는걸 어떻게 해야할지 전혀 감이 오지 않았다. 

그것도 이해하는데 오래걸렸다..

function solution(N, arr1) {
  const location = [[1, 0], [-1, 0], [0, 1], [0, -1], [1, 1], [1, -1], [-1, 1], [-1, -1]]
  for (let i = 0; i < N; i++) {
    for (let j = 0; j < N; j++) {
      if (arr1[i][j] === '.') {
        arr1[i][j] = 0;
        //arr1의 i번째인덱스 배열안에 배열중 j번째 인덱스값이 .이라면 0으로 바꿔준다.
      } else {
        arr1[i][j] = parseInt(arr1[i][j]);
        //.이 아니라면 숫자열로 바꿔준다.
      }
    }
  }
  const result = []



  for (let i = 0; i < arr1.length; i++) {
    let row = []
    for (let j = 0; j < arr1[0].length; j++) {
      let sum = 0
      for (let k = 0; k < location.length; k++) {
        const x = i + location[k][0];
        const y = j + location[k][1];
        if (x >= 0 && x < arr1.length && y >= 0 && y < arr1[0].length) {
          sum += arr1[x][y];
        }
      }
      row.push(sum)
    }
    result.push(row)
  }
  return result
}


console.log(solution(5,
  [['1', '.', '.', '.', '.'],
  ['.', '.', '3', '.', '.'],
  ['.', '.', '.', '.', '.'],
  ['.', '4', '.', '.', '.'],
  ['.', '.', '.', '9', '.']]))
  
  
// [
// [ 0, 4, 3, 3, 0 ],
// [ 1, 4, 0, 3, 0 ],
// [ 4, 7, 7, 3, 0 ],
// [ 4, 0, 13, 9, 9 ],
// [ 4, 4, 13, 0, 9 ]
// ]

처음에 완성하지 못했던 코드인데  arr1에 하나하나요소가 location에 위치의 숫자를 더하는걸 풀어야하는데 그게 너무 어려웠다. 

그래서 계속 구글링도 해보고 해서 x축, y축을 구한 후 위코드의 결과값까지는 갔는데 최종 결과값처럼 코드를 다시 만지려고 하니 시험시간은 2시까지인데 시간은 1시 55분이여서.. 이문제는 혼자 다시 풀어보자 하고 1,2번 문제만 제출하고 나왔다.

 

그리고 다시 풀어본 코드는 이렇다.

function solution(N, arr1) {
  const location = [[1, 0], [-1, 0], [0, 1], [0, -1], [1, 1], [1, -1], [-1, 1], [-1, -1]]
  for (let i = 0; i < N; i++) {
    for (let j = 0; j < N; j++) {
      if (arr1[i][j] === '.') {
        arr1[i][j] = 0;
        //arr1의 i번째인덱스 배열안에 배열중 j번째 인덱스값이 .이라면 0으로 바꿔준다.
      } else {
        arr1[i][j] = parseInt(arr1[i][j]);
        //.이 아니라면 숫자열로 바꿔준다.
      }
    }
  }
  const result = []

  for (let i = 0; i < arr1.length; i++) {
    let row = []
    for (let j = 0; j < arr1[i].length; j++) {
      if (arr1[i][j] !== '.' && arr1[i][j] !== 0) {
        row.push('*');
        continue;
      }

      let sum = 0
      for (let k = 0; k < location.length; k++) {
        const x = i + location[k][0];
        const y = j + location[k][1];

        if (x >= 0 && x < arr1.length && y >= 0 && y < arr1[0].length) {
          sum += arr1[x][y];
        }
      }

      if (sum >= 10) {
        row.push('M');
      } else {
        row.push(sum)
      }
    }
    result.push(row)
  }
  return result
}


console.log(solution(5,
  [['1', '.', '.', '.', '.'],
  ['.', '.', '3', '.', '.'],
  ['.', '.', '.', '.', '.'],
  ['.', '4', '.', '.', '.'],
  ['.', '.', '.', '9', '.']]))

이렇게 해서 원하던 결과값은 얻을 수 있다.

[
  [ '*', 4, 3, 3, 0 ],
  [ 1, 4, '*', 3, 0 ],
  [ 4, 7, 7, 3, 0 ],
  [ 4, '*', 'M', 9, 9 ],
  [ 4, 4, 'M', '*', 9 ]
]

 

여기서 내가 하나 알아갔던건 

continue이다. 

 

먼저 break를 간략하게 설명하자면 

반복문에서 조건문이 true일때 break가 실행이되면 아예 반복문이 끝나버린다. 말 그대로 for문이 0부터 5까지 돌아야하는데 2에서 조건문이 true가 되어서 break가 발생되면 더이상 반복문을 돌지 않는다.

 

이개념과 비슷하게 continue는 많은 사람들이 알다시피 반복할때 해당위치는 건너뛰고 계속 반복되는건데 

조건문이 true일때 continue를 사용하면 해당 반복시점에서 추가로 코드가 있더라도 실행하지 않고 다음 반복으로 넘어간다.

이것도 말 그대로 

for (let i = 0; i < arr1.length; i++) {
    let row = []
    for (let j = 0; j < arr1[i].length; j++) {
      if (arr1[i][j] !== '.' && arr1[i][j] !== 0) {
        row.push('*');
        continue;
      }

      let sum = 0
      for (let k = 0; k < location.length; k++) {
        const x = i + location[k][0];
        const y = j + location[k][1];

        if (x >= 0 && x < arr1.length && y >= 0 && y < arr1[0].length) {
          sum += arr1[x][y];
        }
      }

이런식으로 코드가있는데 3중for문에서 j단계 j = 2일때 에서 조건문이 true가 되면 아래에있는 k for문은 실행되지 않고 j =3반복문으로 들어가게된다.

 

이렇게 되면 로직적으로 필요없는 반복은 하지않게 되어 훨씬 좋은 코드가 되는걸 알게되었다.