네 개의 명령어 D, S, L, R 을 이용하는 간단한 계산기가 있다. 이 계산기에는 레지스터가 하나 있는데, 이 레지스터에는 0 이상 10,000 미만의 십진수를 저장할 수 있다. 각 명령어는 이 레지스터에 저장된 n을 다음과 같이 변환한다. n의 네 자릿수를 d1, d2, d3, d4라고 하자(즉 n = ((d1 × 10 + d2) × 10 + d3) × 10 + d4라고 하자)
D: D 는 n을 두 배로 바꾼다. 결과 값이 9999 보다 큰 경우에는 10000 으로 나눈 나머지를 취한다. 그 결과 값(2n mod 10000)을 레지스터에 저장한다.
S: S 는 n에서 1 을 뺀 결과 n-1을 레지스터에 저장한다. n이 0 이라면 9999 가 대신 레지스터에 저장된다.
L: L 은 n의 각 자릿수를 왼편으로 회전시켜 그 결과를 레지스터에 저장한다. 이 연산이 끝나면 레지스터에 저장된 네 자릿수는 왼편부터 d2, d3, d4, d1이 된다.
R: R 은 n의 각 자릿수를 오른편으로 회전시켜 그 결과를 레지스터에 저장한다. 이 연산이 끝나면 레지스터에 저장된 네 자릿수는 왼편부터 d4, d1, d2, d3이 된다.
위에서 언급한 것처럼, L 과 R 명령어는 십진 자릿수를 가정하고 연산을 수행한다. 예를 들어서 n = 1234 라면 여기에 L 을 적용하면 2341 이 되고 R 을 적용하면 4123 이 된다.
여러분이 작성할 프로그램은 주어진 서로 다른 두 정수 A와 B(A ≠ B)에 대하여 A를 B로 바꾸는 최소한의 명령어를 생성하는 프로그램이다. 예를 들어서 A = 1234, B = 3412 라면 다음과 같이 두 개의 명령어를 적용하면 A를 B로 변환할 수 있다.
1234 →L 2341 →L 3412
1234 →R 4123 →R 3412
따라서 여러분의 프로그램은 이 경우에 LL 이나 RR 을 출력해야 한다.
n의 자릿수로 0 이 포함된 경우에 주의해야 한다. 예를 들어서 1000 에 L 을 적용하면 0001 이 되므로 결과는 1 이 된다. 그러나 R 을 적용하면 0100 이 되므로 결과는 100 이 된다.
문제를 읽고 이게 왜 20퍼지? 의문을 품었다. 그런데 한 두 번 시간 초과를 겪고 아 이래서 20퍼구나 느꼈던 문제이다. 이 문제를 시간 초과 없이 통과 하기 위해서는 'L'과 'R'연산을 최소한으로 줄여야 한다.
1) 'L'연산은 왼쪽으로 회전하고 천의 자리가 일의 자리로 간다.
n = 1234라면 1234 나누기 1000은 몫이 1 나머지가 234 나온다.
234 * 10 + 1 = 2341이고 2341은 1234를 왼쪽으로 회전시킨 결괏값이다.
2) 'R'연산은 오른쪽으로 회전하고 일의 자리가 천의 자리로 간다.
n = 1234라면 1234 나누기 10은 몫이 123 나머지가 4가 나온다.
123 + 4 * 1000 = 4123이고 4123은 1234를 오른쪽으로 회전시킨 결괏값이다.
이 두 개 연산만 이렇게 줄일 수 있다면 통과할 수 있다.
class Queue {
constructor() {
this.storage = {};
this.front = 0;
this.rear = -1;
}
size() {
if (this.front > this.rear) {
return 0;
} else {
return this.rear - this.front + 1;
}
}
push(value) {
this.rear += 1;
this.storage[this.rear] = value;
}
pop_left() {
let value = this.storage[this.front];
if (this.size()) {
delete this.storage[this.front];
this.front += 1;
}
return value;
}
}
const fs = require('fs');
let inputData = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
let T = inputData[0].trim() * 1;
let A;
let B;
let visited;
let output = '';
let op = ['D', 'S', 'L', 'R'];
for (let i = 1; i <= T; i++) {
let [a, b] = inputData[i].trim().split(' ').map(x => x * 1);
A = a;
B = b;
visited = new Array(10000).fill(false);
output += `${BFS()}\n`;
}
console.log(output.trim());
function BFS() {
let que = new Queue();
que.push([A, '']);
visited[A] = true;
while (que.size()) {
let [a, op_str] = que.pop_left();
if (a === B) {
return op_str;
}
for (let i = 0; i < op.length; i++) {
let na = DSLR(a, op[i]);
if (!visited[na]) {
visited[na] = true;
que.push([na, op_str + op[i]]);
}
}
}
}
function DSLR(v, op) {
let nv;
if (op === 'D') {
nv = v * 2;
if (nv > 9999) {
nv = nv % 10000;
}
} else if (op === 'S') {
if (v === 0) {
nv = 9999;
} else {
nv = v - 1;
}
} else if( op === 'L') {
nv = v % 1000 * 10 + parseInt(v/1000);
} else if( op === 'R') {
nv = parseInt(v/10) + v % 10 * 1000
}
return nv;
}