diff options
author | Prefetch | 2023-02-25 11:41:27 +0100 |
---|---|---|
committer | Prefetch | 2023-02-25 11:41:27 +0100 |
commit | 3b877bf4cc667eb8bcc787d145203600a4dba2d2 (patch) | |
tree | c1d247def29fcb58ae28e4ae4e4d73d1b4e1b27f /d01/src |
Initial commit
Diffstat (limited to 'd01/src')
-rw-r--r-- | d01/src/main.rs | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/d01/src/main.rs b/d01/src/main.rs new file mode 100644 index 0000000..3117a5a --- /dev/null +++ b/d01/src/main.rs @@ -0,0 +1,123 @@ +use std::fs; + +enum Heading { + North, + East, + South, + West, +} + +impl Heading { + fn turn_left(&mut self) { + *self = match *self { + Heading::North => Heading::West, + Heading::East => Heading::North, + Heading::South => Heading::East, + Heading::West => Heading::South, + }; + } + + fn turn_right(&mut self) { + *self = match *self { + Heading::North => Heading::East, + Heading::East => Heading::South, + Heading::South => Heading::West, + Heading::West => Heading::North, + }; + } +} + +fn get_route(input: &str) -> Vec<(isize, isize)> { + let steps: Vec<&str> = input.trim().split(", ").collect(); + + let mut pos = (0, 0); + let mut route = vec![pos]; + + let mut facing = Heading::North; + for s in steps { + // Read which way to turn + if s.starts_with("L") { + facing.turn_left(); + } else if s.starts_with("R") { + facing.turn_right(); + } + + // Read how far to go in the new direction + let dist: usize = s[1..].parse().unwrap(); + + // Add each 1-block step to `route' so that part 2 can be solved + for _i in 0..dist { + pos = match facing { + Heading::North => (pos.0 + 1, pos.1), + Heading::East => (pos.0, pos.1 + 1), + Heading::South => (pos.0 - 1, pos.1), + Heading::West => (pos.0, pos.1 - 1), + }; + route.push(pos); + } + } + + route +} + +fn solve_part1(input: &str) -> isize { + let route = get_route(input); + let ended = route.last().unwrap(); + + // Manhattan distance from origin to `ended' position + ended.0.abs() + ended.1.abs() +} + +fn solve_part2(input: &str) -> Option<isize> { + let route = get_route(input); + + for i in 1..route.len() { + let pos = route[i - 1]; + if route[i..].contains(&pos) { + // Manhattan distance to first twice-visited position + return Some(pos.0.abs() + pos.1.abs()); + } + } + + None +} + +fn main() { + // Read instructions from input text file + let input = fs::read_to_string("input.txt").unwrap(); + + // Part 1 gives 181 for me + println!("Part 1 solution: {}", solve_part1(&input)); + + // Part 2 gives 140 for me + println!("Part 2 solution: {}", solve_part2(&input).unwrap()); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_example1() { + let input = "R2, L3"; + assert_eq!(solve_part1(input), 5); + } + + #[test] + fn part1_example2() { + let input = "R2, R2, R2"; + assert_eq!(solve_part1(input), 2); + } + + #[test] + fn part1_example3() { + let input = "R5, L5, R5, R3"; + assert_eq!(solve_part1(input), 12); + } + + #[test] + fn part2_example1() { + let input = "R8, R4, R4, R8"; + assert_eq!(solve_part2(input).unwrap(), 4); + } +} |