본문 바로가기

Python/code problem

[sw expert academy] 1954. 달팽이 숫자

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

 

SW Expert Academy

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

swexpertacademy.com

 

이 문제 쉽지 않다..

 

먼저 n=4일 때를 기준으로 먼저 코딩을 했다.

def puzzle():
    for i in range(4):
        for j in range(4):
            print(arr[i][j],end=" ")
        print(" ")

arr = []
for i in range(4):
    arr.append([0 for t in range(4)])

on =1
for i in range(4):
    arr[0][i] = on
    on+=1

for i in range(3):
    arr[i+1][3] = on
    on+=1

for i in range(3):
    arr[3][2-i]= on
    on+=1

for i in range(2):
    arr[2-i][0] = on
    on+=1

for i in range(2):
    arr[1][1+i]=on
    on+=1

for i in range(1):
    arr[2+i][2] = on
    on+=1

for i in range(1):
    arr[2][1-i] = on
    on+=1
puzzle()

가장 먼저 함수 puzzle을 정의했다.
이 함수는 [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] (예시)를
0 0 0 0
0 0 0 0 
0 0 0 0
0 0 0 0
으로 바꿔준다.
참고로 이 함수는 입력값과 결괏값이 없는 함수다.

그 다음 arr 라는 빈 리스트를 정의해주었다.
이 문제를 이중 인덱싱으로 풀어나갈 것이기 때문에 append 함수를 이용하여
arr = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
기초 리스트를 만들었다.

 

달팽이 같은 표는 n=4를 기준으로 1~16의 수들을 나열해 놓은 것이다.

따라서 on의 초기값은 1로 설정했다.

 

그리고 여기서 난 저 달팽이표를 하나의 보드게임 판처럼 생각했을 때

4,3,3,2,2,1,1 이렇게 움직인다는 것을 발견했다.

 

그 다음 arr = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]를 

arr = [[1,2,3,4], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] 로 만들어주었다.

arr[0][j]에서 j만 바뀌므로 for문으로 구현해주었다.

 

같은 원리로 나머지 것들도 연산자를 이용하여 구현해주었다.

 

이렇게 미리 노트에다가 하나하나 써보고 vsc를 통해 구현했다.

이 굿노트 템플릿은 맨 아래에 첨부된 링크에서 구매했다.

 

 

이제는 일반화를 시켜줄 차례다.

난 오른쪽으로 가는 함수, 왼쪽으로 가는 함수, 아래로 가는 함수, 위로 가는 함수를 하나하나 만들어 줄 생각이다.

 

그래서 먼저 오른쪽으로 가는 함수를 만들려고 했다.

arr = []
for i in range(4):
    arr.append([0 for t in range(4)])

on= 1

num_r = 0
def go_r(d):
    for i in range(d):
        arr[num_r][i+num_r] = on
        on+=1
    num_r +=1
print(go_r(4))

마지막 print문은 test 프린트문이다.

근데 이렇게 했더니 

UnboundLocalError: local variable 'on' referenced before assignment 

라는 에러가 떴다.

 

이 에러를 그대로 구글에 찾아봤더니 

전역변수(global variable)를 지역 변수로 호출했기 때문에 에러가 난 것이라고 한다.
전역변수를 지역범위(local scope)에서 사용하고 싶으면 지역 영역(예를 들면 함수 내)에서 global 표현을 사용하면 된다.

 

그래서 global 선언을 해줬다.

arr = []
for i in range(4):
    arr.append([0 for t in range(4)])

on= 1

num_r = 0
def go_r(d):
    global on
    global num_r
    for i in range(d):
        arr[num_r][i+num_r] = on
        on+=1
    num_r +=1
    return arr

print(go_r(4))

 

다른 함수들도 만들어야겠다.

def puzzle():
    for i in range(4):
        for j in range(4):
            print(arr[i][j],end=" ")
        print(" ")

arr = []
for i in range(4):
    arr.append([0 for t in range(4)])

N = 4 #이건 바꿔야하는 것
on= 1

num_r = 0
num_d = 0
num_l = 0
num_u = 0

def go_r(d):
    global on
    global num_r
    for i in range(d):
        arr[num_r][i+num_r] = on
        on+=1
    num_r +=1
    return arr

def go_d(d):
    global on
    global num_d
    for i in range(d):
        arr[i+1+num_d][N-1-num_d] = on
        on +=1
    num_d +=1
    return arr

def go_l(d):
    global on
    global num_l
    for i in range(d):
        arr[N-1-num_l][N-2-num_l-i] = on
        on +=1
    num_l +=1
    return arr

def go_u(d):
    global on
    global num_u
    for i in range(d):
        arr[N-2-num_u-i][num_u] = on
        on +=1
    num_u +=1
    return arr

go_r(4)
go_d(3)
go_l(3)
go_u(2)

go_r(2)
go_d(1)
go_l(1)
puzzle()

 

1 2 3 4  
12 13 14 5  
11 16 15 6
10 9 8 7

 

이렇게 출력된다.

n=4일 때 기준 일단 성공이다.

 

자 이제 4,3,3,2,2,1,1 을 함수에 넣어주는 일반화 함수를 세워주자.

 

이므로 이것을 이용해 식을 세워주겠다.

 

go_r(N)

for i in range(N-1,0.-2):
    go_d(i)
    go_l(i)
    if i==1:
        break
    go_u(i-1)
    go_r(i-1)
    if i==2:
        break

먼저 N으로 arr의 첫번째 리스트를 쫘라락 채워주고

아래, 왼, 위, 오 순으로 계속 함수를 진행시켜주는 것이다.

 

(아래, 왼)은 항상 한 세트고, (위,오른) 은 항상 한 세트다.

아래, 왼 이 실행된 후 i==1이면 멈춰야 한다.(이때 N은 홀수)

아래,왼, 위, 오른 이 실행된 후 i==2이면 멈춰야 한다. (이때 N은 짝수)

 

완성된 코드는 다음과 같다.

  • 56,672kb메모리
  • 132ms실행시간
def puzzle():
    for i in range(N):
        for j in range(N):
            print(arr[i][j],end=" ")
        print(" ")

def go_r(d):
    global on
    global num_r
    for i in range(d):
        arr[num_r][i+num_r] = on
        on+=1
    num_r +=1
    return arr

def go_d(d):
    global on
    global num_d
    for i in range(d):
        arr[i+1+num_d][N-1-num_d] = on
        on +=1
    num_d +=1
    return arr

def go_l(d):
    global on
    global num_l
    for i in range(d):
        arr[N-1-num_l][N-2-num_l-i] = on
        on +=1
    num_l +=1
    return arr

def go_u(d):
    global on
    global num_u
    for i in range(d):
        arr[N-2-num_u-i][num_u] = on
        on +=1
    num_u +=1
    return arr



T = int(input())
for t in range(1,T+1):
    on= 1
    num_r = 0
    num_d = 0
    num_l = 0
    num_u = 0

    N=int(input())
    if 1<=N<=10:
        arr = []
        for i in range(N):
            arr.append([0 for t in range(N)])

        go_r(N)
        for i in range(N-1,0,-2):
            go_d(i)
            go_l(i)
            if i==1:
                break
            go_u(i-1)
            go_r(i-1)
            if i==2:
                break

        print("#{}".format(t))
        puzzle()

N의 범위도 포함시켜줬다.

r,d,l,u 는 각각 right,down,left,up 이다.

 


진짜 ㅋㅋㅋㅋ 구현하기 어려운 문제다..

3시간정도 걸린 듯...

 

그래도 모범답안 안 보고 혼자 열심히 푼 문제라 뿌듯하다.

예시 -> 일반화

과정으로 풀었는데 이렇게 푸는게 오래 걸리긴 해도 정확하게 답을 도출해낼 수 있어서 좋다..

 

 

 

-손코딩 노트

https://nelna.shop/shop_view/?idx=4476 

 

[에듀앳홈] 손코딩 노트 : 낼나샵

굿노트, 노타빌리티, 노트쉘프 유저의 나다운 내일을 위한 디지털 문방구

nelna.shop

 

 

-UnboundLocalError: local variable ' ' referenced before assignment

 

https://korbillgates.tistory.com/98

 

https://wotres.tistory.com/entry/python-error-%ED%95%B4%EA%B2%B0%EB%B2%95-local-variable-df-referenced-before-assignment

 

https://docs.python.org/3/reference/simple_stmts.html#the-global-statement