본문 바로가기

Python/code problem

[sw expert academy] 1961. 숫자 배열 회전

https://swexpertacademy.com/main/main.do

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

(12/23일에 푼 문제다;; ㅋㅋ)

 

문제를 첨 보자마자 헉 했다..

이걸 어떻게 풀지..

그래서 가장 먼저 모범답안을 봤다.

 

내 기준 모범답안은 실행시간이 가장 짧은 것이었다.

아래 답안은 samsungsh 님의 답안이다.

  • 51,668 kb메모리
  • 107 ms실행시간

사실 이걸 봐도 바로 아..! 하고 느낌이 오지 않는다.

특히 for문 두개의 중첩은 더더욱..

 

그래서 메모에 하나씩 써가며 분석했다.

위에 코드의 해설을 다음과 같다.(예시로 n=3인 경우를 들었다)

 

먼저 변수 T를 입력받고 T 범위만큼의 for문을 돌린다.(test case)
행렬의 길이인 n을 받는다.
arr라는 빈 리스트를 만든다.
dir이라는 리스트는 90,180,270 원소가 차례대로 배열되어있는 리스트이다.
dir을 이렇게 설정해준 이유는 dir 내부의 원소들을 상대로 for문을 돌렸을 때 90,180,270을 차례로 실행시키기 위해서다.(for case in dir)
그 다음 for _ in range(n) … 은 

1 2 3
4 5 6
7 8 9

이렇게 입력된 값들을 (예시)

arr = [['1','2','3'],['4','5','6'],['7','8','9']]

이렇게 만들어준다.

for i in range(n)은 한줄 한줄을 만들어주는 for문이다.

따라서 이 for문에 종속되어 있는 명령문들은 

741 987 369
852 654 258
963 321 147

각각의 한줄을 만드는데 필요한 명령문들이다.

다시 말해 i=0이면 첫번째 문장이 만들어진다.

result는 출력되는 문장의 초기값이다. 

for case in dir: 이 뒤에 부터 아까 dir = [90,180,270]으로 설정한 이유가 드러난다.

if case==90: 이면

7 4 1
8 5 2
9 6 3

첫번째 7 4 1 만 보자.

숫자 배열이 이렇게 된다.

'741'  = arr[2][0] + arr[1][0] + arr[0][0] 

여기서 arr[j][0] 

j 자리만 바뀐다. 

'852' = arr[2][1] + arr[1][1] + arr[0][1]

여기서도 arr[j][1]

j 자리만 바뀐다.

'963'  = arr[2][2] + arr[1][2] + arr[0][2] 

여기서 arr[j][2]

j 자리만 바뀐다. 

그래서 두번째 for문의 변수?(바뀌는 값. 이걸 변수라고 표현하는 게 맞는지는 모르겠다..)가 j인 것이다.

첫번째 변수는 arr[][i] 0,1,2 이렇게 변하는 i 이다.

 

이걸 일반화하면 i는 0,1,2...n-1 이렇게 가고 j는 n-1,n-2...1,0 이렇게 가야한다.

따라서 

for j in range(n-1,-1,-1):
    result +=arr[j][i]

이렇게 된 것이다.

같은 방식으로

case = 180, case 270 일 때에도 이러한 연산을 이용해 1차로 바뀌는 값, 2차로 바뀌는 값을 확인하여 그 식을 구할 수 있다. 

 

이렇게 모범답안을 풀이해보았다.

이젠 내가 모범답안을 보지 않고 직접 코드를 짜볼 차례다.

 

모범 답안에서는 

10
3
1 2 3
4 5 6
7 8 9

을 입력하면(통으로 복사해서 터미널에 붙여넣기 함)

10
#1
3
1 2 3
4 5 6
7 8 9
741 987 369
852 654 258
963 321 147

터미널에 이렇게 표현되었다..(입력값과 출력값이 모두 섞여있는 형태)

근데 난 이게 좀 맘에 안 들었다.

 

그래서 이걸 좀 보완해서 아래와 같이 코드를 짰다.

  • 56,692kb메모리
  • 129ms실행시간
T= int(input())

for t in range(1,T+1):
    N = int(input())
    ang = [90,180,270]
    num_lst = []
    for n in range(N): #리스트 만들기
        num_lst.append(input().split())
    for n in range(N): #n번째 줄
        if n==0:
            print("#{}".format(t))
        stng = ""
        for a in ang:
            if a==90:
                for j in range(N-1,-1,-1):
                    stng+= num_lst[j][n]
                stng+=" "

            elif a==180:
                for j in range(N-1,-1,-1):
                    stng+= num_lst[N-1-n][j]
                stng+=" "
            
            elif a==270:
                for j in range(0,N):
                    stng+= num_lst[j][N-1-n]
        print(stng)

모범답안과 전체적인 틀은 비슷하다.

 

터미널에는 이렇게 나온다.

10
3
1 2 3
4 5 6
7 8 9
#1
741 987 369
852 654 258
963 321 147

#1부터는 출력값이고 그 위에는 입력값이다.

 

 

진짜 쉽지 않은 문제였다.

이것저것 복잡한 연산이 정말 머리를 싸매게 만든다.

이런 문제에 익숙해지는 날이 오기를 바란다.