코딩테스트

[백준][구현] 모노미노도미노

pythaac 2022. 4. 27. 22:30
BAEKJOON Online Judge(BOJ) 문제입니다.

https://www.acmicpc.net/

 

Baekjoon Online Judge

Baekjoon Online Judge 프로그래밍 문제를 풀고 온라인으로 채점받을 수 있는 곳입니다.

www.acmicpc.net

 

문제

https://www.acmicpc.net/problem/20061

 

20061번: 모노미노도미노 2

모노미노도미노는 아래와 같이 생긴 보드에서 진행되는 게임이다. 보드는 빨간색 보드, 파란색 보드, 초록색 보드가 그림과 같이 붙어있는 형태이다. 게임에서 사용하는 좌표 (x, y)에서 x는 행,

www.acmicpc.net

 

내가 작성한 코드

from collections import defaultdict, deque

def read_data():
    N = int(input().rstrip())
    command = deque()
    for _ in range(N):
        t, x, y = map(int, input().rstrip().split())
        command.append((t, x, y))
    blue = [[0 for _ in range(6)] for _ in range(4)]
    green = [[0 for _ in range(4)] for _ in range(6)]
    return N, command, blue, green

def in_range(r, c, board):
    return 0 <= r < len(board) and 0 <= c < len(board[0])

def move_and_deploy(board, crnt, d_r, d_c):
    def stop_moving(board, crnt, d_r, d_c):
        for r, c, t in crnt:
            if not in_range(r + d_r, c + d_c, board) or board[r + d_r][c + d_c] > 0:
                return True
        return False

    def deploy_block(board, crnt):
        for r, c, t in crnt:
            board[r][c] = t

    while not stop_moving(board, crnt, d_r, d_c):
        crnt = list(map(lambda x: (x[0]+d_r, x[1]+d_c, x[2]), crnt))

    deploy_block(board, crnt)

def blue_go_block(cmd, blue):
    def get_crnt(t, x):
        if t == 1:
            crnt = [(x, 0, t)]
        elif t == 2:
            crnt = [(x, 0, t), (x, 1, t)]
        else:
            crnt = [(x, 0, t), (x + 1, 0, t)]
        return crnt

    d_r, d_c = 0, 1
    t, x, y = cmd
    crnt = get_crnt(t, x)

    move_and_deploy(blue, crnt, d_r, d_c)

def green_go_block(cmd, green):
    def get_crnt(t, y):
        if t == 1:
            crnt = [(0, y, t)]
        elif t == 2:
            crnt = [(0, y, t), (0, y+1, t)]
        else:
            crnt = [(0, y, t), (1, y, t)]
        return crnt

    d_r, d_c = 1, 0
    t, x, y = cmd
    crnt = get_crnt(t, y)

    move_and_deploy(green, crnt, d_r, d_c)

def blue_destroy(blue):
    def destroy(c):
        for r in range(len(blue)):
            if blue[r][c] == 0:
                return 0
        for r in range(len(blue)):
            blue[r][c] = 0
        return 1
    def move(c, shift):
        if shift == 0:
            return
        d_r, d_c = 0, 1

        for r in range(len(blue)):
            blue[r + (d_r * shift)][c + (d_c * shift)] = blue[r][c]
        for r in range(len(blue)):
            blue[r][c] = 0

    score = 0
    shift = 0
    for c in range(len(blue[0]) - 1, -1, -1):
        nw_score = destroy(c)
        if nw_score > 0:
            score += nw_score
            shift += 1
        else:
            move(c, shift)
    return score


def green_destroy(green):
    def destroy(r):
        for c in range(len(green[0])):
            if green[r][c] == 0:
                return 0
        for c in range(len(green[0])):
            green[r][c] = 0
        return 1

    def move(r, shift):
        if shift == 0:
            return
        d_r, d_c = 1, 0

        for c in range(len(green[0])):
            green[r+(d_r*shift)][c+(d_c*shift)] = green[r][c]
        for c in range(len(green[0])):
            green[r][c] = 0

    score = 0
    shift = 0
    for r in range(len(green)-1, -1, -1):
        nw_score = destroy(r)
        if nw_score > 0:
            score += nw_score
            shift += 1
        else:
            move(r, shift)

    return score

def blue_shift(blue):
    def shift_amount():
        amount = 0
        for c in range(2):
            for r in range(len(blue)):
                if blue[r][c] != 0:
                    amount += 1
                    break
        return amount

    amount = shift_amount()
    if amount > 0:
        for r in range(len(blue)):
            for c in range(len(blue[0])-1, amount-1, -1):
                blue[r][c] = blue[r][c-amount]

        for r in range(len(blue)):
            for c in range(amount):
                blue[r][c] = 0


def green_shift(green):
    def shift_amount():
        amount = 0
        for r in range(2):
            for c in range(len(green[0])):
                if green[r][c] != 0:
                    amount += 1
                    break
        return amount

    amount = shift_amount()
    if amount > 0:
        for c in range(len(green[0])):
            for r in range(len(green) - 1, amount - 1, -1):
                green[r][c] = green[r-amount][c]

        for c in range(len(green[0])):
            for r in range(amount):
                green[r][c] = 0

def get_answer(N, command, blue, green):
    score = 0
    for cmd in command:
        blue_go_block(cmd, blue)
        _score = blue_destroy(blue)
        while _score > 0:
            score += _score
            _score = blue_destroy(blue)
        blue_shift(blue)

        green_go_block(cmd, green)
        _score = green_destroy(green)
        while _score > 0:
            score += _score
            _score = green_destroy(green)
        green_shift(green)

        # debug(blue, green)


    count = 0
    for row in blue:
        for v in row:
            if v != 0:
                count += 1

    for row in green:
        for v in row:
            if v != 0:
                count += 1

    return score, count

def debug(blue, green):
    print("=======================")

    for z in blue:
        print(z)
    print()

    for z in green:
        print(z)
    print()

def test():
    N = 1
    test = [
        (2, 0, 0), (2, 1, 1), (2, 2, 2), (2, 3, 1),
        (3, 0, 0), (3, 0, 0)
            ]
    command = deque(test)
    blue = [[0 for _ in range(6)] for _ in range(4)]
    green = [[0 for _ in range(4)] for _ in range(6)]
    return N, command, blue, green

N, command, blue, green = read_data()
# N, command, blue, green = test()
for answer in get_answer(N, command, blue, green):
    print(answer)
  • green / blue
    • 두 영역에 적용할 함수를 나누어 작성
    • 하나를 작성하고, 다른 하나는 복붙하여 수정
    • 수정 실수로 디버깅이 오래걸림
  • 삼성코딩테스트 다시 풀어볼 문제 메모

 

다른 사람이 작성한 코드

None
  • 강한 구현문제로 다른 코드를 참고하지 않음

 

기억해야할 것

  • 서로 다른 격자에 대한 함수 통합
    • 공통된 부분을 함수로 작성
    • 구별할 부분을 함수로 다시 묶기

 

'코딩테스트' 카테고리의 다른 글

[백준][구현] 원판 돌리기  (0) 2022.04.28
[백준][구현] 주사위 윷놀이  (0) 2022.04.28
[백준][구현] 청소년 상어  (0) 2022.04.27
[백준][구현] 어른 상어  (0) 2022.04.27
[백준][구현] 스타트 택시  (0) 2022.04.26