라떼는말이야

[solved.ac 실버2] 2615_오목 (파이썬, 구현, 브루트포스) 본문

알고리즘/코딩 테스트

[solved.ac 실버2] 2615_오목 (파이썬, 구현, 브루트포스)

MangBaam 2022. 6. 25. 17:09
반응형

밑의 사진을 클릭하면 문제 링크로 이동합니다

제한 사항

문제

오목은 바둑판에 검은 바둑알과 흰 바둑알을 교대로 놓아서 겨루는 게임이다. 바둑판에는 19개의 가로줄과 19개의 세로줄이 그려져 있는데 가로줄은 위에서부터 아래로 1번, 2번, ... ,19번의 번호가 붙고 세로줄은 왼쪽에서부터 오른쪽으로 1번, 2번, ... 19번의 번호가 붙는다.

위의 그림에서와 같이 같은 색의 바둑알이 연속적으로 다섯 알을 놓이면 그 색이 이기게 된다. 여기서 연속적이란 가로, 세로 또는 대각선 방향 모두를 뜻한다. 즉, 위의 그림은 검은색이 이긴 경우이다. 하지만 여섯 알 이상이 연속적으로 놓인 경우에는 이긴 것이 아니다.

입력으로 바둑판의 어떤 상태가 주어졌을 때, 검은색이 이겼는지, 흰색이 이겼는지 또는 아직 승부가 결정되지 않았는지를 판단하는 프로그램을 작성하시오. 단, 검은색과 흰색이 동시에 이기거나 검은색 또는 흰색이 두 군데 이상에서 동시에 이기는 경우는 입력으로 들어오지 않는다.

입력

19줄에 각 줄마다 19개의 숫자로 표현되는데, 검은 바둑알은 1, 흰 바둑알은 2, 알이 놓이지 않는 자리는 0으로 표시되며, 숫자는 한 칸씩 띄어서 표시된다.

출력

첫줄에 검은색이 이겼을 경우에는 1을, 흰색이 이겼을 경우에는 2를, 아직 승부가 결정되지 않았을 경우에는 0을 출력한다. 검은색 또는 흰색이 이겼을 경우에는 둘째 줄에 연속된 다섯 개의 바둑알 중에서 가장 왼쪽에 있는 바둑알(연속된 다섯 개의 바둑알이 세로로 놓인 경우, 그 중 가장 위에 있는 것)의 가로줄 번호와, 세로줄 번호를 순서대로 출력한다.

예제


나의 풀이

오목 확인 뿐만 아니라 육목까지 확인해야 해서 좀 더 고민이 필요했다.

오목이 나올 수 있는 상황은 4가지가 있다.

  1. 가로 ( - )
  2. 세로( | )
  3. 오른쪽 아래 대각선 ( \ )
  4. 오른쪽 위 대각선( / )

이 이외의 방향은 모두 위 4개의 방향과 겹친다. (예를 들어 왼쪽 아래 대각선은 오른쪽 위 대각선과 동일)

 

오목인 경우 가장 위, 왼쪽 돌을 출력해야하기 때문에 왼쪽 대각선이 아닌 오른쪽 대각선으로 체크를 한다.

그래서 (0, 0) 부터 (18, 18) 까지 차례로 순회하며 위 4가지 방향에서 오목인 경우가 있는 지를 확인하게 된다. 그리고 5개 연속으로 같은 돌인 경우 시작 돌 이전의 돌과 끝 돌 이후의 돌을 확인한 후 육목이 아니라면(다른 돌이라면) 답을 출력하고 종료하면 된다.

모든 순회를 마친 후에도 오목을 발견하지 못했다면 0을 출력하고 종료한다.

LEN = 19
t = [list(map(int, input().split())) for _ in range(LEN)]
d = [(0, 1), (1, 0), (1, 1), (-1, 1)]


def solution():
    for x in range(LEN):
        for y in range(LEN):
            if not t[x][y]: continue
            start = t[x][y]
            for k in range(4):
                count = 1
                nx, ny = x + d[k][0], y + d[k][1]

                while nx in range(LEN) and ny in range(LEN) and t[nx][ny] == start:
                    count += 1
                    # 육목 확인
                    if count == 5:
                        # 이전 돌 체크
                        bx, by = x - d[k][0], y - d[k][1]
                        if bx in range(LEN) and by in range(LEN) and t[bx][by] == start:
                            break
                        # 다음 돌 체크
                        nnx, nny = nx + d[k][0], ny + d[k][1]
                        if nnx in range(LEN) and nny in range(LEN) and t[nnx][nny] == start:
                            break
                        # 정답 출력
                        print(start)
                        print(x + 1, y + 1)
                        return
                    nx += d[k][0]
                    ny += d[k][1]
    print(0) # 승부 안 남


solution()

문제에서 바둑판의 길이가 19 x 19 라고 했지만 나는 range(19)와 같이 하드 코딩하는 것을 지양한다. 그래서 길이를 LEN 이라는 상수로 만들어 LEN을 대신 사용했다.

채점 결과

 

반응형
Comments