[백준] 2447번 별 찍기 - 10 | 파이썬 Python

문제

재귀적인 패턴으로 별을 찍어 보자. N이 3의 거듭제곱(3, 9, 27, ...)이라고 할 때, 크기 N의 패턴은 N×N 정사각형 모양이다.

크기 3의 패턴은 가운데에 공백이 있고, 가운데를 제외한 모든 칸에 별이 하나씩 있는 패턴이다.

***
* *
***

N이 3보다 클 경우, 크기 N의 패턴은 공백으로 채워진 가운데의 (N/3)×(N/3) 정사각형을 크기 N/3의 패턴으로 둘러싼 형태이다. 예를 들어 크기 27의 패턴은 예제 출력 1과 같다.

 

입력

첫째 줄에 N이 주어진다. N은 3의 거듭제곱이다. 즉 어떤 정수 k에 대해 N=3k이며, 이때 1 ≤ k < 8이다.

 

출력

첫째 줄부터 N번째 줄까지 별을 출력한다.

 

예제

etc-image-0

 

나의 풀이

N = int(input())
stars = []

for i in range(N):
    if i % 3 == 1:
        stars.append(["*", " ", "*"]*9)
    else: 
        stars.append(["*" for _ in range(N)])

def make_blank(size, cnt, row, col):
    third = size//3
    blank = [" " for i in range(third)]

    if col >= N:
        return make_blank(size, 1, row+size, third)
    elif row < N:
        if cnt < third:
            stars[row+cnt][col:col+third] = blank
            return make_blank(size, cnt+1, row, col)
        else:
            stars[row][col:col+third] = blank
            return make_blank(size, 1, row, col+size)

size = 9
while size <= N:
    make_blank(size, 1, size//3, size//3)
    size *= 3

for line in stars:
    print("".join(line))
  • 2차원 배열을 이용해서 접근했다. 크기 3의 패턴을 기본적으로 그리고, 크기 9의 패턴부터는 재귀 함수를 실행해 리스트의 요소를 수정한다.
  • while문을 통해 크기 9, 크기 27... 순서로 단계적으로 패턴을 그린다.
  • 처음에는 크기 3의 패턴 부분을 제외하고는 모든 요소를 *로 채워넣고, 재귀함수를 실행하면서 중간중간 크기에 맞는 공백을 넣는 방법을 사용했다.
  • 이 풀이는 예제를 그리는 것에는 성공했지만 4의 거듭제곱부터는 이상하게 그려지고, 결과적으로 런타임 에러로 실패했다.

 

다른 사람의 풀이

N = int(input())

def append_star(len):
    if len == 1:
        return ['*']

    Stars = append_star(len//3)
    li = []

    for S in Stars:
        li.append(S*3)
    for S in Stars:
        li.append(S + ' '*(len//3) + S)
    for S in Stars:
        li.append(S*3)
    
    return li

print('\n'.join(append_star(N)))
  • 리스트의 하나의 요소에 한 줄씩 담아서 출력하는 풀이 방법이다.
  • append_star()27 -> 9 -> 3 순서대로 함수를 실행하면서 크기 3의 패턴부터 그리기 시작해서, 이전의 함수가 반환한 리스트를 이용해서 패턴의 크기를 점점 확장해 나간다.
    • * -> *** -> ********* 순으로 리스트의 요소를 3배씩 더해나간다.
  • 공백 부분을 제외하고는 크기 3의 패턴이 반복되는 구조이기 때문에 첫 번째, 세 번째 for문은 크기 3의 패턴을 반복해서 생성하고 두 번째 for문에서는 가운데 공백을 생성한다. (기본적으로 크기 3의 기본 패턴을 NxN 크기의 정사각형 바탕에 반복적으로 깔아놓고 공백을 추가하는 과정이라고 생각하면 된다.)
  • 최종적으로 생성된 리스트를 한 줄씩 줄바꿈해서 출력한다.

 

회고

  • 며칠을 붙잡고 있다가 포기하고 다른 사람의 풀이를 처음 봤을 때 이걸 이렇게 깔끔하게 풀 수 있다고? 싶어서 감탄이 나왔다.
  • 나는 문자열을 위에서부터 한 줄씩 출력해야 된다는 점에 꽂혀서 별을 한 글자씩 쪼갠 후에 요소를 쉽게 수정할 수 있는 2차원 리스트로만 접근했었는데 지금 생각해 보면 너무 비효율적이고 재귀함수답지 않은 풀이였다.
  • 이렇게 점점 재귀함수에 대한 개념이 머릿속에 잡혀가는 거 같다. 이번 문제로 많이 배웠다!

 

참고