본문 바로가기
Problem Solving

여러 좌표가 주어질 때 이쁘게 별(*) 찍기

by sohyunwriter 2021. 2. 7.

오늘 코딩테스트를 보다가 오랜만에 '별 찍기' 문제를 보게 됐다.

 

해당 문제에서 좀 까다로웠던 부분만 하위 문제로 새롭게 만들어봤다.

 

 

Q. 여러 좌표가 주어질 때 이쁘게 별(*) 찍기

 

(-1, 0), (1, 0) 과 같은 좌표가 주어지면, 

주어진 좌표는 '*'로 표시하고, 나머지는 '.'로 표시한다.

즉, ['*.*'] 로 출력한다.

 

물론 board의 크기 제한은 없지만, 

['...', '*.*']로 출력하면 안 된다. 즉, '...'는 굳이 필요 없으므로 제거한다.

 

별로 어렵지 않은 문제인데, 구현을 어떻게 하면 간단히 할까라는 생각을 시험 끝나고 생각해보다가, 

다음과 같이 함수화시켜봤다.

 

points_to_star 함수는 점들이 주어지면 해당 점들에 대해 '*'로 board에 표시해주는 함수다.

 

코드

from random import randint

def points_to_star(points):
    """
    This function is to mark points(x, y) to star(*) in the board.
    Input: [(x1, y1), (x2, y2), .... ] 좌표들의 집합

    Output: 좌표는 (*)로 출력하고 아닐 경우 (.)로 출력
            단, board 크기는 (*)의 최소, 최대에 따라 이쁘게 출력. (e.g. ["...", "*.."] (<-wrong),  ["*.."] (<-correct)

    Examples:
    >>> points_to_star([(-1, 0), (1, 0)])
    ['*.*']

    >>> points_to_star([(0, 0)])
    ['*']

    >>> points_to_star([(-2, 3), (5, 4)])
    ['.......*', '*.......']
    """

    min_x = min(points, key=lambda x: x[0])[0]
    max_x = max(points, key=lambda x: x[0])[0]
    min_y = min(points, key=lambda x: x[1])[1]
    max_y = max(points, key=lambda x: x[1])[1]
    board = [["."] * (max_x - min_x + 1) for _ in range(min_y, max_y+1)]

    # parallel translation (min_x, max_y) -> (0, 0)
    # y means row, x means col
    for x, y in points:
        board[abs(y-max_y)][x-min_x] = "*"

    ans = ["".join(i) for i in board]
    return ans

if __name__ == "__main__":
    import doctest
    doctest.testmod()

    n = 5
    points = []
    for i in range(n):
        x = randint(-10, 10)
        y = randint(-10, 10)
        points.append([x, y])

    print(f'Question\n {points}')
    print(f'GOT\n {points_to_star(points)}')

 

풀이방법

1) min_x, max_x, min_y, max_y 구하기

'*'를 모두 나타내는데 필요한 최소 board 크기를 구한다. 즉, points 집합에서 min_x, max_x, min_y, max_y를 구한다.

 

2) 최소한의 크기의 board 만들기

(max_y-min_y+1, max_x-min_x+1) 모양의 board를 만든다. 그리고 '.'로 초기화한다.

여기서 주의할 건, 좌표상 yboard에서는 row이고, 좌표상 x는 board에서 col로 매칭된다.

 

예시)

(min_x, max_y)                                          (max_x, max_y)
                        
(min_x, min_y)     (max_x, min_y)

표에 색칠이 안 돼서 위와 같이 표시했다.

위 그림을 보면 (x, y) 좌표는 list에서 각각 (col, row)랑 연관있다는 걸 알 수 있다.

 

3) points 집합에 있는 좌표는 '*'로 바꾸기

이때, (min_x, max_y)를 (0, 0)으로 평행이동시켰다. 물론 이 부분은 for문 2개 돌리며 구현해도 되지만, 평행이동시키면 코드가 한 줄로 깔끔해져서 이렇게 풀었다.

평행이동으로 구현할 때 주의할 점은, 원래 (x, y) 좌표가 board에서는 (abs(y - max_y), x - min_x)로 표현된다. 음수가 나올 수도 있어서 해당 부분을 절댓값 처리해야 한다.

 

그리고 마지막은 join을 이용해서 문자열로 연결했다. 참고로, 처음부터 각 행을 하나의 문자열로 만들지 않은 이유는 '*'자리는 '*'로 바꾸기 위함이었다.

 

좌표가 주어질 때 이쁘게 * 찍는 문제가 얼마나 등장할지 모르겠지만, 

나중에 귀차니즘을 줄이기 위해 해당 부분을 함수로 만들어둔다.

 

 

 

 

'Problem Solving' 카테고리의 다른 글

2020년~2016년 주요 기업 코딩 테스트 유형 분석  (0) 2021.01.16