[Algorithm] 스토쿠 검사

myeonji·2022년 1월 24일
0

Algorithm

목록 보기
14/89

스도쿠는 매우 간단한 숫자 퍼즐이다. 9×9 크기의 보드가 있을 때, 각 행과 각 열, 그리고 9개의 3×3 크기의 보드에 1부터 9까지의 숫자가 중복 없이 나타나도록 보드를 채우면 된다. 위 그림은 스도쿠를 정확하게 푼 경우이다. 각 행에 1부터 9까지의 숫자가 중복 없이 나오고, 각 열에 1부터 9까지의 숫자가 중복 없이 나오고, 각 3×3짜리 사각형(9개이며, 위에서 색깔로 표시되었다)에 1부터 9까지의 숫자가 중복 없이 나오기 때문이다. 완성된 9×9 크기의 수도쿠가 주어지면 정확하게 풀었으면 “YES", 잘 못 풀었으면 ”NO"를 출력하는 프로그램을 작성하세요.

<내 답안>

list1 = [list(map(int, input().split())) for _ in range(9)]
str = 'YES'

# 행
for i in range(9):
    temp = sorted(list1[i])
    for j in range(9):
        if temp[j] == j+1:
            str = 'YES'
        else:
            str = 'NO'
            break
    if str == 'NO':
        print('NO')
        break

# 열
if str != 'NO':
    for i in range(9):
        temp = []
        for j in range(9):
            temp.append(list1[j][i])
        temp = sorted(temp)
        for k in range(9):
            if temp[k] == k+1:
                str = 'YES'
            else:
                str = 'NO'
                break
        if str == 'NO':
            print('NO')
            break

# 3x3
if str != 'NO':
    for i in range(0, 7, 3):
        temp = []
        for j in range(3):
            for k in range(3):
                temp.append(list1[j+i][k])
        temp = sorted(temp)
        for k in range(9):
            if temp[k] == k+1:
                str = 'YES'
            else:
                str = 'NO'
                break
        if str == 'NO':
            print('NO')
            break

if str != 'NO':
    for i in range(0, 7, 3):
        temp = []
        for j in range(3):
            for k in range(3):
                temp.append(list1[j+i][k+3])
        temp = sorted(temp)
        for k in range(9):
            if temp[k] == k+1:
                str = 'YES'
            else:
                str = 'NO'
                break
        if str == 'NO':
            print('NO')
            break

if str != 'NO':
    for i in range(0, 7, 3):
        temp = []
        for j in range(3):
            for k in range(3):
                temp.append(list1[j+i][k+6])
        temp = sorted(temp)
        for k in range(9):
            if temp[k] == k+1:
                str = 'YES'
            else:
                str = 'NO'
                break
        if str == 'NO':
            print('NO')
            break

if str != 'NO':
    print(str)

행하고 열을 검사하는 것까진 수월했다. 나는 행과 열 한 줄씩 temp라는 새로운 리스트를 생성하여 집어넣고 오름차순 정렬을 하여 다시 for문으로 1~9 임을 확인했다. (하지만 여기서 for문으로 확인하는 것은 시간낭비였다. 해설처럼 했으면 시간을 단축시켰을 것이다. 특히나 나는 행과 열을 구분하여 for문이 총 5번 돌았다..)
3x3 박스 부분에서 정~말 비효율적으로 구현했다. 나는 9x3으로 3번 나누어 풀었는데 같은 코드를 3번 구현한거나 다름 없었다. 풀면서도 이상했지만.. 어찌저찌 풀긴 했는데 해설이 생각보다 너무 간단해서 헛웃음이..ㅎ; ㅠㅠ

<모범답안>

def check(a):
    # ch1 = 행, ch2 = 열
    for i in range(9):
        ch1=[0]*10
        ch2=[0]*10
        for j in range(9):
            ch1[a[i][j]] = 1
            ch2[a[j][i]] = 1
        if sum(ch1)!=9 or sum(ch2)!=9:
            return False

    # 3x3 블럭
    for i in range(3):
        for j in range(3):
            ch3 = [0]*10
            for k in range(3):
                for s in range(3):
                    ch3[a[k+i*3][s+j*3]] = 1
            if sum(ch3) != 9:
                return False
    return True

a = [list(map(int, input().split())) for _ in range(9)]
if check(a):
    print("YES")
else:
    print("NO")

먼저 ch라는 10칸짜리 리스트를 3개 만들어 0으로 초기화 시켰다. for문 2개로 행과 열을 동시에 돌면서 이차원 리스트 a 값에 해당하는 인덱스 즉, 행은 ch1이고 열은 ch2의 인덱스를 1로 바꾸는 방식이다. 마지막은 ch 리스트의 전체 합이 9가 나오면 1부터 9까지 모든 수가 나온 것이므로 True이다. 3x3도 마찬가지다. 이것은 for문이 4개지만 로직은 똑같다. 생각해보면 해설 대부분이 이런 방식으로 푼 것이 많았다. 내 방식에만 갇혀있지 말고 이런 방법도 있다는 것에 익숙해지고 싶다.

0개의 댓글