Skip to content

Commit caf5107

Browse files
committed
trait std::str::FromStr
1 parent c31d4aa commit caf5107

File tree

1 file changed

+87
-39
lines changed

1 file changed

+87
-39
lines changed

2018/day21/day21.rs

Lines changed: 87 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,108 @@
11
//! [Day 21: Chronal Conversion](https://adventofcode.com/2018/day/21)
22
33
use std::collections::HashSet;
4+
use std::fmt::Error;
45

5-
const OPCODES: [&str; 16] = [
6-
"addi", "addr", "bani", "banr", "bori", "borr", "eqir", "eqri", "eqrr", "gtir", "gtri", "gtrr",
7-
"muli", "mulr", "seti", "setr",
8-
];
9-
10-
fn emulate(opcode: &'static str, a: u64, b: u64, c: u64, regs: &mut [u64]) {
11-
regs[c as usize] = match opcode {
12-
"addr" => regs[a as usize] + regs[b as usize],
13-
"addi" => regs[a as usize] + b,
14-
"mulr" => regs[a as usize] * regs[b as usize],
15-
"muli" => regs[a as usize] * b,
16-
"banr" => regs[a as usize] & regs[b as usize],
17-
"bani" => regs[a as usize] & b,
18-
"borr" => regs[a as usize] | regs[b as usize],
19-
"bori" => regs[a as usize] | b,
20-
"setr" => regs[a as usize],
21-
"seti" => a,
22-
"gtir" => u64::from(a > regs[b as usize]),
23-
"gtri" => u64::from(regs[a as usize] > b),
24-
"gtrr" => u64::from(regs[a as usize] > regs[b as usize]),
25-
"eqir" => u64::from(a == regs[b as usize]),
26-
"eqri" => u64::from(regs[a as usize] == b),
27-
"eqrr" => u64::from(regs[a as usize] == regs[b as usize]),
28-
_ => panic!("bad opcode {opcode}"),
29-
};
6+
#[derive(Debug)]
7+
enum OpCodes {
8+
Addi,
9+
Addr,
10+
Bani,
11+
Banr,
12+
Bori,
13+
Borr,
14+
Eqir,
15+
Eqri,
16+
Eqrr,
17+
Gtir,
18+
Gtri,
19+
Gtrr,
20+
Muli,
21+
Mulr,
22+
Seti,
23+
Setr,
24+
}
25+
26+
impl std::str::FromStr for OpCodes {
27+
type Err = Box<Error>;
28+
fn from_str(s: &str) -> Result<Self, Self::Err> {
29+
let opcode = match s {
30+
"addr" => OpCodes::Addr,
31+
"addi" => OpCodes::Addi,
32+
"mulr" => OpCodes::Mulr,
33+
"muli" => OpCodes::Muli,
34+
"banr" => OpCodes::Banr,
35+
"bani" => OpCodes::Bani,
36+
"borr" => OpCodes::Borr,
37+
"bori" => OpCodes::Bori,
38+
"setr" => OpCodes::Setr,
39+
"seti" => OpCodes::Seti,
40+
"gtir" => OpCodes::Gtir,
41+
"gtri" => OpCodes::Gtri,
42+
"gtrr" => OpCodes::Gtrr,
43+
"eqir" => OpCodes::Eqir,
44+
"eqri" => OpCodes::Eqri,
45+
"eqrr" => OpCodes::Eqrr,
46+
_ => panic!("unknown opcode {s}"),
47+
};
48+
49+
Ok(opcode)
50+
}
51+
}
52+
53+
impl OpCodes {
54+
fn emulate(&self, a: u64, b: u64, c: u64, regs: &mut [u64]) {
55+
regs[c as usize] = match &self {
56+
OpCodes::Addr => regs[a as usize] + regs[b as usize],
57+
OpCodes::Addi => regs[a as usize] + b,
58+
OpCodes::Mulr => regs[a as usize] * regs[b as usize],
59+
OpCodes::Muli => regs[a as usize] * b,
60+
OpCodes::Banr => regs[a as usize] & regs[b as usize],
61+
OpCodes::Bani => regs[a as usize] & b,
62+
OpCodes::Borr => regs[a as usize] | regs[b as usize],
63+
OpCodes::Bori => regs[a as usize] | b,
64+
OpCodes::Setr => regs[a as usize],
65+
OpCodes::Seti => a,
66+
OpCodes::Gtir => u64::from(a > regs[b as usize]),
67+
OpCodes::Gtri => u64::from(regs[a as usize] > b),
68+
OpCodes::Gtrr => u64::from(regs[a as usize] > regs[b as usize]),
69+
OpCodes::Eqir => u64::from(a == regs[b as usize]),
70+
OpCodes::Eqri => u64::from(regs[a as usize] == b),
71+
OpCodes::Eqrr => u64::from(regs[a as usize] == regs[b as usize]),
72+
};
73+
}
3074
}
3175

32-
#[derive(Debug)]
3376
struct Instr {
34-
opcode: &'static str,
77+
opcode: OpCodes,
3578
a: u64,
3679
b: u64,
3780
c: u64,
3881
}
3982

4083
impl Instr {
4184
fn run(&self, regs: &mut [u64]) {
42-
emulate(self.opcode, self.a, self.b, self.c, regs);
85+
self.opcode.emulate(self.a, self.b, self.c, regs);
86+
}
87+
}
88+
89+
impl std::str::FromStr for Instr {
90+
type Err = Box<Error>;
91+
fn from_str(s: &str) -> Result<Self, Self::Err> {
92+
let s: Vec<_> = s.split_ascii_whitespace().collect();
93+
94+
let opcode = s[0].parse().unwrap();
95+
let a = s[1].parse().unwrap();
96+
let b = s[2].parse().unwrap();
97+
let c = s[3].parse().unwrap();
98+
99+
Ok(Instr { opcode, a, b, c })
43100
}
44101
}
45102

46103
impl std::fmt::Display for Instr {
47104
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48-
write!(f, "{} {} {} {}", self.opcode, self.a, self.b, self.c)
105+
write!(f, "{:?} {} {} {}", self.opcode, self.a, self.b, self.c)
49106
}
50107
}
51108

@@ -72,16 +129,7 @@ impl Puzzle {
72129
if let Some(value) = line.strip_prefix("#ip ") {
73130
self.ip_reg = value.parse::<usize>().unwrap();
74131
} else {
75-
let line: Vec<_> = line.split_ascii_whitespace().collect();
76-
77-
let opcode = OPCODES.iter().find(|&&opcode| opcode == line[0]).unwrap();
78-
let a = line[1].parse::<u64>().unwrap();
79-
let b = line[2].parse::<u64>().unwrap();
80-
let c = line[3].parse::<u64>().unwrap();
81-
82-
let instr = Instr { opcode, a, b, c };
83-
84-
self.program.push(instr);
132+
self.program.push(line.parse().unwrap());
85133
}
86134
}
87135
}

0 commit comments

Comments
 (0)