https://www.acmicpc.net/problem/2447
코드1_1 - "*"로 다 채워놓은 다음, 빈 칸을 찾아 없애는 방식
n=int(input()) # input
arr = [["*"]*n for _ in range(n)] # output array 생성
v=n;cnt=0
while v!=1: # 입력받은 n이 3의 몇승?
v/=3
cnt+=1
for cnt_ in range(cnt):
idx = [i for i in range(n) if (i // 3 ** cnt_) % 3 == 1] # 빈칸으로 채울 행/열 index
for i in idx:
for j in idx:
arr[i][j] = " "
# 출력
print('\n'.join([''.join([str(i) for i in row]) for row in arr]))
코드1_2 - 위 코드 function으로 묶기
def star(i):
global arr # arr 전역변수화; r에서 "<<-" 와 같은 기능
idx = [i for i in range(n) if (i // 3 ** cnt_) % 3 == 1]
for i in idx:
for j in idx:
arr[i][j] = " "
n=int(input())
v=n;cnt=0
while v!=1:
v/=3
cnt+=1
arr = [["*"]*n for _ in range(n)]
for cnt_ in range(cnt):
star(cnt_)
print('\n'.join([''.join([str(i) for i in row]) for row in arr]))
코드1 설명
if) n = 27
1) 위에부터 3(=3^1)줄씩 한 세트라고 했을 때,
행 기준 : 각 세트에서 두 번째 줄에서 가장 처음 빈 칸이 나타나기 시작한다.
*************************** .......... 0
* ** ** ** ** ** ** ** ** * .......... 1
*************************** .......... 2
*** ****** ****** *** .......... 3
* * * ** * * ** * * * .......... 4
*** ****** ****** *** .......... 5
*************************** .......... 6
* ** ** ** ** ** ** ** ** * .......... 7
*************************** .......... 8
********* ********* .......... 9
* ** ** * * ** ** * .......... 10
********* ********* .......... 11
*** *** *** *** .......... 12
* * * * * * * * .......... 13
*** *** *** *** .......... 14
********* ********* .......... 15
* ** ** * * ** ** * .......... 16
********* ********* .......... 17
*************************** .......... 18
* ** ** ** ** ** ** ** ** * .......... 19
*************************** .......... 20
*** ****** ****** *** .......... 21
* * * ** * * ** * * * .......... 22
*** ****** ****** *** .......... 23
*************************** .......... 24
* ** ** ** ** ** ** ** ** * .......... 25
*************************** .......... 26
즉, 전체적으로 봤을 때 [1, 4, 7, 10, 13, 16, 19, 22, 25] index이다.
또한, 두 번째 줄에서 빈 칸의 index역시 [1, 4, 7, 10, 13, 16, 19, 22, 25] 이다.
이 때, [1, 4, 7, 10, 13, 16, 19, 22, 25]은 3의 배수+1.
즉, 1~n 중 n%3==1 인 수 이다.
2) 위에서 9(=3^2)줄씩 한 세트라고 했을 때,
행 기준 : 각 세트에서 [3,4,5]줄에서 가장 처음 큰 빈칸(3 by 3)이 나타나기 시작한다.
즉, 9줄 안에서도 3줄씩 한 세트라고 했을 때, 1)과 마찬가지로 두 번째 줄이다.
전체적으로 [3, 4, 5, 12, 13, 14, 21, 22, 23] 번째 index이며,
이는 (n//3)%3==1인 수이다.
***************************
* ** ** ** ** ** ** ** ** *
*************************** .......... 0
*** ****** ****** ***
* * * ** * * ** * * *
*** ****** ****** *** .......... 1 : 3,4,5
***************************
* ** ** ** ** ** ** ** ** *
*************************** .......... 2
********* *********
* ** ** * * ** ** *
********* ********* .......... 3
*** *** *** ***
* * * * * * * *
*** *** *** *** .......... 4 : 12,13,14
********* *********
* ** ** * * ** ** *
********* ********* .......... 5
***************************
* ** ** ** ** ** ** ** ** *
*************************** .......... 6
*** ****** ****** ***
* * * ** * * ** * * *
*** ****** ****** *** .......... 7 : 21,22,23
***************************
* ** ** ** ** ** ** ** ** *
*************************** .......... 8
위와 같은 방식으로 총 3번(27은 3의 3승이기때문) 반복하여 빈 칸을 찾아주면 완성된다.
코드1 예시
ex)
>>> n = 9
>>> arr = [["*"]*n for _ in range(n)]
print('\n'.join([''.join([str(i) for i in row]) for row in arr]))
*********
*********
*********
*********
*********
*********
*********
*********
*********
>>> v=n;cnt=0
while v!=1:
v/=3
cnt+=1
>>> cnt
2
>>> cnt_ = 0
>>> idx = [i for i in range(n) if (i // 3 ** cnt_) % 3 == 1] # 빈 칸의 행/열 위치
>>> idx
[1,4,7]
>>> for i in idx:
for j in idx:
arr[i][j] = " "
>>> print('\n'.join([''.join([str(i) for i in row]) for row in arr]))
*********
* ** ** *
*********
*********
* ** ** *
*********
*********
* ** ** *
*********
>>> cnt_ = 1
>>> idx = [i for i in range(n) if (i // 3 ** cnt_) % 3 == 1]
>>> idx
[3,4,5]
>>> for i in idx:
for j in idx:
arr[i][j] = " "
>>> print('\n'.join([''.join([str(i) for i in row]) for row in arr]))
*********
* ** ** *
*********
*** ***
* * * *
*** ***
*********
* ** ** *
*********
만약, n=27,
>>> cnt_ = 2
>>> idx = [i for i in range(n) if (i // 3 ** cnt_) % 3 == 1]
>>> idx
[9,10,11,12,13,14,15,16,17]
코드2
def concatenate(r1, r2):
return [''.join(x) for x in zip(r1, r2, r1)]
def star10(n):
if n == 1:
return ['*']
n //= 3
x = star10(n)
top_bottom = concatenate(x, x)
middle = concatenate(x, [' '*n]*n)
return top_bottom + middle + top_bottom
print('\n'.join(star10(int(input()))))
코드2 예시
ex)
>>> n = 3
>>> n //= 3
print(n)
1
>>> x = star10(n)
x
['*']
>>> top_bottom = concatenate(x, x) # zip(['*'],['*'],['*'])
top_bottom
['***']
>>> middle = concatenate(x, [' '*n]*n)
middle
['* *']
>>> top_bottom + middle + top_bottom
['***', '* *', '***']
>>> print('\n'.join(top_bottom + middle + top_bottom))
***
* *
***
ex)
>>> n = 9
>>> n//=3 # n=3
>>> x = star10(n)
x
['***', '* *', '***'] # 바로 위 예제의 top_bottom + middle + top_bottom
>>> top_bottom = concatenate(x, x) # zip(['***', '* *', '***'] ,['***', '* *', '***'] ,['***', '* *', '***'] )
top_bottom
['*********', '* ** ** *', '*********']
>>> middle = concatenate(x, [' '*n]*n)
middle
['*** ***', '* * * *', '*** ***']
>>> top_bottom + middle + top_bottom
['*********', '* ** ** *', '*********', '*** ***', '* * * *', '*** ***', '*********', '* ** ** *', '*********']
>>> print('\n'.join(top_bottom + middle + top_bottom)
*********
* ** ** *
*********
*** ***
* * * *
*** ***
*********
* ** ** *
*********
* zip() : 각 리스트에서 같은 위치에 있는 원소들끼리 묶어줌
>>> list(zip([1,2,3],[4,5,6],[7,8,9]))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
* 2차원 배열 초기화 :
arr = [["*"]*n]*n 으로 초기화시 arr[0][0] = " "로 하면 모든 행의 0번째 모두 " "로 바뀜
https://leedakyeong.tistory.com/14
'코딩테스트 연습 > 백준' 카테고리의 다른 글
[백준-python] 10809번 : 알파벳 찾기 (6) | 2019.08.14 |
---|---|
[백준-python] 11729번 : 하노이 탑 이동 순서(hanoi top in python) (0) | 2019.08.13 |
[백준-python] 10872번 : 팩토리얼 factorial (0) | 2019.08.07 |
[백준-python] 1065번 : 한수 (0) | 2019.08.05 |
[백준-python] 4673번 : 셀프 넘버 Self Number (0) | 2019.08.05 |