diff --git a/src/day5/main.rs b/src/day5/main.rs index c91ebc7..094b54a 100644 --- a/src/day5/main.rs +++ b/src/day5/main.rs @@ -4,295 +4,298 @@ use std::io::{self, BufRead, BufReader, Write}; #[derive(Copy, Clone, Debug)] enum Mode { - Position, - Immediate, + Position, + Immediate, } impl Default for Mode { - fn default() -> Self { - Mode::Position - } + fn default() -> Self { + Mode::Position + } } impl From for Mode { - fn from(b: bool) -> Self { - match b { - false => Mode::Position, - true => Mode::Immediate, - } - } + fn from(b: bool) -> Self { + match b { + false => Mode::Position, + true => Mode::Immediate, + } + } } #[derive(Copy, Clone, Default, Debug)] struct Modes { - a: Mode, - b: Mode, - c: Mode, + a: Mode, + b: Mode, + c: Mode, } impl From<(Mode, Mode, Mode)> for Modes { - fn from(modes: (Mode, Mode, Mode)) -> Self { - Modes { - a: modes.0, - b: modes.1, - c: modes.2, - } - } + fn from(modes: (Mode, Mode, Mode)) -> Self { + Modes { + a: modes.0, + b: modes.1, + c: modes.2, + } + } } impl From<&ModedOpcode> for Modes { - fn from(mo: &ModedOpcode) -> Self { - mo.modes - } + fn from(mo: &ModedOpcode) -> Self { + mo.modes + } } #[derive(Copy, Clone)] enum Opcode { - Add, - Multiply, - Input, - Output, - JumpIfTrue, - JumpIfFalse, - LessThan, - Equals, - Halt, + Add, + Multiply, + Input, + Output, + JumpIfTrue, + JumpIfFalse, + LessThan, + Equals, + Halt, } impl From<&ModedOpcode> for Opcode { - fn from(mo: &ModedOpcode) -> Self { - mo.op - } + fn from(mo: &ModedOpcode) -> Self { + mo.op + } } impl From for Opcode { - fn from(i: i64) -> Self { - match i { - 1 => Opcode::Add, - 2 => Opcode::Multiply, - 3 => Opcode::Input, - 4 => Opcode::Output, - 5 => Opcode::JumpIfTrue, - 6 => Opcode::JumpIfFalse, - 7 => Opcode::LessThan, - 8 => Opcode::Equals, - 99 => Opcode::Halt, - _ => panic!("invalid opcode {}", i), - } - } + fn from(i: i64) -> Self { + match i { + 1 => Opcode::Add, + 2 => Opcode::Multiply, + 3 => Opcode::Input, + 4 => Opcode::Output, + 5 => Opcode::JumpIfTrue, + 6 => Opcode::JumpIfFalse, + 7 => Opcode::LessThan, + 8 => Opcode::Equals, + 99 => Opcode::Halt, + _ => panic!("invalid opcode {}", i), + } + } } struct ModedOpcode { - modes: Modes, - op: Opcode, + modes: Modes, + op: Opcode, } impl From for ModedOpcode { - fn from(i: i64) -> Self { - let code = i % 100; - let a = i % 1000 >= 100; - let b = i % 10000 >= 1000; - let c = i > 10000; - let modes = (Mode::from(a), Mode::from(b), Mode::from(c)).into(); - ModedOpcode { - modes: modes, - op: Opcode::from(code), - } - } + fn from(i: i64) -> Self { + let code = i % 100; + let a = i % 1000 >= 100; + let b = i % 10000 >= 1000; + let c = i > 10000; + let modes = (Mode::from(a), Mode::from(b), Mode::from(c)).into(); + ModedOpcode { + modes: modes, + op: Opcode::from(code), + } + } } fn main() -> io::Result<()> { - println!("Hello, i am {}.", env::args().next().unwrap()); - let filename = env::args().nth(1).expect("provide file as first param"); - let computer = Computer::from(File::open(filename)?); - computer.clone().run(); - Ok(()) + println!("Hello, i am {}.", env::args().next().unwrap()); + let filename = env::args().nth(1).expect("provide file as first param"); + let computer = Computer::from(File::open(filename)?); + computer.clone().run(); + Ok(()) } struct Computer { - pos: usize, - program: Vec, - modes: Modes, + pos: usize, + program: Vec, + modes: Modes, } impl Clone for Computer { - fn clone(&self) -> Self { - Computer { - pos: 0, - program: self.program.clone(), - modes: Default::default(), - } - } + fn clone(&self) -> Self { + Computer { + pos: 0, + program: self.program.clone(), + modes: Default::default(), + } + } } impl From for Computer { - fn from(f: File) -> Self { - let f = BufReader::new(f); - let program: Vec = f - .split(b',') - .map(|o| { - let o = o.unwrap(); - let mut o = o.iter().peekable(); - let sign = if o.peek() == Some(&&b'-') { -1 } else { 1 }; - o.filter(|i| **i >= b'0' && **i <= b'9') - .fold(0, |s, i| ((i - b'0') as i64 + 10 * s)) - * sign - }) - .collect(); - program.into() - } + fn from(f: File) -> Self { + let f = BufReader::new(f); + let program: Vec = f + .split(b',') + .map(|o| { + let o = o.unwrap(); + let mut o = o.iter().peekable(); + let sign = if o.peek() == Some(&&b'-') { -1 } else { 1 }; + o.filter(|i| **i >= b'0' && **i <= b'9') + .fold(0, |s, i| ((i - b'0') as i64 + 10 * s)) + * sign + }) + .collect(); + program.into() + } } impl From> for Computer { - fn from(program: Vec) -> Self { - Computer { - pos: 0, - program: program, - modes: Default::default(), - } - } + fn from(program: Vec) -> Self { + Computer { + pos: 0, + program: program, + modes: Default::default(), + } + } } impl Computer { - fn update(&mut self, u: Vec<(usize, i64)>) -> Computer { - let mut computer = self.clone(); - for (pos, val) in u { - computer.program[pos] = val; - } - computer - } + fn update(&mut self, u: Vec<(usize, i64)>) -> Computer { + let mut computer = self.clone(); + for (pos, val) in u { + computer.program[pos] = val; + } + computer + } - fn run(&mut self) -> i64 { - loop { - let instruction = self.program[self.pos]; - let instruction = ModedOpcode::from(instruction); - self.modes = (&instruction).into(); - let advance = match (&instruction).into() { - Opcode::Add => self.add(), - Opcode::Multiply => self.multiply(), - Opcode::Input => self.input(), - Opcode::Output => self.output(), - Opcode::JumpIfTrue => self.jump_if_true(), - Opcode::JumpIfFalse => self.jump_if_false(), - Opcode::LessThan => self.less_than(), - Opcode::Equals => self.equals(), - Opcode::Halt => return self.program[0], - }; - self.pos += advance; - } - } + fn run(&mut self) -> i64 { + loop { + let instruction = self.program[self.pos]; + let instruction = ModedOpcode::from(instruction); + self.modes = (&instruction).into(); + let advance = match (&instruction).into() { + Opcode::Add => self.add(), + Opcode::Multiply => self.multiply(), + Opcode::Input => self.input(), + Opcode::Output => self.output(), + Opcode::JumpIfTrue => self.jump_if_true(), + Opcode::JumpIfFalse => self.jump_if_false(), + Opcode::LessThan => self.less_than(), + Opcode::Equals => self.equals(), + Opcode::Halt => return self.program[0], + }; + self.pos += advance; + } + } - fn get_a(&self) -> i64 { - let a = self.program[self.pos + 1]; - match self.modes.a { - Mode::Position => self.program[a as usize], - Mode::Immediate => a, - } - } + fn get_a(&self) -> i64 { + let a = self.program[self.pos + 1]; + match self.modes.a { + Mode::Position => self.program[a as usize], + Mode::Immediate => a, + } + } - fn set_a(&mut self, value: i64) { - let a = self.program[self.pos + 1]; - match self.modes.a { - Mode::Position => self.program[a as usize] = value, - Mode::Immediate => self.program[self.pos] = value, - } - } + fn set_a(&mut self, value: i64) { + let a = self.program[self.pos + 1]; + match self.modes.a { + Mode::Position => self.program[a as usize] = value, + Mode::Immediate => self.program[self.pos] = value, + } + } - fn get_b(&self) -> i64 { - let b = self.program[self.pos + 2]; - match self.modes.b { - Mode::Position => self.program[b as usize], - Mode::Immediate => b, - } - } + fn get_b(&self) -> i64 { + let b = self.program[self.pos + 2]; + match self.modes.b { + Mode::Position => self.program[b as usize], + Mode::Immediate => b, + } + } - fn set_c(&mut self, value: i64) { - let c = self.program[self.pos + 3]; - match self.modes.c { - Mode::Position => self.program[c as usize] = value, - Mode::Immediate => self.program[self.pos] = value, - } - } + fn set_c(&mut self, value: i64) { + let c = self.program[self.pos + 3]; + match self.modes.c { + Mode::Position => self.program[c as usize] = value, + Mode::Immediate => self.program[self.pos] = value, + } + } - fn add(&mut self) -> usize { - self.set_c(self.get_a() + self.get_b()); - 4 - } + fn add(&mut self) -> usize { + self.set_c(self.get_a() + self.get_b()); + 4 + } - fn multiply(&mut self) -> usize { - self.set_c(self.get_a() * self.get_b()); - 4 - } + fn multiply(&mut self) -> usize { + self.set_c(self.get_a() * self.get_b()); + 4 + } - fn input(&mut self) -> usize { - let mut line = String::new(); - print!("input: "); - io::stdout().flush().expect("unable to flush output"); - io::stdin().lock().read_line(&mut line).expect("input failed"); - let value = line.trim().parse().expect("numeric input required"); - self.set_a(value); - 2 - } + fn input(&mut self) -> usize { + let mut line = String::new(); + print!("input: "); + io::stdout().flush().expect("unable to flush output"); + io::stdin() + .lock() + .read_line(&mut line) + .expect("input failed"); + let value = line.trim().parse().expect("numeric input required"); + self.set_a(value); + 2 + } - fn output(&mut self) -> usize { - println!("output: {}", self.get_a()); - 2 - } + fn output(&mut self) -> usize { + println!("output: {}", self.get_a()); + 2 + } - fn jump_if_true(&mut self) -> usize { - if self.get_a() > 0 { - self.pos = self.get_b() as usize; - return 0; - } - 3 - } + fn jump_if_true(&mut self) -> usize { + if self.get_a() > 0 { + self.pos = self.get_b() as usize; + return 0; + } + 3 + } - fn jump_if_false(&mut self) -> usize { - if self.get_a() == 0 { - self.pos = self.get_b() as usize; - return 0; - } - 3 - } + fn jump_if_false(&mut self) -> usize { + if self.get_a() == 0 { + self.pos = self.get_b() as usize; + return 0; + } + 3 + } - fn less_than(&mut self) -> usize { - if self.get_a() < self.get_b() { - self.set_c(1) - } else { - self.set_c(0) - } - 4 - } + fn less_than(&mut self) -> usize { + if self.get_a() < self.get_b() { + self.set_c(1) + } else { + self.set_c(0) + } + 4 + } - fn equals(&mut self) -> usize { - if self.get_a() == self.get_b() { - self.set_c(1) - } else { - self.set_c(0) - } - 4 - } + fn equals(&mut self) -> usize { + if self.get_a() == self.get_b() { + self.set_c(1) + } else { + self.set_c(0) + } + 4 + } } #[cfg(test)] mod tests { - use super::*; + use super::*; - #[test] - fn example1() { - let program: Vec = vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50]; - assert_eq!(Computer::from(program).run(), 3500) - } + #[test] + fn example1() { + let program: Vec = vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50]; + assert_eq!(Computer::from(program).run(), 3500) + } - #[test] - fn example2() { - let program: Vec = vec![1, 0, 0, 0, 99]; - assert_eq!(Computer::from(program).run(), 2) - } + #[test] + fn example2() { + let program: Vec = vec![1, 0, 0, 0, 99]; + assert_eq!(Computer::from(program).run(), 2) + } - #[test] - fn example3() { - let program: Vec = vec![1, 1, 1, 4, 99, 5, 6, 0, 99]; - assert_eq!(Computer::from(program).run(), 30) - } + #[test] + fn example3() { + let program: Vec = vec![1, 1, 1, 4, 99, 5, 6, 0, 99]; + assert_eq!(Computer::from(program).run(), 30) + } }