diff --git a/2018/rust/src/bin/day_15.rs b/2018/rust/src/bin/day_15.rs
index 035020c..4d64577 100644
--- a/2018/rust/src/bin/day_15.rs
+++ b/2018/rust/src/bin/day_15.rs
@@ -8,7 +8,7 @@ use advent_of_code::main;
main!();
-fn solve(input: &str) -> Result<String, Box<Error>> {
+fn solve(_input: &str) -> Result<String, Box<Error>> {
unimplemented!();
}
@@ -458,7 +458,7 @@ enum Race {
}
impl Race {
- fn enemy(&self) -> Race {
+ fn enemy(self) -> Race {
match self {
Race::Elf => Race::Goblin,
Race::Goblin => Race::Elf,
diff --git a/2018/rust/src/bin/day_19.rs b/2018/rust/src/bin/day_19.rs
new file mode 100644
index 0000000..8e9054d
--- /dev/null
+++ b/2018/rust/src/bin/day_19.rs
@@ -0,0 +1,201 @@
+use std::error::Error;
+use std::str::FromStr;
+
+use regex::Regex;
+
+use advent_of_code::main;
+
+main!();
+
+fn solve(input: &str) -> Result<String, Box<Error>> {
+ let mut program: Program = input.parse()?;
+ program.registers[0] = 1;
+ let registers = program.last().unwrap();
+ let output = registers[0].to_string();
+ Ok(output)
+}
+
+type Registers = [usize; 6];
+
+struct Program {
+ ip: usize,
+ instructions: Vec<Instruction>,
+ registers: Registers,
+}
+
+impl Program {
+ fn execute(&mut self, i: &Instruction) {
+ match i.opcode {
+ Opcode::Addr => self.registers[i.c] = self.registers[i.a] + self.registers[i.b],
+ Opcode::Addi => self.registers[i.c] = self.registers[i.a] + i.b,
+ Opcode::Mulr => self.registers[i.c] = self.registers[i.a] * self.registers[i.b],
+ Opcode::Muli => self.registers[i.c] = self.registers[i.a] * i.b,
+ Opcode::Banr => self.registers[i.c] = self.registers[i.a] & self.registers[i.b],
+ Opcode::Bani => self.registers[i.c] = self.registers[i.a] & i.b,
+ Opcode::Borr => self.registers[i.c] = self.registers[i.a] | self.registers[i.b],
+ Opcode::Bori => self.registers[i.c] = self.registers[i.a] | i.b,
+ Opcode::Setr => self.registers[i.c] = self.registers[i.a],
+ Opcode::Seti => self.registers[i.c] = i.a,
+ Opcode::Gtir => self.registers[i.c] = if i.a > self.registers[i.b] { 1 } else { 0 },
+ Opcode::Gtri => self.registers[i.c] = if self.registers[i.a] > i.b { 1 } else { 0 },
+ Opcode::Gtrr => {
+ self.registers[i.c] = if self.registers[i.a] > self.registers[i.b] {
+ 1
+ } else {
+ 0
+ }
+ }
+ Opcode::Eqir => self.registers[i.c] = if i.a == self.registers[i.b] { 1 } else { 0 },
+ Opcode::Eqri => self.registers[i.c] = if self.registers[i.a] == i.b { 1 } else { 0 },
+ Opcode::Eqrr => {
+ self.registers[i.c] = if self.registers[i.a] == self.registers[i.b] {
+ 1
+ } else {
+ 0
+ }
+ }
+ }
+ }
+}
+
+impl Iterator for Program {
+ type Item = Registers;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let ins = *self.instructions.get(self.registers[self.ip])?;
+ self.execute(&ins);
+ self.registers[self.ip] += 1;
+ Some(self.registers)
+ }
+}
+
+#[test]
+fn test_program() {
+ let mut program: Program = r"
+#ip 0
+seti 5 0 1
+seti 6 0 2
+addi 0 1 0
+addr 1 2 3
+setr 1 0 0
+seti 8 0 4
+seti 9 0 5
+ "
+ .parse()
+ .unwrap();
+
+ assert_eq!(program.next().unwrap(), [1, 5, 0, 0, 0, 0]);
+}
+
+#[derive(Clone, Copy)]
+struct Instruction {
+ opcode: Opcode,
+ a: usize,
+ b: usize,
+ c: usize,
+}
+
+#[derive(Clone, Copy)]
+enum Opcode {
+ Addr,
+ Addi,
+ Mulr,
+ Muli,
+ Banr,
+ Bani,
+ Borr,
+ Bori,
+ Setr,
+ Seti,
+ Gtir,
+ Gtri,
+ Gtrr,
+ Eqir,
+ Eqri,
+ Eqrr,
+}
+
+impl FromStr for Program {
+ type Err = Box<Error>;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut lines = s.trim().lines();
+ let ip_re = Regex::new(r"^#ip (\d+)$").unwrap();
+ let ip = lines
+ .next()
+ .and_then(|l| ip_re.captures(l))
+ .and_then(|c| c.get(1))
+ .unwrap()
+ .as_str()
+ .parse()?;
+
+ let instructions = lines.map(|l| l.parse()).collect::<Result<_, _>>()?;
+
+ let registers = [0; 6];
+
+ Ok(Program {
+ ip,
+ instructions,
+ registers,
+ })
+ }
+}
+
+impl FromStr for Instruction {
+ type Err = Box<Error>;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut s = s.split_whitespace();
+ let opcode = s.next().unwrap().parse()?;
+ let a = s.next().unwrap().parse()?;
+ let b = s.next().unwrap().parse()?;
+ let c = s.next().unwrap().parse()?;
+ Ok(Instruction { opcode, a, b, c })
+ }
+}
+
+impl FromStr for Opcode {
+ type Err = Box<Error>;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let opcode = match s {
+ "addr" => Opcode::Addr,
+ "addi" => Opcode::Addi,
+ "mulr" => Opcode::Mulr,
+ "muli" => Opcode::Muli,
+ "banr" => Opcode::Banr,
+ "bani" => Opcode::Bani,
+ "borr" => Opcode::Borr,
+ "bori" => Opcode::Bori,
+ "setr" => Opcode::Setr,
+ "seti" => Opcode::Seti,
+ "gtir" => Opcode::Gtir,
+ "gtri" => Opcode::Gtri,
+ "gtrr" => Opcode::Gtrr,
+ "eqir" => Opcode::Eqir,
+ "eqri" => Opcode::Eqri,
+ "eqrr" => Opcode::Eqrr,
+ _ => unreachable!(),
+ };
+ Ok(opcode)
+ }
+}
+
+// OPCODES = {
+// addr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + registers[b] } },
+// addi: ->(a, b, c) { ->(registers) { registers[c] = registers[a] + b } },
+// mulr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * registers[b] } },
+// muli: ->(a, b, c) { ->(registers) { registers[c] = registers[a] * b } },
+// banr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & registers[b] } },
+// bani: ->(a, b, c) { ->(registers) { registers[c] = registers[a] & b } },
+// borr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | registers[b] } },
+// bori: ->(a, b, c) { ->(registers) { registers[c] = registers[a] | b } },
+// setr: ->(a, b, c) { ->(registers) { registers[c] = registers[a] } },
+// seti: ->(a, b, c) { ->(registers) { registers[c] = a } },
+// gtir: ->(a, b, c) { ->(registers) { registers[c] = (a > registers[b]) ? 1 : 0 } },
+// gtri: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] > b) ? 1 : 0 } },
+// gtrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] > registers[b]) ? 1 : 0 } },
+// eqir: ->(a, b, c) { ->(registers) { registers[c] = (a == registers[b]) ? 1 : 0 } },
+// eqri: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] == b) ? 1 : 0 } },
+// eqrr: ->(a, b, c) { ->(registers) { registers[c] = (registers[a] == registers[b]) ? 1 : 0 } },
+// }