문제에 나온 조건들을 실수하지 않고 모두 만족시키도록 하는 것이 중요한 문제였다.

 

간단하게 생각하면 구조물을 새롭게 짓거나 제거할 때 지으려는 위치 근처에 있는 다른 구조물들이 존재하는 위치에 따라 가능 여부가 정해진다.

 

벽면을 2차원 배열의 필드로 만들어서 조건들을 비교하기보다는 set을 하나 만들어서 (x좌표, y좌표, 구조물 종류)를 저장하도록 했다.

 

기둥은 세로, 보는 가로로 지어지기 때문에 같은 위치에 서로 다른 구조물이 동시에 존재할 수 있다.

 

구조물을 지을 때 순서는 이렇다.

  1. 지으려는 장소에 지으려는 구조물이 이미 존재하지 않는다면(set에 현재 위치와 구조물 요소가 없다면)
  2. 벽면에 구조물을 짓고(set에 추가하고)
  3. 모든 구조물들 상태가 괜찮은지 전부 확인하고(set에 있는 모든 요소들이 구조물에 따른 조건에 맞는지 검사)
  4. 조건에 맞으면 구조물 짓기 완료!
  5. 만약 조건에 맞지 않다면 지은 구조물을 제거한다

구조물을 제거할 때는 위의 순서에서 지을 때를 제거할 때로 바꾸고, 제거할 때를 지을 때로 바꾸면 된다.

 

구조물에 따른 조건을 꼼꼼하게 작성하고 실수하지 않는게 굉장히 중요한 문제였던 것 같다.

 

EMPTY = -1
PILLAR = 0
PLATE = 1
BUILD = 1
REMOVE = 0


def solution(n, build_frame):
    answer = set()

    for frame in build_frame:
        x, y, structure, action = frame
        frame_set = (x, y, structure)

        if action == BUILD:
            buildStructure(answer, frame_set)

        if action == REMOVE:
            removeStructure(answer, frame_set)

    return getSortedAnswer(answer)


def buildStructure(answer, frame_set):
    if frame_set in answer:
        return
    answer.add(frame_set)
    if isPossibleAnother(answer):
        return
    answer.remove(frame_set)


def removeStructure(answer, frame_set):
    if frame_set not in answer:
        return
    answer.remove(frame_set)
    if isPossibleAnother(answer):
        return
    answer.add(frame_set)


def isPossibleAnother(answer):
    for x, y, structure in answer:
        if structure == PILLAR and not isPossiblePillar(answer, x, y):
            return False
        if structure == PLATE and not isPossiblePlate(answer, x, y):
            return False

    return True


def isPossiblePillar(answer, x, y):
    def isOnFloor(): return True if y == 0 else False
    def isOnPillar(): return True if (x, y-1, PILLAR) in answer else False
    def isOnPlate(): return True if (x-1, y, PLATE) in answer or (x, y, PLATE) in answer else False

    if isOnFloor() or isOnPillar() or isOnPlate():
        return True

    return False


def isPossiblePlate(answer, x, y):
    def isOnPillar(): 
        return True if (x, y-1, PILLAR) in answer or (x+1, y-1, PILLAR) in answer else False
    def isOnTwoPlate(): 
        return True if (x-1, y, PLATE) in answer and (x+1, y, PLATE) in answer else False

    if isOnPillar() or isOnTwoPlate():
        return True

    return False


def getSortedAnswer(answer):
    answer = [list(s) for s in answer]
    return sorted(answer, key=lambda x: (x[0], x[1], x[2]))

+ 따끈한 최근 게시물