본문 바로가기

컴퓨터/알고리즘

백준 2447 파이썬

복잡하지만, 재귀 자체를 익히기 좋은 문제는 아닌 것 같습니다.

이 문제는 재귀만으로 풀기에는 무리가 있습니다. 그 이유는 아래에서 자세히 다루고,
이 포스트에서는 반복을 포함한 쉬운 방법으로 구현한 코드를 다루겠습니다.

size = int(input())

def make(size):
    if size ==1:
        return [['*']]

    unitsize = int(size/3)

    full = [[] for i in range(size)]
    unit = make(unitsize)
    none = [' ' for i in range(int(size/3))]

    for i in range(size):
        for j in range(3):
            if j==1 and int(i/(unitsize))==1:
                full[i].extend(none)
            else:
                full[i].extend(unit[i%unitsize])
    return full

for i in make(size):
    for j in i:
        print(j, end='')
    print()

재귀를 사용하는 이유는 속도가 아니고 가독성이기 때문에, 굳이 재귀로 전체 구현을 하지 않았습니다.
먼저 부분별로 나누어 설명해 보겠습니다.

size = int(input())

입력입니다. 숫자 한 개를 받았습니다.

def make(size):
    if size ==1:
        return [['*']]

make함수는 재귀를 활용한 함수로, 크기 1의 별 배열을 요청하면 바로 한개짜리 배열을 리턴합니다.

    unitsize = int(size/3)

    full = [[] for i in range(size)]
    unit = make(unitsize)
    none = [' ' for i in range(int(size/3))]

이 부분을 설명하기 전에 이 문제를 어떻게 이해했는지부터 이야기하면,
출력할 배열은 사이즈가 3,9,27,81으로 커져도 언제나 3x3=9개의 부분으로 나누어지게 되며, 9개 중 1개의 사이즈를 unitsize로 정합니다.

ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ
ㅇ ㅇ ㅇ

--> size가 9일 때

위의 경우 unitsize는 3이 됩니다.
그래서 make(3)을 호출하고, make(3)에서의 unitsize는 1이므로 make(1)을 호출합니다.
이 때, 1인 경우에는 바로 리턴하도록 if문이 있으므로(위쪽 코드 블락 참고),
한 개짜리 unit을 (*) 가져오게 됩니다.

full은 리턴하기 위한 전체 배열이고, none은 아무것도 없는 배열입니다.

    for i in range(size):
        for j in range(3):
            if j==1 and int(i/(unitsize))==1:
                full[i].extend(none)
            else:
                full[i].extend(unit[i%unitsize])
    return full

가져온 unit을 배열에 추가하기 위한 코드입니다.
i는 세로, j는 가로로 순회하는데, i의 경우 9개 전부 순회해야 하지만 j는 하위 배열의 한 줄(3개)을 한꺼번에 추가 가능하기 때문에(3+3+3) 3번만 순회하면 됩니다.
이 부분을 재귀로 만들려고 하면, 함수 인자로 "전체 배열에서 인덱스 a,b부터 인덱스 c,d까지 어떤 배열로 채우시오"를 지정해야 하는데,
이 부분이 복잡하기 때문에 재귀로 구현했습니다.

for i in make(size):
    for j in i:
        print(j, end='')
    print()

마지막으로 결과 배열을 전체 출력해주었습니다.