백준 15787 / 기차가 어둠을 헤치고 은하수를 / JS

Jihoo·2021년 9월 15일
0

Algorithm

목록 보기
12/16

https://www.acmicpc.net/problem/15787

구현

아래의 각 명령은 비트연산으로 구현할 수 있습니다.

1. i x : i번째 기차에(1 ≤ i ≤ N) x번째 좌석에(1 ≤ x ≤ 20) 사람을 태워라. 이미 사람이 타있다면 , 아무런 행동을 하지 않는다.
2. i x : i번째 기차에 x번째 좌석에 앉은 사람은 하차한다. 만약 아무도 그자리에 앉아있지 않았다면, 아무런 행동을 하지 않는다.
3. i : i번째 기차에 앉아있는 승객들이 모두 한칸씩 뒤로간다. k번째 앉은 사람은 k+1번째로 이동하여 앉는다. 만약 20번째 자리에 사람이 앉아있었다면 그 사람은 이 명령 후에 하차한다.
4. i : i번째 기차에 앉아있는 승객들이 모두 한칸씩 앞으로간다. k번째 앉은 사람은 k-1 번째 자리로 이동하여 앉는다. 만약 1번째 자리에 사람이 앉아있었다면 그 사람은 이 명령 후에 하차한다.

1번 명령은 'x번째 비트의 값을 1로 변경한다'라고 해석할 수 있습니다. 해당 비트연산은 'binary | (1 << x)'을 이용하면 됩니다.
(비트연산에 관한 자세한 설명은 '비트마스킹'에 관한 검색을 부탁드립니다.)

2번 명령은 'x번째 비트의 값을 0으로 변경한다.'라고 해석하면, 'binary & ~(1 << x)'을 이용할 수 있습니다.

3번은 >>, 4번은 <<를 사용합니다.

위의 구현대로 M번의 명령을 수행한 이후 중복 제거는 Set()객체를 이용했습니다.

사실 비트연산을 잘 몰라서 억지로 써보려고 노력한 문제인데요. 채점현황 보니까 훨씬 짧게 구현하신 분들이 많아서 더 좋은 풀이들이 많을 것 같아요. 그래도 javascript로 공개된 코드가 몇 개 없어서 올립니다. '통과된 코드'라는 점에서만 참고해주세요..

const filePath = process.platform === 'linux' ? '/dev/stdin' : './input.txt';
const input = require('fs')
  .readFileSync(filePath)
  .toString()
  .trim()
  .split('\n');
const tmp = input[0].trim().split(' ');
const N = Number(tmp[0]);
const M = Number(tmp[1]);

// 0번부터 N-1번까지의 기차
const train = Array.from({ length: N }, () => 0);

// M번의 명령 실행
for (let k = 1; k <= M; k++) {
  const tmp = input[k]
    .trim()
    .split(' ')
    .map((x) => Number(x));
  const order = tmp[0];
  const i = tmp[1] - 1;
  if (order === 1) {
    // x번째 비트의 값을 1로 변경합니다.
    const x = tmp[2];
    train[i] = (`0b${train[i]}` | (1 << (20 - x))).toString(2);
  } else if (order === 2) {
    // x번째 비트의 값을 0으로 변경합니다.
    const x = tmp[2];
    train[i] = (`0b${train[i]}` & ~(1 << (20 - x))).toString(2);
  } else if (order === 3) {
    // >>
    const target = train[i];
    train[i] = (`0b${target}` >> 1).toString(2);
    const targetStr = String(train[i]);
    if (targetStr.length > 20) {
      train[i] = targetStr.slice(0, 20);
    }
  } else if (order === 4) {
    // <<
    const target = train[i];
    train[i] = (`0b${target}` << 1).toString(2);
    const targetStr = String(train[i]);
    if (targetStr.length > 20) {
      train[i] = targetStr.slice(targetStr.length - 20, targetStr.length);
    }
  }
}

// 중복되는 기차를 제거합니다.
const set = new Set();
train.forEach((x) => set.add(String(x).padStart(20, 0)));
console.log(set.size);

0개의 댓글