프로그래머스_JS - 행렬 테두리 회전하기

nd098pkc·2022년 6월 10일
0

코딩테스트 준비

목록 보기
4/15
post-thumbnail

2021 Dev-Matching: 웹 백엔드 개발자 선발 테스트 문제이며 레벨 2로 구분되어있다.

문제

rows*columns크기의 숫자배열에 queries 좌표를 둘레로하여 회전시키고 회전시킬때 마다 움직인 숫자들 중 최소값을 정답배열에 넣어서 출력하면 되는 문제이다.
소소한 주의사항은 queries의 좌표값이 index가 아닌 위치값이어서 index로 활용할때는 1씩 빼줘야하는 점이 있겠다.

풀이과정

<입력>

1.행의 크기(높이) "rows"(Number)
2.열의 길이(너비) "columns"(Number)
3.회전시킬 영역들의 정보가 순서대로 담긴 "queries"(Array)

<2차원 숫자배열 만들기>

우선 입력에 배열이 들어와있는게 아니어서 직접 2차원 숫자 배열을 만들어줘야한다.
간단하게 생각하면 rows*columns 크기의 배열을 만들어주고 순서대로 숫자를 넣어주면 되겠다.

let arr = Array.from(new Array(rows),()=>[])  // 일단 행의 길이만큼 2차원배열 생성
    let num =1                                // 숫자는 1부터 시작
    for(let i=0;i<rows;i++){                  
        for(let j=0;j<columns;j++){           //[i,j] 좌표를 지시해줄 2중 반복문
            arr[i][j]=num++                   //2차원배열에 순서대로 숫자를 넣어준다
        }                                     //num을 0부터 시작해서 arr[i][j]=++num을 해줘도 결과는 같다
    }

<배열 회전시키기>

우선 특정 영역은 둘째치고 배열의 테두리를 회전시키는 것을 가정해보자
배열 회전의 방향은 시계방향으로 고정되어있고 배열의 칸을 움직이는것은 어려우니 가장 간편한 방법은 '숫자를 받을 칸'에서 '숫자를 넘겨줄 칸'의 값을 가져오는것이 될것이다.
하지만 이 방법은 순서가 매우 중요한데 위 그림과 같이 원래 2번이었던 칸에서 넘겨받을 1번을 받고 나면 값이 바뀌어버리기때문에 넘겨줄 2번이 사라지게 된다. 따라서 값을 넘겨받을 방향은 아래와 같이 시계 반대방향이어야한다.
이 방법으로 하면 끊기지 않고 테두리의 숫자들을 시계방향으로 한칸 씩 옮길 수 있다.
하지만 어떻게 하더라도 제일 처음 값을 넘겨받는 칸의 숫자는 보존할 수가 없었다. 그래서 제일 처음 값을 넘겨줄 칸의 번호를 미리 저장해두기로 했다.

이런 과정을 코드로 표현하면 다음과 같다.

function rotate (table,x1,y1,x2,y2){   //회전시킬 배열과 테두리위치 정보를 받는다.
    let LT= table[x1][y1]              //제일 처음 값을 넘겨줄 칸의 번호를 미리 저장해두겠다.

    let min = LT                       //회전과 별개로 정답은 움직이는 번호들 가운데 최소값을 저장해야하므로
                                         일단은 min에 첫번째 값을 저장해둔다
    for(let i=x1;i<x2;i++){            
        table[i][y1]=table[i+1][y1]    //y1(첫열)을 고정하고 x1행부터 x2행까지 아래로 이동하며 숫자들을 넘겨준다
        if(table[i+1][y1]<min){
            min=table[i+1][y1]         //그리고 이 값이 기존 min보다 작으면 최소값을 갱신
        }
    }
    for(let i=y1;i<y2;i++){            
        table[x2][i]=table[x2][i+1]    //x2(맨밑줄)을 고정하고 y1열부터 y2열까지 오른쪽으로 이동해가며 숫자를 넘겨준다
        if(table[x2][i+1]<min){        
            min=table[x2][i+1]         //min 갱신부분
        }
    }
     for(let i=x2;i>x1;i--){
        table[i][y2]=table[i-1][y2]
        if(table[i-1][y2]<min){
            min=table[i-1][y2]
        }
    }
    for(let i=y2;i>y1;i--){
        table[x1][i]=table[x1][i-1]
        if(table[x1][i-1]<min){
            min=table[x1][i-1]
        }
    }
    table[x1][y1+1]=LT                  // 저장해둔 값이 들어갈 칸에 저장해둔 값을 넣어준다

    return min                          //회전과 별개로 이동한 숫자들 중 최소값을 return
}

이제 queries의 정보를 토대로 회전시키면서 회전시킬때마다 최소값을 정답배열에 넣어주면 되겠다

<rotate 활용>

function solution(rows, columns, queries) {
    let arr = Array.from(new Array(rows),()=>[]) 
    let num =1
    for(let i=0;i<rows;i++){
        for(let j=0;j<columns;j++){
            arr[i][j]=num++
        }
    }                                   //여기까지가 숫자배열 만들기
  
    let answer=[]                       //정답배열 초기화
    for(let i=0;i<queries.length;i++){  //쿼리들을 순회하면서
        answer.push(rotate(arr,queries[i][0]-1,queries[i][1]-1,queries[i][2]-1,queries[i][3]-1))
    }        //만든 숫자배열과 각 쿼리의 x1,y1,x2,y2를 넣고 return되는 각 회전마다의 최소값을 정답배열로 넘겨주면 되는데
             //query의 값들이 index가 아니어서 각 값마다 -1을 해서 넣어줘야한다.
    return answer
}

조금 노가다 느낌이 나는 문제였던것 같지만 나름 생각해볼 부분도 있었고 예전에는 손댈 생각도 못했을것 같은데 나름 수월하게 풀어서 성취감이 있었다.
다만 이것보다 더 스마트하게 풀 수 있는 방법도 있지 않을까 하는 아쉬움도 남는다.

전체코드

function rotate (table,x1,y1,x2,y2){
    let LT= table[x1][y1]
   
    let min = LT
   
    for(let i=x1;i<x2;i++){
        table[i][y1]=table[i+1][y1]
        if(table[i+1][y1]<min){
            min=table[i+1][y1]
        }
    }
    for(let i=y1;i<y2;i++){
        table[x2][i]=table[x2][i+1]
        if(table[x2][i+1]<min){
            min=table[x2][i+1]
        }
    }
     for(let i=x2;i>x1;i--){
        table[i][y2]=table[i-1][y2]
        if(table[i-1][y2]<min){
            min=table[i-1][y2]
        }
    }
    for(let i=y2;i>y1;i--){
        table[x1][i]=table[x1][i-1]
        if(table[x1][i-1]<min){
            min=table[x1][i-1]
        }
    }
    table[x1][y1+1]=LT
   
    return min
}

function solution(rows, columns, queries) {
    let arr = Array.from(new Array(rows),()=>[])
    let num =1
    for(let i=0;i<rows;i++){
        for(let j=0;j<columns;j++){
            arr[i][j]=num++
        }
    }
    let answer=[]
    for(let i=0;i<queries.length;i++){
        answer.push(rotate(arr,queries[i][0]-1,queries[i][1]-1,queries[i][2]-1,queries[i][3]-1))
    }
    return answer
}
profile
늦게배운 코딩이 무섭다

0개의 댓글