[백준] 2578 빙고 JavaScript

·2024년 6월 4일

문제

빙고 게임은 다음과 같은 방식으로 이루어진다.

먼저 아래와 같이 25개의 칸으로 이루어진 빙고판에 1부터 25까지 자연수를 한 칸에 하나씩 쓴다

다음은 사회자가 부르는 수를 차례로 지워나간다. 예를 들어 5, 10, 7이 불렸다면 이 세 수를 지운 뒤 빙고판의 모습은 다음과 같다.

차례로 수를 지워가다가 같은 가로줄, 세로줄 또는 대각선 위에 있는 5개의 모든 수가 지워지는 경우 그 줄에 선을 긋는다.

이러한 선이 세 개 이상 그어지는 순간 "빙고"라고 외치는데, 가장 먼저 외치는 사람이 게임의 승자가 된다.

철수는 친구들과 빙고 게임을 하고 있다. 철수가 빙고판에 쓴 수들과 사회자가 부르는 수의 순서가 주어질 때, 사회자가 몇 번째 수를 부른 후 철수가 "빙고"를 외치게 되는지를 출력하는 프로그램을 작성하시오.

입력

첫째 줄부터 다섯째 줄까지 빙고판에 쓰여진 수가 가장 위 가로줄부터 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 여섯째 줄부터 열째 줄까지 사회자가 부르는 수가 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 빙고판에 쓰여진 수와 사회자가 부르는 수는 각각 1부터 25까지의 수가 한 번씩 사용된다.

출력

첫째 줄에 사회자가 몇 번째 수를 부른 후 철수가 "빙고"를 외치게 되는지 출력한다.

예제 입력

11 12 2 24 10
16 1 13 3 25
6 20 5 21 17
19 4 8 14 9
22 15 7 23 18
5 10 7 16 2
4 22 8 17 13
3 18 1 6 25
12 19 23 14 21
11 24 9 20 15

예제 출력

15

내가 했던 풀이 방법

  1. 5×5 bingo 배열에 5번째 줄까지 입력받은 내용을 저장해준다. 5번째 줄 이후 끝까지 입력받은 내용을 1차원 배열(number)로 저장해준다.
  2. number 배열을 처음부터 순서대로 반복하면서, 매 숫자마다 bingo 배열에 현재 부른 숫자의 위치를 찾아낸다. 위치는 0부터 5까지 line을 반복하면서, 해당 배열 중 현재 부른 수가 포함된 경우(indexOf가 -1이 아닌 경우) 해당 위치를 x로, 해당 line을 y로 저장해준다. 찾아낸 위치를 bingo에서 null로 바꿔준다.
  3. 가로, 세로, 대각선 방향으로 검사를 해준다. 가로 방향은 x가 바뀌고 y가 고정되었을 때 모든 값이 null인지를 확인해주면 되고, 세로 방향은 y가 바뀌고 x가 고정되었을 때 모든 값이 null인지를 확인해주면 된다. 대각선은 두 가지 방향이 있는데, 위치의 좌표를 비교하여 조건에 포함된 경우를 검사해주면 된다. 오른쪽에서 왼쪽으로 향하는 대각선은 y가 줄어들수록 x가 커지는 것을 이용하고, 그 반대의 대각선은 x가 줄어들수록 y가 커지는 것을 이용해 해당 요소가 모두 null인지를 검사해주면 된다. 해당 경우에 count를 1씩 증가시켜주면 된다.
  4. 모든 방향을 검사해준 뒤 count가 3 이상일 경우 연산을 중단하고 number의 현재 index+1을 출력해준다. (index는 0부터 시작하기 때문)

코드

const fs = require('fs');
let input = fs.readFileSync(0, 'utf-8').toString().trim().split('\n');

let bingo = Array.from({ length: 5 }, () => Array(5));
for (let i = 0; i < 5; i++) {
  input[i] = input[i].trim().split(' ').map(Number);
  bingo[i] = input[i];
}

let number = [];
for (let i = 5; i < input.length; i++) {
  input[i] = input[i].trim().split(' ').map(Number);
  number.push(...input[i]);
}

function vertical(index) {
  for (let i = 0; i < 5; i++) {
    if (bingo[i][index] !== null) return false;
  }
  return true;
}

function horizontal(index) {
  for (let i = 0; i < 5; i++) {
    if (bingo[index][i] !== null) return false;
  }
  return true;
}

function diagonal1() {
  let y = 0;
  let x = 4;
  for (let i = 0; i < 5; i++) {
    if (bingo[y][x] !== null) return false;
    y++;
    x--;
  }
  return true;
}

function diagonal2() {
  let y = 4;
  let x = 0;
  for (let i = 0; i < 5; i++) {
    if (bingo[y][x] !== null) return false;
    y--;
    x++;
  }
  return true;
}

let x = 0;
let y = 0;
let count = 0;
for (let i = 0; i < number.length; i++) {
  for (let j = 0; j < 5; j++) {
    let contain = bingo[j].indexOf(number[i]);
    if (contain !== -1) {
      x = contain;
      y = j;
      break;
    }
  }
  bingo[y][x] = null;

  if (
    (y === 0 && x === 4) ||
    (y === 1 && x === 3) ||
    (y === 2 && x === 2) ||
    (y === 3 && x === 2) ||
    (y === 4 && x === 1)
  ) {
    if (diagonal1()) count++;
  }
  if (
    (y === 4 && x === 0) ||
    (y === 3 && x === 1) ||
    (y === 2 && x === 2) ||
    (y === 2 && x === 3) ||
    (y === 1 && x === 4)
  ) {
    if (diagonal2()) count++;
  }
  if (vertical(x)) count++;
  if (horizontal(y)) count++;
  if (count >= 3) {
    console.log(i + 1);
    break;
  }
}

회고

문제가 어렵진 않은데 구현하기 귀찮은 문제. 대각선 방향을 찾는 걸 어떻게 해야하나 고민했는데, 대충 대각선 위치에 있는지는 파악할 수 있지만, 방향을 판단하기에 어려움이 있어서 배열의 크기가 크지도 않기 때문에 단순하게 좌표를 비교해주는 것으로 풀이했다.

profile
Frontend🍓

0개의 댓글