본문 바로가기
[Python] Baekjoon/Brute force(브루트포스)

[백준(Baekjoon)] 2578 빙고

by 파크영 2021. 10. 4.

문제

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

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

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


 

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

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

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

 

입력

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

 

출력

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

 

예제 입력 1 

11 12 2 24 10

16 1 13 3 25

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

 

예제 출력 1 

15

 


나의 풀이

[Python(파이썬)]

import sys
def find(bingo, findnum):   # idx find def
    for idx1 in range(5):
        if findnum in bingo[idx1]:
            idx2 = (bingo[idx1].index(findnum))
            return idx1, idx2

def linecheck(check): # Bingo check def
    cnt = 0
    for i in check:
        cnt += i.count(5)
        if cnt >= 3: return True
    return False

# main
check, call = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0]], []  # 0:가, 1:세, 2:대
bingo = [[*map(int, input().split())] for _ in range(5)]
for _ in range(5):
    call += list(map(int, sys.stdin.readline().split()))

for i in range(len(call)):
    idx1, idx2 = find(bingo, call[i])
    check[0][idx1] += 1
    check[1][idx2] += 1
    if idx1 + idx2 == 4: 
        check[2][0] += 1
    if idx1 == idx2:
        check[2][1] += 1

    if i >= 11 and linecheck(check):
        print(i+1)
        break

 

 


풀이 과정

1. 1줄 빙고 체크
2. 인덱스 찾는 함수
3. 3줄 빙고 체크 함수

 

1. 1줄 빙고 체크

 

check = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0]]  # 0:가, 1:세, 2:대


for i in range(len(call)):
    idx1, idx2 = find(bingo, call[i])
    check[0][idx1] += 1	# 가로줄
    check[1][idx2] += 1	# 세로줄
    if idx1 + idx2 == 4: # 오른쪽 위로 가는 대각선
        check[2][0] += 1 
    if idx1 == idx2:	# 왼쪽 위로 가는 대각선
        check[2][1] += 1

 

한 줄 빙고가 되는 것을 체크하기 위해 이차원 리스트 check를 만들어준다. 

check에 표시된 숫자는 해당 줄에서 지워진 숫자의 개수를 의미한다. 

 

처음으로 10이 지워진다고 생각해보자. 

그럼 가로로 보면 1번째 줄,  세로로 보면 5번째 줄이다.  또한 오른쪽 위로 가는 대각선에서도 지워지므로

[[1, 0, 0, 0, 0], [0, 0, 0, 0, 1], [1, 0]]인 것

-> 가로 1번째 줄에서 1개, 세로 5번째 줄에서 1개, 오른쪽 위로 가는 대각선에서 1개 지워졌다는 의미

 

한 개의 예를 더 생각해 21이 지워진다고 생각해보자.

가로에서 3번째 줄, 세로에서 4번째 줄이며, 양쪽 대각선에는 모두 포함되지 않는다. 

[[0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0]]이다. 

-> 가로 1번째 줄에서 1개, 세로 5번째 줄에서 1개, 오른쪽 위로 가는 대각선에서 1개 지워졌다는 의미

 

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

그 의미는 check 리스트에서 숫자 5가 되면 해당 줄에서 5개의 모든 수가 지워진 경우니까 한 줄 빙고가 되는 것이다. 

리스트 check에서 5의 개수 = 빙고가 된 줄의 개수

 

자세한 check의 설명은 아래 그림과 함께 보면 좀 더 이해하기가 쉬울 것이다. 

 


2. 인덱스 찾는 함수

 

이차원 리스트인 빙고판에서 사회자가 부르는 숫자의 인덱스를 찾아야 한다. 

 

  • main 호출 부분
idx1, idx2 = find(bingo, call[i])

매개변수 : 빙고판 리스트,  현재 부른 숫자

리턴 값 : idx1(해당 숫자 가로줄 인덱스), idx2(해당 숫자 세로줄 인덱스)

 

  • 인덱스 찾는 함수
def find(bingo, findnum):   # idx find def
    for idx1 in range(5):
        if findnum in bingo[idx1]:
            idx2 = (bingo[idx1].index(findnum))
            return idx1, idx2

 

 


3. 3줄 빙고 체크 함수

 

  • main 호출 부분
if i >= 11 and linecheck(check):
        print(i+1)

매개변수 : check 리스트

리턴 값 : 빙고 여부(T or F)

 

※ i >= 11 인 이유

최소 12개를 불러야 세줄 빙고가 될 수 있기 때문에 11개까지는 linecheck를 호출할 필요가 없다. 

 

 

  • 빙고가 총 3줄이 되었는지 확인해주는 함수

리스트 check를 확인하며 5가 3개 이상(3줄 빙고)이면 True 리턴, 3개 미만이면 False 리턴

def linecheck(check): # Bingo check def
    cnt = 0
    for i in check:
        cnt += i.count(5)
        if cnt >= 3: return True
    return False

 

 

ex) 

1) check[0] = [2, 3, 2, 2, 2]를 가져와 5의 개수를 확인해 cnt에 더해준다. 

2) check[1] = [2, 2, 5, 1, 2] => 5의 개수 -> 1개 cnt += 1

3). check[2] = [5, 1]  => 5의 개수 -> 1개 cnt += 1

4) cnt = 2이므로 False 리턴

 

 

ex) 

1) check[0] = [2, 5, 3, 2, 3] => 5의 개수 -> 1개 cnt += 1

2) check[1] = [3, 2, 5, 1, 4] => 5의 개수 -> 1개 cnt += 1

3). check[2] = [5, 1]  => 5의 개수 -> 1개 cnt += 1

4) cnt = 3이므로 True 리턴

 

 

 

 


문제 출처

 

2578번: 빙고

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

www.acmicpc.net

 

댓글