백준 알고리즘
[Gold V] 귀도 반 로썸은 크리스마스날 심심하다고 파이썬을 만들었다 - 6568
성능 요약
메모리: 13152 KB, 시간: 4 ms
분류
구현(implementation), 시뮬레이션(simulation)
문제 설명
그래서 여러분도 크리스마스날 심심해서 컴퓨터를 하나 만들었다. 이 컴퓨터는 아주 적은 수의 명령어를 사용하는 하나의 프로세서, 32바이트 메모리, 8비트짜리 가산기, 5비트짜리 프로그램 카운터(pc)로 이루어져 있다. 폰 노이만 구조를 표방하여 이 컴퓨터는 메모리와 프로그램 구문을 공유한다.
프로그램 카운터는 다음에 실행되어야 하는 명령어의 주소를 갖고 있다. 각 명령어의 길이는 1바이트이며, 상위 3비트는 명령어의 종류를, 하위 5비트는 피연산자를 표현한다. 피연산자는 언제나 메모리 값(XXXXX)이다. 피연산자가 필요하지 않은 명령어도 있는데, 이때는 하위 5비트는 무의미하다(-----). 사용되는 명령어들의 의미는 다음과 같다.
000xxxxx STA x
메모리 주소 x에 가산기의 값을 저장한다.
001xxxxx LDA x
메모리 주소 x의 값을 가산기로 불러온다.
010xxxxx BEQ x
가산기의 값이 0이면 PC 값을 x로 바꾼다.
011----- NOP
아무 연산도 하지 않는다.
100----- DEC
가산기 값을 1 감소시킨다.
101----- INC
가산기 값을 1 증가시킨다.
110xxxxx JMP x
PC 값을 x로 바꾼다.
111----- HLT
프로그램을 종료한다.
초기엔 PC와 가산기 값은 모두 0이다. 명령어를 불러와 해독한 뒤, 그 명령어를 실행하기 전에 PC 값은 1 증가한다. 프로그램은 언제나 종료된다고 가정해도 좋다.
입력
입력은 여러 개의 테스트 케이스로 주어진다. 각 테스트 케이스는 32개의 줄에 걸쳐 각 메모리 값, 즉 코드가 순서대로 8비트 2진수의 형태로 주어진다. 왼쪽에 있는 비트일수록 상위 비트이다. 입력은 EOF와 함께 종료된다.
출력
각 테스트 케이스마다 한 줄에 걸쳐 프로그램이 종료되었을 때의 가산기 값을 역시 8비트 2진수 형태로 출력한다. 이때도 왼쪽에 출력될수록 상위 비트이다.
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
let mut lines = stdin.lock().lines();
loop {
let mut memory = vec![0; 32];
for i in 0..32 {
let bin = lines.next();
if !bin.is_some() {
return;
}
let bin = bin.unwrap().ok().unwrap();
if bin.is_empty() {
return;
}
memory[i] = isize::from_str_radix(&bin, 2).unwrap() as usize;
}
let (mut pc, mut accumulator) = (0, 0);
loop {
let instruction = memory[pc];
let operator = instruction / 32;
let value = instruction % 32;
if operator == 7 {
break;
}
pc = (pc + 1) % 32;
match operator {
0 => memory[value] = accumulator,
1 => accumulator = memory[value],
2 => {
if accumulator == 0 {
pc = value;
}
},
4 => accumulator = (accumulator + 255) % 256,
5 => accumulator = (accumulator + 1) % 256,
6 => pc = value,
_ => ()
}
}
for i in (0..8).rev() {
print!("{}", (accumulator >> i) & 1);
}
println!();
}
}