코딩테스트 연습/백준

[백준-python] 2447번 : 별 찍기-10

슈퍼짱짱 2019. 8. 7. 13:19
반응형

https://www.acmicpc.net/problem/2447

 

2447번: 별 찍기 - 10

첫째 줄에 N이 주어진다. N은 항상 3의 제곱꼴인 수이다. (3, 9, 27, ...) (N=3k, 1 ≤ k < 8)

www.acmicpc.net


코드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] 2 dimension list

python에서 2차원 이상의 list를 초기화 할 땐 >>> n = 9 >>> arr = [[0]*n for _ in range(n)] 과 같이 해야한다. 그 이유는 만약, >>> arr = [[0]*n]*n 으로 초기화 할 경우 n개의 [0]*n은 모두 같은 객체로 인..

leedakyeong.tistory.com

 

반응형