Programmers - 자물쇠와 열쇠

SJ0000·2022년 6월 10일

문제 링크

완전탐색 문제

열쇠를 0도,90도,180도,270도 회전 시킨 상태를 기준으로
left와 up을 반복하면서 맞는지 확인
left와 down을 반복하면서 맞는지 확인
right와 up을 반복하면서 맞는지 확인
right와 down을 반복하면서 맞는지 확인

rotate90(): 2차원 배열을 90도 회전한 후 결과를 반환하는 함수
size_up() : key의 size를 키워서 lock의 size와 같게 만드는 함수
move_up,down,left,right() : 열쇠를 해당 방향으로 이동
is_match() : 자물쇠가 열리는지 확인
simulate() : 방향1,방향2를 입력받아서 해당 방향대로 진행하여 자물쇠가 열리는지 확인하는 함수

from collections import deque


def rotate90(key):
    copied = key[:]
    copied.reverse()
    return list(map(list, zip(*copied)))


def size_up(key, n):
    m = len(key)
    if n == m:
        return key

    diff = n-m
    new_key = []
    added_row = [0 for _ in range(diff)]
    for row in key:
        new_key.append(row + added_row)

    zero_row = [0 for _ in range(n)]
    for i in range(diff):
        new_key.append(zero_row)

    return new_key


def move_up(key):
    n = len(key)
    new_key = []
    for i in range(1, n):
        new_key.append(key[i])
    new_key.append([0 for i in range(n)])
    return new_key


def move_down(key):
    n = len(key)
    new_key = []
    new_key.append([0 for i in range(n)])
    for i in range(n-1):
        new_key.append(key[i])

    return new_key


def move_right(key):
    n = len(key)
    new_key = []
    for row in key:
        new_key.append([0]+row[:n-1])
    return new_key


def move_left(key):
    n = len(key)
    new_key = []
    for row in key:
        new_key.append(row[1:]+[0])
    return new_key


def is_matched(key, lock):
    '''
    print("is matched")
    for i in range(len(key)):
        print(key[i], "     ", lock[i])
    '''
    n = len(key)
    for i in range(n):
        for j in range(n):
            if key[i][j] == lock[i][j]:
                return False
    return True


# l,u / l,d / r,u / r,d
def simulate(key, lock, left_or_right, up_or_down):
    n = len(lock)
    visit = [[[False for _ in range(n+1)]
              for __ in range(n+1)] for _____ in range(4)]

    q = deque()
    rotated_key1 = rotate90(key)
    rotated_key2 = rotate90(rotated_key1)
    rotated_key3 = rotate90(rotated_key2)

    q.append((key, 0, 0, 0))
    q.append((rotated_key1, 1, 0, 0))
    q.append((rotated_key2, 2, 0, 0))
    q.append((rotated_key3, 3, 0, 0))

    while len(q) > 0:
        (current_key, rotate_count, lr, ud) = q.popleft()

        if lr > n or ud > n:
            continue

        if visit[rotate_count][lr][ud]:
            continue

        visit[rotate_count][lr][ud] = True

        if is_matched(current_key, lock):
            return True

        if left_or_right == 'left':
            q.append((move_left(current_key), rotate_count, lr+1, ud))
        else:
            q.append((move_right(current_key), rotate_count, lr+1, ud))

        if up_or_down == 'up':
            q.append((move_up(current_key), rotate_count, lr, ud+1))
        else:
            q.append((move_down(current_key), rotate_count, lr, ud+1))

    return False


def solution(key, lock):

    key = size_up(key, len(lock))

    # l,u / l,d / r,u / r,d
    if simulate(key, lock, 'left', 'up'):
        return True
    if simulate(key, lock, 'left', 'down'):
        return True
    if simulate(key, lock, 'right', 'up'):
        return True
    if simulate(key, lock, 'right', 'down'):
        return True

    return False
profile
잘하고싶은사람

0개의 댓글