[JS][백준]14891_톱니바퀴
Algorithm

[JS][백준]14891_톱니바퀴

문제 번호

 

14891번: 톱니바퀴

첫째 줄에 1번 톱니바퀴의 상태, 둘째 줄에 2번 톱니바퀴의 상태, 셋째 줄에 3번 톱니바퀴의 상태, 넷째 줄에 4번 톱니바퀴의 상태가 주어진다. 상태는 8개의 정수로 이루어져 있고, 12시방향부터

www.acmicpc.net

 

 

 

알고리즘 분류

 

문제 풀이

  구현 문제이다. 

 한 가지 어려웠던 점은 한개의 톱니바퀴가 돌아가면 다른 톱니바퀴에도 영향을 끼치게되는데 이 과정들이 동시에 일어난다는 것이다. 예를들어 1번 톱니바퀴를 돌리면 오른쪽 끝에있는 4번 톱니바퀴도 돌아갈 수 있는데, 1-2-3-4번 차례로 돌리는 것이 아니라 1-2-3-4번 톱니바퀴가 '동시에' 돌아가야 한다.

 

 우선 돌리긴 돌려야하니 시계방향, 반 시계 방향으로 톱니를 돌리는 알고리즘을 작성했다.

function turnClock(gear) {  // 반 시계 방향. <-
  let temp = [...gear];
  for (let i = 0; i < gear.length; i++) {
    gear[i] = temp[(i + 1) % gear.length];
  }
  return gear;
}
function turnRclock(gear) { // 시계 방향. ->
  let temp = [...gear];
  for (let i = 0; i < gear.length; i++) {
    gear[i] = temp[(i + gear.length - 1) % gear.length]
  }
}

 그러고 나서 생각을 해보니 '동시에' 돌려야 한다면 모든 톱니바퀴의 회전상태를 알고나서 한번에 돌리면 되겠거니 싶었다. 그럼 이제 돌리는 톱니바퀴와 방향이 주어졌을때 다른 톱니바퀴는 어느 방향으로 돌려야하는지 파악해보자.

 

 각 톱니바퀴는 오른쪽, 왼쪽에 다른 톱니바퀴가 있을 수 있으므로 양쪽 다 확인해 준다. rotate배열에 각각의 톱니바퀴가 어느 방향으로 회전하는지 저장 할 것이다.

  //각 톱니가 어디로 도는지 파악하고 모든 톱니를 한번에 돌린다.
  let rotate = new Array(4).fill(0);
  rotate[numOfGear] = way;

  // 돌리는 톱니를 기준으로 오른쪽 확인.
  for (let i = numOfGear; i < 3; i++) {
    if (gear[i][2] !== gear[i + 1][6])
      rotate[i + 1] = -1 * rotate[i];
    else
      break;
  }
  // 돌리는 톱니를 기준으로 왼쪽 확인.
  for (let i = numOfGear; i > 0; i--) {
    if (gear[i][6] !== gear[i - 1][2])
      rotate[i - 1] = -1 * rotate[i];
    else
      break;
  }

 

 각각의 톱니바퀴가 어느방향으로 회전하는지 알았다면 위에서 구현해둔 회전 알고리즘을 사용해서 톱니바퀴를 돌려주면 된다.

  // 톱니들의 회전방향을 모두 알았으니 돌린다.
  for (let i = 0; i < rotate.length; i++) {
    if (rotate[i] == 0)
      continue;
    else if (rotate[i] == -1) {
      turnClock(gear[i]);
    } else if (rotate[i] == 1) {
      turnRclock(gear[i]);
    }
  }

 

 마지막으로 각각의 톱니바퀴바다 위(12시 방향)에 있는 극에 따라서 점수를 합산해 주어야 한다.

  for(let i=0; i<gear.length; i++) {
    answer += gear[i][0] * Math.pow(2,i) ;
  }

전체 코드

/**
 * 1 2 3 4 
 * 극이 다르면 반대 방향.
 * 
 * 극이 같으면 회전 안함.
 * 1. 시계방향 회전 구현.
 * 2. 반시계방향 회전 구현.
 * 3. 각 톱니의 상태에 따라서 서로의 영향을 확인한다.
 * 4. 각 톱니는 0-7 인덱스. 0은 12시방향, 2는 오른쪽, 6은 왼쪽 이다.
 * 5. 1개의 톱니바퀴를 돌리때 다른 톱니의 회전방향까지 모두 구한다.
 * 6. 모든 톱니바퀴의 회전방향을 구하고 모든 톱니바퀴의 회전을 한번에 적용한다.
 */
function main() {
  let answer = 0;
  const input = require('fs').readFileSync('dev/stdin').toString().trim().split('\n');
  let gear = input.slice(0, 4).map(_ => _.trim().split('').map(Number));
  // 회전 횟수
  const K = +input[4].trim(); 
  // 톱니, 방향 1:시계, -1: 반시계
  const move = input.slice(5).map(_ => _.trim().split(' ').map(Number)); 

  for (let i = 0; i < move.length; i++) {
    let [numOfGear, way] = move[i];
    sol(gear, numOfGear, way)
  }
  for(let i=0; i<gear.length; i++) {
    answer += gear[i][0] * Math.pow(2,i) ;
  }
  console.log(answer)
}
function sol(gear, numOfGear, way) {
  numOfGear--;
  //각 톱니가 어디로 도는지 파악하고 모든 톱니를 한번에 돌린다.
  let rotate = new Array(4).fill(0);
  rotate[numOfGear] = way;

  // 돌리는 톱니를 기준으로 오른쪽 확인.
  for (let i = numOfGear; i < 3; i++) {
    if (gear[i][2] !== gear[i + 1][6])
      rotate[i + 1] = -1 * rotate[i];
    else
      break;
  }
  // 돌리는 톱니를 기준으로 왼쪽 확인.
  for (let i = numOfGear; i > 0; i--) {
    if (gear[i][6] !== gear[i - 1][2])
      rotate[i - 1] = -1 * rotate[i];
    else
      break;
  }
  // 톱니들의 회전방향을 모두 알았으니 돌린다.
  for (let i = 0; i < rotate.length; i++) {
    if (rotate[i] == 0)
      continue;
    else if (rotate[i] == -1) {
      turnClock(gear[i]);
    } else if (rotate[i] == 1) {
      turnRclock(gear[i]);
    }
  }
}
function turnClock(gear) {  // 반 시계 방향. <-
  let temp = [...gear];
  for (let i = 0; i < gear.length; i++) {
    gear[i] = temp[(i + 1) % gear.length];
  }
  return gear;
}
function turnRclock(gear) { // 시계 방향. ->
  let temp = [...gear];
  for (let i = 0; i < gear.length; i++) {
    gear[i] = temp[(i + gear.length - 1) % gear.length]
  }
}
main();

 

특이사항

 

 

'Algorithm' 카테고리의 다른 글

[JS][백준]10699_오늘 날짜  (2) 2022.03.28