프로그래머스 파이썬 기초 트레이닝 :: 정수를 나선형으로 배치하기 (*)

     



      

              


    문제 설명 

    프로그래머스 URL

    https://school.programmers.co.kr/learn/courses/30/lessons/181832



    프로그래머스 코딩 카테고리 

    코딩 기초 트레이닝

    Day 25 - 정수를 나선형으로 배치하기 

    Lv.0



    문제 내용 

    양의 정수 n이 매개변수로 주어집니다. n × n 배열에 1부터 n2 까지 정수를 인덱스 [0][0]부터 시계방향 나선형으로 배치한 이차원 배열을 return 하는 solution 함수를 작성해 주세요.




    넘나 어려운 문제다.. 




    -----------------------------------


    나선형으로 도는거기 때문에, 시계방향으로 돈다. 

    방향은    U 이렇게 고정이 되어있다. 


    4가지 경우에 따른 방향 설정

    dir = R(1) → D(2) → L(3) → U(4)

    def solution(n):
        answer = [[0]*n for i in range(n)]
        x, y = 0, 0
        
        dir = 'r'		#dir로 방향조정 : r, d, l, u
        
        if n == 1:
            return [[1]]
        
        for i in range(1, n*n+1):
            answer[x][y] = i 
            if dir == 'r':
                y += 1
                if y == n-1 or answer[x][y+1] != 0:
                    dir = 'd'
            elif dir == 'd':
                x += 1
                if x == n-1 or answer[x+1][y] != 0:
                    dir = 'l'
            elif dir == 'l':
                y -= 1
                if y == 0 or answer[x][y-1] != 0:
                    dir = 'u'
            elif dir == 'u':
                x -= 1
                if x == n-1 or answer[x-1][y] != 0:
                    dir = 'r'
                    
        return answer


    1) 1 X 1 배열일때  

    if n == 1:
        return [[1]]

    n이 1일때를 따로 지정해주지 않으면 테스트13에서 "실패 (런타임 에러)"로 뜸

    그 이유는 x, y = 0, 0으로 선언하면 반복문을 시작한 r 방향때 부터 문제가 생긴다.


    if dir == 'r':
        y += 1
        if y == n-1 or answer[x][y+1] != 0:
            dir = 'd'

    y+=1 을 하는데 arr[0][0]을 입력하지않고, 바로 arr[0][1] 값부터 넣는데, 

    y+=1 을 수행한 이후기 때문에 if y ==n-1 이 항상 참이 되기 때문이다. 

    그래서 arr[0][0] 이 입력되지도 않아도 r 방향의 if문이 참이 되서 런타임 에러뜸  



    2) r : 행은 그대로고, 열만 오른쪽으로 이동  

    for i in range(1, n*n+1):
        answer[x][y] = i 
    
        if dir == 'r':
            y += 1
            if y == n-1 or answer[x][y+1] != 0:
                ir = 'd'

    행은 그대로이기 때문에 answer[x][y] 에서 x축은 그대로고, y축만 +1 씩 이동 

    이동한 y축이 배열의 끝까지 도착했을때나, 이미 answer 다음자리에 값이 들어가있으면 방향전환


    3) d : 열은 그대로고, 행만 위에서 아래로 이동  

    elif dir == 'd':
        x += 1
        if x == n-1 or answer[x+1][y] != 0:
            dir = 'l'

    열은 그대로이기 때문에 answer[x][y] 에서 y축은 그대로고, x축만 +1 씩 이동 

    동작이 멈추는 원리는 r때랑 동일


    4) l : 행은 그대로고, 열만 오른쪽에서 왼쪽으로 이동  

    elif dir == 'l':
        y -= 1
        if y == 0 or answer[x][y-1] != 0:
            dir = 'u'

    행은 그대로이기 때문에 answer[x][y] 에서 x축은 그대로고, y축만 -1 씩 이동 


    5) u : 열은 그대로고, 행만 밑에서 위로 이동  

    elif dir == 'u':
        x -= 1
        if x == 0 or answer[x-1][y] != 0:
            dir = 'r'

    열은 그대로이기 때문에 answer[x][y] 에서 y축은 그대로고, x축만 -1 씩 이동 




    방향전환을 숫자로 지정해도됨 (원리는 동일) 

    def solution(n):
        arr = [[0]*n for i in range(n)]
        x, y = 0, 0 
    
        mode = 1	#mode로 방향조정 : R(1)-> D(2) -> L(3) -> U(4)
        
        if n == 1:
            return [[1]]
        
        for i in range(1, n*n+1):
            arr[x][y] = i
            if mode%4 == 1:
                y+=1
                if y == n-1 or arr[x][y+1] != 0:		
                    mode+=1
            elif mode%4 == 2:
                x+=1
                if x == n-1 or arr[x+1][y] != 0:
                    mode+=1
            elif mode%4 == 3:
                y-=1
                if y == n-1 or arr[x][y-1] != 0:
                    mode+=1
            elif mode%4 == 0:
                x-=1
                if x == n-1 or arr[x-1][y] != 0:
                    mode+=1
        return arr



    -----------------------------------


       U 순환하는건 고정이고, 과정마다 x축과 y축의 인덱스 변화를 표현하면 이렇다. 

    x축은 R : 변화없음  D : +1씩 증가  L : 변화없음  U : -1씩 감소 

    y축은 R : +1씩 증가  D : 변화없음  L : -1씩 감소  U : 변화없음 

    이거를 배열로 표현하면 x축 = [0, 1, 0, -1], y축 = [1, 0, -1, 0]


    x, y 축 배열을 설정 

    x축 y축 배열을 활용해서 인덱스를 만듬  

    def solution(n):
        answer = [[0]*n for _ in range(n)]
        dx=[0, 1, 0, -1]
        dy=[1, 0, -1, 0]
        x, y=0, 0
        answer[x][y] = 1
        k = 2
        while k <= n*n:
            for i in range(4):
                while True:
                    nx = x + dx[i]
                    ny = y + dy[i]
                    
                    if nx>=n or ny>=n or nx<0 or ny<0 or answer[nx][ny]!=0:
                        break
                    else:
                        answer[nx][ny] = k
                        x = nx
                        y = ny
                        k += 1
        return answer


    1) 1 X 1 배열일때  

    dx=[0, 1, 0, -1]
    dy=[1, 0, -1, 0]
    x, y = 0, 0

    이렇게 선언을 하고 반복문을 했을때 

    제일 첫번째 수가 answer[0+0][1+0] 이렇게 되서, 이 코드 또한 answer[0][0]은 건너뛰기가 된다. 

      

    answer[x][y]=1

    그래서 answer[0][0] 값을 이렇게 지정해줘도된다. 



    2) 세개의 반복문  

    while k <= n*n:
        for i in range(4):
            while True:
                nx = x + dx[i]
                ny = y + dy[i]
                    
                if nx>=n or ny>=n or nx<0 or ny<0 or answer[nx][ny]!=0:
                    break
                else:
                    answer[nx][ny] = k
                    x = nx
                    y = ny
                    k += 1

    ① 반복문 : while k <= n*n:

    k 값이 2부터 시작해 n*n 배열을 다 채울때까지 반복됨


    ② 반복문 : for i in range(4):

    x축, y축 배열의 방향이 4개라서 4번 반복한다. 

    우, 하, 좌, 상 순서로 이동하기 위한 방향을 나타낸다 


    ③ 반복문 : while True:

    ②의 for문에서 방향을 정했으면, 그 한쪽 방향으로 계속 이동하는 무한 루프이다. 

    다음 배열 인덱스에 값이 이미 차있거나, 배열의 경계를 벗어날려고 하면 반복문을 종료하고 다음 방향으로 전환한다. 


    while True:
        nx = x + dx[i]
        ny = y + dy[i]
                    
        if nx>=n or ny>=n or nx<0 or ny<0 or answer[nx][ny]!=0:
            break
        else:
            answer[nx][ny] = k
            x = nx
            y = ny
            k += 1
    if문으로 값이 이미 차있거나, 배열의 경계를 넘었을때 while True 문을 종료시키고 방향을 전환시킨다. 

    else문에서는 인덱스 값에 k를 저장시킨다. 

    다음 반복문이 돌때 x, y 값을 이어가기 위해서 x, y = nx, ny로 선언 



    -----------------------------------



    위의 코드에서는 while, for문을 사용해서 x축 y축 배열의 인덱스를 옮겨갔는데 

    반복문 대신 dir의 숫자를 활용해서 인덱스에 접근을 할 수 있다. 

    x, y 축 배열 인덱스를 활용

    반복문을 최소화 할 수 있음   

    def solution(n):
        dx = [0, 1, 0, -1]
        dy = [1, 0, -1, 0]
        x, y = 0, -1
    
        arr = [[0] * n for _ in range(n)]
        k = 1
        dir = 0
        while k <= n**2:
            nx = x + dx[dir]
            ny = y + dy[dir]
            if 0 <= nx < n and 0 <= ny < n and not arr[nx][ny]:
                arr[nx][ny] = k
                k += 1
                x, y = nx, ny
            else:
                dir = (dir + 1) % 4
    
        return arr


    1) 1 X 1 배열일때  

    dx = [0, 1, 0, -1]
    dy = [1, 0, -1, 0]
    x, y = 0, -1

    x, y = 0, -1 로 선언을 했기때문에 

    answer[0+0][1-1] = answer[0][0] 값 부터 시작을 한다. 

    그래서, 이렇게 x, y를 선언하면 별도로 answer[0][0]일때 값을 주지 않더라도 테스트 13에서 런타임 에러가 나지않음


    while k <= n**2:
        nx = x + dx[dir]
        ny = y + dy[dir]
        if 0 <= nx < n and 0 <= ny < n and not arr[nx][ny]:
            arr[nx][ny] = k
            k += 1
            x, y = nx, ny
        else:
            dir = (dir + 1) % 4

    dir = (dir + 1) % 4 로 방향을 전환하기때문에 방향을 전환해주는 for문 - range(4)가 필요없게된다. 

    그리고, if문에서 0 <= nx < n and 0 <= ny < n and not arr[nx][ny] 배열 범위가 넘어가지 않고 값이 0일때를 조건문 걸어둘 수 있다.

    같은 의미 : nx < n and ny < n and nx >= 0 and ny >= 0 and answer[nx][ny] == 0

    훨씬 코드를 간결하게 쓸 수 있어진다.. 





    -----------------------------------







    이동을 하는 배열을 이차원 배열로 둬서, x축 y축을 하나의 배열에서 수행할 수도 있다. 

    x, y 축 2차원 배열

    x, y축을 나타내는 2차원 배열과 방향을 조절하는 m 변수  

    def solution(n):
        answer = [[None for j in range(n)] for i in range(n)]
        move = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        x, y, m = 0, 0, 0
        for i in range(1, n**2 + 1):
            answer[x][y] = i  
            if x + move[m][0] >= n or y + move[m][1] >= n or answer[x + move[m][0]][y + move[m][1]]:
                m = (m + 1) % 4
            x = x + move[m][0]
            y = y + move[m][1] 
        return answer


    answer[x][y]로 값부터 넣은 뒤에 

    if문으로 배열 인덱스 범위, 배열 값 체크한 뒤에 방향을 전환한다. 

    입력 가능한 상태면 move 2차원배열의 인덱스를 더해서 answer[x][y] 인덱스를 변화시킴 












    댓글

    이 블로그의 인기 게시물

    [KT 에이블스쿨 - IT 트랜드] 국내외 AI 관련 규제

    KT 에이블스쿨 : IT 인프라 (1일차~5일차) 공부 정리

    KT 에이블스쿨 : 핀테크 아이디어 공모전