[분할 정복] 백준 2447번: 별 찍기 - 10

KimRiun·2021년 5월 17일
2

알고리즘_문제

목록 보기
11/26

사용 언어: python 3.7.4

❓ Problem

문제 설명

문제

백준 2447번: 별 찍기 - 10

🚩 Solution

1. 접근법

1차 접근(오답

n=3 일 때 별을 도장처럼 찍어간다고 생각했다.

규칙에 맞게 도장을 찍으면 될 거라고 생각했다.

하지만 출력에서 막혔다.

패턴이 담긴 리스트에서 별을 규칙에 맞게 출력하기 어려워 다른 접근법을 사용하게 되었다.

2차 접근

<나무와 함께 푼 풀이>

  • 아이디어

위아래 패턴(top_bottom)과 중간 패턴(middle)으로 쪼갠다.

위와 아래 패턴은 같은 모양이기 때문에, 위 패턴만 만들면 아래 패턴은 재사용할 수 있다.

패턴을 만들 때, 이전 별 모양(n//3 일 때)을 '한 줄씩' 가져와서 만든다.

  • 패턴 만들기
  1. 기저 코드를 먼저 작성한다. n = 3일 때를 기저로 설정했다.
# 기저
    if n == 3:
        return ['***','* *','***']
  1. 본격적으로 패턴을 만들기 위해, 이전 별 모양을 가져온다.
before_star = printStar(n//3) # 이전 별 모양
  1. top_bottom을 만드는 과정을 살펴보자.

top_bottom의 첫째 줄은 이전 별 모양 첫째 줄*3이다.

top_bottom의 둘째 줄은 이전 별 모양 둘째 줄*3이다.

top_bottom의 셋째 줄은 이전 별 모양 셋째 줄*3이다.

코드를 보면 아래와 같다.

# 위, 아래 패턴. 둘은 같은 모양이다.
    top_bottom = []
    for i in range(n//3):
        text = before_star[i]*3
        top_bottom.append(text)

'''
>> print(top_bottom)
['*********', '* ** ** *', '*********']
'''
  1. middle 패턴을 만드는 과정도 비슷한데, 중간을 n//3만큼 공백으로 채워주면 된다.
# 중간 패턴
    middle = []
    for i in range(n//3):
        text = before_star[i]+ ' '*(n//3) + before_star[i]
        middle.append(text)
'''
>> print(middle)
['***   ***', '* *   * *', '***   ***']
'''
  1. 그렇다면 정답을 저장할 리스트에 top_bottom, middle, top_bottom를 순서대로 붙이고 출력하면 된다.

이때 리스트.append()를 써서 붙이면 차원이 늘어나게 되고, 그러면 출력하기 불편해진다.

대신 리스트.extend()를 사용하면 1차원을 유지하여 패턴을 붙일 수 있고, 그러면 for문을 한 번만 돌려 쉽게 출력할 수 있다.

results = []
results.extend(top_bottom)
results.extend(middle)
results.extend(top_bottom)
'''
>> print(results)
['*********', '* ** ** *', '*********', '***   ***', '* *   * *', '***   ***', '*********', '* ** ** *', '*********']
'''

전체 코드는 아래 '2차 접근 코드(정답)'에 있다.

2. 코드

  • 1차 접근 코드(오답)
# 틀린 코드. n=27 부터도 뭔가 이상함
import sys

def printStar(n):
    # 기저
    if n == 3:
        return ['***','* *','***']

		results = []
		for i in range(3):
		        for j in range(3):
		            if i == 1 and j == 1:
		                results.append([' '*(n//3)]*(n//3))
		            else:
		                results.append((printStar(n//3)))
		
		        for i in range(n//3):
		            for j in range(n//3):
		                print(results[j][i], end='')
		            print()

    return results

n = int(sys.stdin.readline())
answer = printStar(n)

print('\n'.join(answer))
  • 2차 접근 코드(정답)
import sys

def printStar(n):
    # 기저
    if n == 3:
        return ['***','* *','***']

    results = []
    before_star = printStar(n//3) # 이전 별 모양

    # 위, 아래 패턴. 둘은 같은 모양이다.
    top_bottom = []
    for i in range(n//3):
        text = before_star[i]*3
        top_bottom.append(text)

    # 중간 패턴
    middle = []
    for i in range(n//3):
        text = before_star[i]+ ' '*(n//3) + before_star[i]
        middle.append(text)

    results.extend(top_bottom)
    results.extend(middle)
    results.extend(top_bottom)

    return results

n = int(sys.stdin.readline())
answer = printStar(n)

print('\n'.join(answer))
  • 다른 사람 코드
a=int(input())
def s(n):
 if n==3:return['***','* *','***']
 x=s(n//3)
 y=list(zip(x,x,x))
 for i in range(len(y)):y[i]=''.join(y[i])
 z=list(zip(x,[' '*(n//3)]*(n//3),x))
 for i in range(len(z)):z[i]=''.join(z[i])
 return y+z+y
print('\n'.join(s(a)))

3. 결과

채점 결과

correct

메모리시간코드길이
41292 KB75 ms670 B

시간 복잡도 분석

O (NlogN)

📕 피드백

1. 검색한 내용

2. 실수

3. 발전 방향

  1. 나무의 피드백:
재귀를 풀 때는 함수의 리턴값 모양을 만들어두자.
예시: 1차원 리스트 안에 문자열만 있는 형태로 만들기
-> 이런 식으로 형태가 고정적이어야 재귀 함수에서 활용 가능
  1. print하기가 까다로우면, print할 데이터를 가공하는 방향으로 생각해보자.

4. 느낀점

첫번째 접근법 출력이 너무 어려워서 몇 시간동안 고생했다. 힘들었다.

profile
Java, Python

2개의 댓글

comment-user-thumbnail
2021년 5월 22일

그림자료가 있어서 이해가 더 잘 되네요!

1개의 답글