[JS][백준]16926_배열 돌리기1
Algorithm/BaeKJoon

[JS][백준]16926_배열 돌리기1

문제 번호

 

16926번: 배열 돌리기 1

크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다. A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ← A[1][5] ↓ ↑ A[2][1] A[2][2] ← A[2][3] ← A[2][4] A[2][5]

www.acmicpc.net

 

 

 

알고리즘 분류

문제 풀이

 구현 문제이다. 언젠가 풀어본 거 같지만 안 풀려있었다.

주어진 배열을 회전해야 하는데 위쪽 부분, 왼쪽 부분, 아래쪽 부분, 오른쪽 부분 이렇게 4 부분으로 나누어서 보기로 했다.

제일 밖에 있는 4개의 영역이 회전하고 크기를 줄여가면서 똑같이 회전하면 된다.

 

우선 윗부분을 살펴본다. 오른쪽에 있는 숫자를 왼쪽에서 받아야 한다. 그런데 가장 오른쪽에 있는 A[1][5]는 오른쪽에서 오는 것이 아니라 한 칸 아래 있는 숫자가 온다. 

 

 

그다음 왼쪽 부분을 살펴보자. 위쪽에 있는 숫자를 아래쪽에서 받아야 한다. 그런데 가장 위에 있는 A[1][1]은 위쪽에서 오는 것이 아니라 오른쪽에 있는 숫자가 온다.

 남아있는 아랫부분, 오른쪽 부분 역시 1개의 칸은 나머지 칸들과 다르게 숫자를 받아와야 한다. 

 

 그래서 각 4개의 부분의 숫자를 변경할 때 시작하는 부분을 한 칸 띄워놓고 시작하기로 했다. limit은 한 단계씩 작아지는 사각형을 표현하기 위함이다. 예를 들어 윗부분의 경우를 살펴보자. 

  for (let limit = 0; limit < Math.floor(min / 2); limit++) {

    // 윗줄.
    for (let j = (M - 2) - limit; j >= 0 + limit; j--) {
      temp[0 + limit][j] = arr[0 + limit][j + 1];
    }

 윗 부분의 가장 오른쪽 칸은 A[1][5]이지만 위의 for문은 A[1][4]부터 값을 채운다. 왜냐하면 A[1][5]를 제외한 나머지 값들은 오른쪽에서 값을 받아온다는 공통된 방식을 취하지만 A[1][5]'만' 아래쪽에서 값을 받아오는 방식을 취하기 때문이다. 

그럼 A[1][5]는 어떻게 값을 변경할 것인가?

 

오른쪽 부분의 값을 변경할 때를 살펴보자. 오른쪽 부분역시 A[4][5]를 제외한 모든 값들은 아래에서 위로 값을 받아온다. 이때 윗부분을 변경할때 제외했던 A [1][5]의 값이 변경된다. 

    // 오른쪽.
    for (let j = (N - 2) - limit; j >= 0 + limit; j--) {
      temp[j][(M - 1) - limit] = arr[j + 1][(M - 1) - limit];
    }

 

결과적으로 각 4 부분의 값을 변경할 때 시작지점을 1칸씩 띄워 놓고 시작했는데 이때 변경되지 않는 '모서리'들은 다른 부분을 변경할때 채워지게 된다.

 

그림으로 보면 이런느낌.

 

전체 코드

const input = require('fs').readFileSync('dev/stdin').toString().trim().split('\n');
const [N, M, R] = input[0].split(' ').map(Number);
let arr = input.slice(1).map(_ => _.trim().split(' ').map(Number));

function main() {
  let answer = '';

  let ret = [...arr];  
  for(let i=0; i<R; i++) {    
    ret = routate(arr);
    arr = [...ret];
  //  console.log(answer.join('\n'))
  // console.log("done")
  }
  ret.forEach(e => {
    answer += e.join(' ') + '\n';
  })
  
  return console.log(answer.trim())
}
function routate(arr) {  // 90000 000
  let min = Math.min(N, M)

  // 나눗셈으로 밀기.
  // 각 모서리 시작점은 다른애가 채워줌.
  let temp = new Array(N).fill(null).map(_ => new Array(M).fill(0));
  for (let limit = 0; limit < Math.floor(min / 2); limit++) {

    // 윗줄.
    for (let j = (M - 2) - limit; j >= 0 + limit; j--) {
      temp[0 + limit][j] = arr[0 + limit][j + 1];
    }
    // 왼쪽.
    for (let j = 1 + limit; j < N - limit; j++) {
      temp[j][0 + limit] = arr[j - 1][0 + limit];
    }
    // 아래
    for (let j = 1 + limit; j < M - limit; j++) {
      temp[(N - 1) - limit][j] = arr[(N - 1) - limit][j - 1];
    }
    // 오른쪽.
    for (let j = (N - 2) - limit; j >= 0 + limit; j--) {
      temp[j][(M - 1) - limit] = arr[j + 1][(M - 1) - limit];
    }

  }
  // temp.forEach(e => {
  //   console.log(e.join(' '))
  // })

  return temp;
}
main();

특이사항

 사각형이 줄어드는 것과 사각형을 4개의 영역으로 잘 나눴다면 어려움 없이 풀 수 있었다.

 

'Algorithm > BaeKJoon' 카테고리의 다른 글

[JS][백준]1166_선물  (0) 2022.07.05
[JS][백준]16938_캠프 준비  (0) 2022.07.05
[JS][백준]16719_ZOAC  (0) 2022.06.15
[JS][백준]16206_롤케이크  (0) 2022.06.15
[JS][백준]1167_트리의 지름  (0) 2022.06.09