[ programmers ] 구현 - 기둥과 보 설치

김우경·2020년 11월 10일
0

알고리즘

목록 보기
9/69

문제링크


코딩테스트 연습 - 기둥과 보 설치

문제설명


n*n의 2차원 벽면에 기둥과 보를 설치하려고 한다.

설치

  • 기둥

    : 바닥 위/ 보의 한쪽 끝/ 다른 기둥 위

  • : 한쪽끝이 기둥위/ 양쪽 끝이 다른 보

삭제

: 삭제 뒤에도 규칙 만족할때

IN

  • n : 벽면의 크기
  • build-frame : 기둥, 보 설치/삭제 순서
    → [가로 좌표, 세로좌표, 기둥(0)보(1), 설치(0)삭제(1)] 형태로 주어짐

OUT

  • 모든 명령어 수행 후의 상태
    → 가로길이가 3인 2차원 배열로 각 구조물의 좌표 담기
    : [가로 좌표, 세로 좌표, 기둥(0)보(1)]
    → 가로, 세로, 기둥, 보 순으로 정렬하기

문제풀이

시도 1

#기둥과 보

def establish(build_frame, wall):
    print("buil")
    if build_frame[2] == 0:
        #기둥
        if build_frame[1] == 0 or  wall[build_frame[1]][build_frame[0]-1] == 2 or wall[build_frame[1]-1][build_frame[0]] == 1:
            #바닥 위
            wall[build_frame[1]][build_frame[0]] = 1
        elif wall[build_frame[1]][build_frame[0]] == 2:
            #보의 한쪽 끝
            wall[build_frame[1]][build_frame[0]] = 3
    else:
        #보
        if wall[build_frame[1]-1][build_frame[0]] == 1 or wall[build_frame[1]-1][build_frame[0]+1] == 1 or (wall[build_frame[1]][build_frame[0]-1] == 2 and wall[build_frame[1]][build_frame[0]+1] == 2):
            #양쪽끝이 다른 보
            wall[build_frame[1]][build_frame[0]] = 2
            
    
def delete(build_frame, wall):
    prev = wall[build_frame[1]][build_frame[0]]
    #일단 지우고
    if wall[build_frame[1]][build_frame[0]] == 3:
        wall[build_frame[1]][build_frame[0]] = 3 - wall[build_frame[1]][build_frame[0]]
    else: wall[build_frame[1]][build_frame[0]] = 0
    possible = 0
    #모든 벽이 조건 만족하는지 찾기
    for i in range(len(wall)):
        for j in range(len(wall)):
            if wall[i][j] == 1:
                #기둥 조건 만족?
                if i == 0 or wall[i][j-1] != 1 or wall[i-1][j] != 2:
                    continue
                else:
                    wall[build_frame[1]][build_frame[0]] = prev
                    return
            elif wall[i][j] == 2:
                #보 조건 만족?
                if wall[i-1][j] !=2 or wall[i-1][j+1] !=2 or (wall[i][j-1] !=1 and wall[i][j+1] !=1):
                     continue
                else:
                    wall[build_frame[1]][build_frame[0]] = prev
                    return
            elif wall[i][j] == 3:
                if i == 0 or wall[i][j-1] != 1 or wall[i-1][j] != 2 or wall[i-1][j] !=2 or wall[i-1][j+1] !=2 or (wall[i][j-1] !=1 and wall[i][j+1] !=1):
                    continue
                else:
                    wall[build_frame[1]][build_frame[0]] = prev
                    return
    

def solution(n, build_frame):
    answer = []
    #기둥:1, 보:2, 둘다:3
    wall = [[0]*(n+1) for _ in range(n+1)]
    for i in range(len(build_frame)):
        if build_frame[i][3] == 0:
            delete(build_frame[i], wall)
        else:
            establish(build_frame[i], wall)
        
        print(i, ": ", build_frame[i])
        for j in range(len(wall)-1, -1, -1):
            print(wall[j])
        print("\n")

    for i in range(len(wall)):
        for j in range(len(wall)):
            if wall[i][j] == 1:
                tmp = [j, i, 0]
                answer.append(tmp)
            elif wall[i][j] == 2:
                tmp = [j, i, 1]
                answer.append(tmp)
            elif wall[i][j] == 3:
                tmp = [j, i, 0]
                answer.append(tmp)
                tmp = [j, i, 1]
                answer.append(tmp)
    answer.sort(key= lambda x:(x[0], x[1], x[2]))
    return answer

print(solution(5,	[[0,0,0,1],[2,0,0,1],[4,0,0,1],[0,1,1,1],[1,1,1,1],[2,1,1,1],[3,1,1,1],[2,0,0,0],[1,1,1,0],[2,2,0,1]]))

벽 사이즈만큼 리스트를 할당해 각 명령어마다 설치/삭제가 가능한지 판별하고 가능할때 해당 좌표에 비었을때 0, 기둥의 경우 1, 보는 2, 둘다 있을때는 3으로 바꾸어줬다.

둘다 있을때 3이 뭔가 문제가 나는것 같다. 파이썬 쓰면서 파이썬 활용 못하고 걍 갖다 하나하나 구현해버린듯 ㅋ.ㅋ

설치와 삭제 함수를 만들어 각 명령어 실행시 규칙에 맞는지 판별하였다.

설치는 맞게 되었는데, 삭제에서 모든 케이스를 분류하지 못해 오류가 났다 ,,,, 전체를 검사하는 방법으로 바꿨는데 마찬가지로 되지 않았다 ,,,,

시도 2

def possible(answer):
    for x,y,a in answer:
        if a == 0:
            #기둥이면
            if y==0 or [x-1, y, 1] in answer or [x, y, 1] in answer or [x, y-1, 0] in answer:
                continue
            return False
        elif a == 1:
            #보이면
            if [x, y-1, 0] in answer or [x+1, y-1, 0] in answer or ([x-1, y, 1] in answer and [x+1, y, 1] in answer):
                continue
            return False
    return True

def solution(n, build_frame):
    answer = []

    for i in build_frame:
        x, y, a, b = i
        if b == 0:
            answer.remove([x, y, a])
            if not possible(answer):
                answer.append([x, y, a])
        if b == 1:
            answer.append([x, y, a])
            if not possible(answer):
                answer.remove([x, y, a])
        
    return sorted(answer)

이렇게 간단하게 끝내다니 ,,, 눈물이 날라하네 ,,

각 명령어마다 일단 설치/삭제하고 가능한지를 possible() 함수로 판단한다.

나처럼 따로 벽에 대한 배열을 두는 것이 아닌 answer에 설치된 구조물에 대한 좌표만 넣어놓고 in으로 판단한다. 똑똑한 파이썬,,

내일 다시 풀어보기 흑흑

알게 된 것

  • 리스트의 정렬 여러 조건으로

    answer.sort(key = lambda x : (x[0], x[1], x[2])
profile
Hongik CE

0개의 댓글