diff --git a/Cargo.lock b/Cargo.lock index e70da3a..b49702e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,3 +5,61 @@ version = 3 [[package]] name = "advent2021" version = "0.1.0" +dependencies = [ + "thiserror", +] + +[[package]] +name = "proc-macro2" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" diff --git a/Cargo.toml b/Cargo.toml index f399d5b..b7a9c67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,5 @@ name = "advent2021" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] +thiserror = "1.0" diff --git a/data/day2_test.txt b/data/day2_test.txt new file mode 100644 index 0000000..b7172ac --- /dev/null +++ b/data/day2_test.txt @@ -0,0 +1,6 @@ +forward 5 +down 5 +forward 8 +up 3 +down 8 +forward 2 diff --git a/data/day2a.txt b/data/day2a.txt new file mode 100644 index 0000000..fb1384e --- /dev/null +++ b/data/day2a.txt @@ -0,0 +1,1000 @@ +forward 8 +down 6 +down 8 +forward 7 +down 5 +up 2 +down 3 +down 7 +down 8 +down 8 +down 8 +down 2 +up 1 +down 3 +up 2 +down 4 +down 2 +forward 6 +forward 4 +down 3 +down 2 +forward 2 +forward 1 +forward 4 +forward 5 +forward 8 +down 1 +down 4 +up 5 +up 2 +forward 3 +down 9 +forward 7 +forward 9 +forward 9 +forward 8 +down 1 +down 2 +forward 7 +down 3 +forward 6 +down 4 +forward 7 +down 1 +up 8 +forward 3 +down 1 +forward 7 +up 1 +forward 8 +up 6 +up 2 +down 6 +forward 1 +up 6 +forward 5 +down 9 +up 5 +forward 7 +forward 9 +down 9 +down 3 +forward 7 +forward 8 +forward 3 +forward 9 +forward 7 +down 3 +down 7 +down 4 +forward 2 +down 7 +down 3 +down 5 +up 1 +down 9 +up 4 +forward 1 +up 9 +down 2 +forward 8 +down 8 +down 6 +forward 7 +down 9 +down 3 +forward 8 +forward 3 +down 6 +down 7 +down 4 +forward 3 +down 3 +down 9 +forward 8 +forward 9 +up 5 +forward 1 +down 3 +down 3 +down 3 +down 9 +down 2 +down 9 +forward 5 +up 3 +up 5 +up 7 +down 2 +down 7 +down 9 +down 5 +down 4 +down 8 +forward 1 +up 8 +up 3 +forward 1 +forward 5 +forward 3 +up 7 +down 9 +down 9 +forward 7 +down 1 +forward 1 +forward 8 +forward 6 +down 1 +down 7 +forward 9 +up 4 +forward 8 +up 6 +forward 3 +down 3 +down 9 +forward 5 +up 3 +down 7 +forward 9 +forward 2 +up 1 +forward 7 +up 8 +forward 7 +forward 1 +up 3 +up 7 +down 1 +forward 5 +up 8 +down 2 +up 2 +up 3 +down 5 +forward 6 +up 8 +down 7 +up 8 +up 4 +down 8 +forward 9 +down 8 +down 2 +up 7 +down 5 +forward 1 +up 1 +down 1 +forward 1 +forward 1 +forward 3 +forward 8 +down 4 +down 5 +forward 9 +up 6 +up 7 +down 8 +forward 8 +down 2 +forward 6 +down 3 +forward 9 +forward 5 +up 7 +down 2 +up 6 +up 6 +down 9 +forward 3 +up 1 +up 2 +forward 9 +down 1 +up 3 +forward 4 +forward 9 +down 3 +down 4 +forward 4 +up 6 +up 5 +forward 2 +down 5 +down 1 +forward 9 +down 7 +up 6 +up 5 +forward 4 +forward 9 +down 6 +forward 1 +up 6 +down 1 +forward 4 +up 9 +down 6 +forward 5 +down 2 +forward 8 +forward 9 +down 7 +down 4 +down 1 +forward 1 +down 4 +down 6 +forward 5 +forward 2 +forward 8 +forward 5 +down 6 +up 9 +forward 2 +down 1 +forward 6 +forward 6 +down 5 +forward 5 +down 8 +forward 3 +down 5 +up 1 +forward 4 +down 5 +down 4 +forward 4 +down 3 +down 5 +down 7 +forward 5 +forward 2 +up 2 +up 4 +forward 7 +down 3 +down 1 +down 7 +up 8 +forward 6 +forward 3 +forward 7 +forward 5 +up 5 +down 3 +down 6 +forward 7 +up 9 +up 5 +forward 2 +down 9 +forward 8 +forward 6 +forward 5 +up 5 +down 9 +down 8 +up 2 +up 4 +forward 5 +forward 2 +up 4 +forward 3 +down 7 +forward 8 +forward 1 +forward 9 +forward 6 +up 7 +up 2 +forward 1 +down 5 +forward 9 +down 8 +down 4 +down 7 +up 2 +down 5 +forward 7 +up 3 +forward 6 +down 2 +forward 8 +forward 8 +up 3 +forward 6 +forward 9 +forward 8 +forward 3 +up 9 +forward 9 +down 6 +forward 5 +forward 8 +up 1 +forward 2 +forward 6 +forward 8 +up 6 +down 3 +down 9 +down 6 +up 7 +forward 6 +forward 1 +forward 1 +forward 7 +down 5 +down 9 +down 3 +up 3 +forward 3 +forward 2 +down 5 +up 4 +forward 1 +down 9 +forward 9 +forward 1 +forward 1 +down 9 +down 2 +forward 4 +forward 9 +down 5 +up 5 +down 6 +forward 8 +down 4 +down 1 +up 5 +up 3 +down 2 +down 3 +forward 8 +forward 5 +forward 9 +down 4 +up 9 +down 1 +forward 2 +down 8 +up 2 +down 8 +up 6 +forward 7 +down 1 +up 7 +down 9 +forward 9 +down 9 +forward 7 +forward 4 +down 5 +up 3 +down 3 +forward 8 +down 3 +down 4 +down 9 +forward 4 +up 4 +forward 6 +down 1 +forward 5 +down 2 +forward 6 +down 4 +down 1 +forward 3 +up 3 +up 3 +forward 8 +forward 6 +forward 6 +down 9 +forward 5 +down 9 +forward 6 +forward 3 +up 4 +forward 6 +down 8 +up 3 +down 9 +down 3 +forward 6 +down 4 +down 8 +down 6 +down 5 +forward 1 +down 3 +forward 9 +down 9 +down 3 +forward 9 +down 2 +forward 3 +up 6 +forward 2 +forward 1 +forward 8 +down 2 +down 2 +down 7 +up 7 +forward 3 +up 2 +up 6 +up 6 +down 2 +forward 2 +forward 2 +down 6 +down 2 +up 6 +forward 4 +down 9 +up 3 +down 4 +forward 7 +up 6 +forward 3 +forward 1 +down 1 +down 8 +down 8 +down 1 +forward 2 +down 6 +down 6 +forward 2 +up 6 +down 2 +up 4 +down 1 +up 8 +up 5 +down 4 +forward 2 +forward 2 +down 2 +forward 9 +down 5 +down 9 +forward 6 +down 9 +down 5 +down 7 +down 3 +up 9 +down 6 +up 6 +up 8 +forward 8 +forward 8 +down 3 +up 9 +forward 9 +forward 8 +forward 6 +down 4 +down 6 +up 9 +down 9 +down 5 +up 2 +up 2 +forward 2 +forward 1 +down 5 +down 8 +up 3 +forward 2 +down 1 +down 9 +forward 7 +forward 5 +up 3 +up 6 +down 5 +up 1 +down 2 +up 7 +forward 1 +down 6 +up 6 +up 1 +up 2 +forward 2 +down 4 +up 1 +up 3 +up 9 +up 7 +forward 4 +down 5 +down 9 +down 8 +forward 1 +down 4 +forward 4 +forward 8 +up 4 +down 8 +down 1 +down 9 +down 5 +forward 3 +forward 8 +up 2 +down 6 +up 6 +forward 5 +down 6 +down 8 +forward 6 +down 6 +up 5 +down 2 +up 5 +down 7 +down 9 +forward 3 +down 8 +forward 1 +forward 5 +forward 2 +down 4 +forward 2 +forward 7 +up 7 +up 3 +down 2 +forward 7 +up 6 +forward 6 +forward 1 +down 4 +down 2 +down 6 +down 1 +forward 1 +forward 8 +down 1 +up 2 +down 2 +down 1 +down 6 +forward 7 +forward 6 +forward 5 +down 1 +down 8 +down 1 +up 5 +forward 6 +forward 5 +up 5 +forward 5 +up 8 +down 3 +forward 1 +forward 6 +up 8 +up 9 +down 7 +down 1 +forward 2 +forward 1 +forward 9 +forward 3 +forward 7 +forward 8 +down 6 +up 5 +down 1 +forward 1 +forward 8 +down 6 +forward 7 +forward 8 +down 7 +down 5 +down 7 +up 7 +down 5 +forward 5 +down 4 +down 7 +forward 6 +forward 5 +forward 6 +forward 7 +up 9 +down 2 +down 2 +down 4 +down 8 +up 3 +down 7 +down 5 +forward 6 +down 9 +down 5 +down 9 +down 1 +forward 6 +up 7 +down 2 +down 2 +forward 8 +forward 1 +down 3 +down 4 +forward 3 +forward 4 +down 1 +forward 9 +up 7 +forward 8 +down 9 +forward 7 +forward 6 +forward 2 +down 8 +up 9 +down 2 +forward 8 +up 7 +down 5 +down 9 +down 3 +down 6 +down 4 +up 2 +down 3 +down 1 +up 1 +up 6 +forward 4 +down 1 +forward 1 +up 4 +forward 4 +forward 3 +forward 8 +forward 9 +forward 9 +down 2 +down 5 +up 8 +up 1 +down 9 +forward 5 +down 1 +up 5 +down 4 +up 3 +forward 9 +up 7 +forward 9 +up 1 +forward 4 +forward 8 +up 6 +down 6 +down 8 +down 8 +down 9 +down 2 +up 7 +forward 9 +up 8 +down 9 +up 6 +forward 4 +up 7 +down 6 +up 7 +down 4 +forward 2 +forward 9 +down 6 +down 8 +forward 6 +forward 3 +down 3 +forward 3 +forward 7 +up 2 +down 8 +forward 7 +down 5 +down 1 +down 6 +down 5 +down 2 +up 6 +forward 7 +forward 6 +down 1 +down 5 +forward 7 +forward 3 +down 9 +down 8 +forward 5 +up 7 +forward 1 +up 5 +down 7 +forward 8 +forward 6 +forward 2 +down 1 +down 9 +up 1 +down 2 +down 2 +down 7 +down 4 +forward 1 +down 3 +down 5 +up 8 +forward 7 +up 5 +down 8 +down 6 +down 3 +down 3 +down 9 +down 7 +forward 4 +up 5 +forward 3 +forward 7 +down 3 +up 6 +forward 4 +forward 4 +down 4 +down 2 +up 1 +forward 8 +forward 3 +up 1 +forward 1 +down 9 +down 6 +up 1 +down 4 +down 8 +up 9 +forward 2 +down 3 +forward 8 +down 6 +down 5 +down 4 +up 5 +down 9 +up 3 +forward 4 +down 9 +down 7 +forward 6 +forward 6 +forward 8 +forward 6 +down 9 +down 1 +forward 3 +forward 9 +forward 4 +up 8 +up 5 +up 2 +down 9 +forward 9 +forward 3 +forward 5 +up 8 +down 2 +down 1 +forward 9 +forward 7 +down 7 +forward 1 +down 5 +down 8 +down 4 +down 7 +down 1 +down 4 +down 7 +forward 2 +down 5 +forward 1 +down 4 +down 5 +down 2 +up 5 +forward 9 +down 5 +forward 1 +down 7 +down 4 +down 7 +down 6 +forward 5 +down 3 +down 1 +up 2 +forward 2 +forward 2 +forward 1 +down 1 +forward 3 +forward 5 +forward 4 +down 7 +forward 7 +down 1 +forward 7 +forward 5 +down 8 +forward 6 +forward 6 +forward 6 +forward 7 +up 9 +down 4 +down 1 +down 8 +forward 7 +up 4 +forward 4 +down 6 +up 1 +forward 5 +forward 2 +down 1 +forward 7 +forward 6 +forward 5 +forward 2 +down 5 +down 6 +down 9 +up 4 +forward 6 +forward 2 +down 5 +down 3 +up 4 +down 6 +up 8 +forward 8 +up 9 +forward 6 +forward 6 +up 5 +down 7 +forward 9 +forward 6 +down 9 +down 9 +up 1 +forward 7 +down 6 +up 4 +down 8 +down 3 +forward 9 +forward 5 +forward 9 +down 2 +forward 3 +down 1 +forward 9 +up 4 +up 8 +forward 6 +down 1 +forward 9 +forward 4 +down 5 +forward 2 +up 3 +forward 5 +up 8 +up 7 +down 8 +forward 4 +down 6 +forward 7 +up 2 +down 2 +forward 4 +down 9 +down 8 +forward 2 +forward 2 +down 2 +down 3 +forward 3 +down 1 +forward 8 +down 7 +up 9 +down 4 +down 2 +down 5 +up 7 +down 8 +down 2 +down 4 +down 4 +down 8 +forward 7 +forward 7 +down 8 +up 2 +up 3 +forward 8 +up 1 +down 7 +forward 7 +down 6 +down 8 +up 6 +forward 5 +forward 3 +down 6 +forward 9 +up 4 +up 7 +forward 4 +down 1 +down 8 +down 1 +forward 9 +down 3 +forward 8 +forward 6 +forward 4 +down 9 +forward 3 +up 5 +up 8 +down 9 +down 5 +down 1 +up 8 +forward 8 +up 6 +forward 2 +down 8 +up 4 +up 7 +forward 7 +forward 5 +forward 9 +forward 2 +up 4 +down 9 +forward 7 +down 6 +down 6 +forward 7 +down 5 +up 6 +down 9 +forward 3 diff --git a/src/bin/day2.rs b/src/bin/day2.rs new file mode 100644 index 0000000..4c337f6 --- /dev/null +++ b/src/bin/day2.rs @@ -0,0 +1,169 @@ +use std::num; +use std::str::FromStr; +use thiserror::Error; + +#[cfg(test)] +const TEST_DATA: &str = include_str!("../../data/day2_test.txt"); +const DAY2A: &str = include_str!("../../data/day2a.txt"); + +#[derive(Debug, Error, PartialEq)] +enum Oopsie { + #[error("Couldn't understand '{0}' as a command.")] + CouldntParseCommand(String), + #[error("Couldn't parse number: {0}")] + CouldntParseNumber(#[from] num::ParseIntError), +} + +#[derive(Debug, Eq, PartialEq)] +enum Command { + Forward(isize), + Down(isize), + Up(isize), +} + +impl FromStr for Command { + type Err = Oopsie; + + fn from_str(s: &str) -> Result { + if let Some(rest) = s.strip_prefix("forward ") { + Ok(Command::Forward(isize::from_str(rest)?)) + } else if let Some(rest) = s.strip_prefix("down ") { + Ok(Command::Down(isize::from_str(rest)?)) + } else if let Some(rest) = s.strip_prefix("up ") { + Ok(Command::Up(isize::from_str(rest)?)) + } else { + Err(Oopsie::CouldntParseCommand(s.to_string())) + } + } +} + +fn from_file_data(filedata: &str) -> Result, T::Err> { + let mut retval = Vec::new(); + + for line in filedata.lines() { + retval.push(T::from_str(line)?); + } + + Ok(retval) +} + +#[test] +fn command_parsing() { + assert_eq!(Ok(Command::Forward(5)), Command::from_str("forward 5")); + assert_eq!(Ok(Command::Down(5)), Command::from_str("down 5")); + assert_eq!(Ok(Command::Forward(8)), Command::from_str("forward 8")); + assert_eq!(Ok(Command::Up(3)), Command::from_str("up 3")); + assert_eq!(Ok(Command::Down(8)), Command::from_str("down 8")); + assert_eq!(Ok(Command::Forward(2)), Command::from_str("forward 2")); +} + +#[test] +fn file_parsing() { + let result: Result, Oopsie> = from_file_data(TEST_DATA); + assert!(result.is_ok()); +} + +#[derive(Debug)] +struct Submarine { + interpretation: Interpretation, + depth: isize, + position_x: isize, + aim: isize, +} + +#[derive(Debug)] +enum Interpretation { + Basic, + WithAim, +} + +impl Submarine { + fn new(interpretation: Interpretation) -> Submarine { + Submarine { + interpretation, + depth: 0, + position_x: 0, + aim: 0, + } + } + + fn command(&mut self, cmd: &Command) { + match self.interpretation { + Interpretation::Basic => match cmd { + Command::Forward(v) => self.position_x += v, + Command::Up(v) => self.depth -= v, + Command::Down(v) => self.depth += v, + }, + + Interpretation::WithAim => match cmd { + Command::Forward(v) => { + self.position_x += v; + self.depth += self.aim * v; + } + Command::Up(v) => self.aim -= v, + Command::Down(v) => self.aim += v, + }, + } + } + + fn run(&mut self, cmds: &[Command]) { + for cmd in cmds.iter() { + self.command(cmd); + } + } + + fn distance(&self) -> isize { + self.depth * self.position_x + } +} + +#[test] +fn basic_test_intepretation() { + let test_commands = from_file_data(TEST_DATA).unwrap(); + let mut test_submarine = Submarine::new(Interpretation::Basic); + test_submarine.run(&test_commands); + assert_eq!(150, test_submarine.distance()); +} + +#[test] +fn test_intepretation_with_aim() { + let test_commands = from_file_data(TEST_DATA).unwrap(); + let mut test_submarine = Submarine::new(Interpretation::WithAim); + test_submarine.run(&test_commands); + assert_eq!(900, test_submarine.distance()); +} + +// just in case I decide to be fancy and pull some stuff out of this for a +// later challenge +#[test] +fn regression_tests() { + let commands = from_file_data(DAY2A).unwrap(); + + let mut part1_submarine = Submarine::new(Interpretation::Basic); + part1_submarine.run(&commands); + assert_eq!(2039912, part1_submarine.distance()); + + let mut part2_submarine = Submarine::new(Interpretation::WithAim); + part2_submarine.run(&commands); + assert_eq!(1942068080, part2_submarine.distance()); +} + +fn day2() -> Result<(), Oopsie> { + let commands = from_file_data(DAY2A)?; + + let mut part1_submarine = Submarine::new(Interpretation::Basic); + part1_submarine.run(&commands); + println!("Part 1 distance: {}", part1_submarine.distance()); + + let mut part2_submarine = Submarine::new(Interpretation::WithAim); + part2_submarine.run(&commands); + println!("Part 2 distance: {}", part2_submarine.distance()); + + Ok(()) +} + +fn main() { + if let Err(e) = day2() { + println!("Whoops: Top-level error: {}", e); + } +}