From 5717adcf1cf46a2e3051c859f6d38d7562784faf Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Tue, 13 Dec 2022 16:19:26 -0500 Subject: [PATCH] Complete day 9 part 1 --- day9/src/main.rs | 110 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 16 deletions(-) diff --git a/day9/src/main.rs b/day9/src/main.rs index 0cebe63..7e9eca2 100644 --- a/day9/src/main.rs +++ b/day9/src/main.rs @@ -11,7 +11,7 @@ use Direction::*; struct Move { dir: Direction, - amount: usize, + amount: isize, } impl Move { @@ -25,7 +25,7 @@ impl Move { "R" => Right, _ => panic!("Invalid direction!"), }; - let amount = parts[1].parse::().unwrap(); + let amount = parts[1].parse::().unwrap(); Move { dir, amount } } @@ -33,17 +33,23 @@ impl Move { #[derive(Debug, Default, Copy, Clone, Eq, Hash, PartialEq)] struct Location { - x: usize, - y: usize, + x: isize, + y: isize, } impl Location { - fn new(x: usize, y: usize) -> Self { + fn new(x: isize, y: isize) -> Self { Location { x, y } } + + fn get_distance(self, other: Self) -> f64 { + let squares = (other.x - self.x).pow(2) + (other.y - self.y).pow(2); + + (squares as f64).sqrt() + } } -// ---------------------------------------------------------------------------- +// --------------------------------------------------------------------------- #[derive(Debug, Default)] struct Rope { @@ -55,21 +61,31 @@ struct Rope { impl Rope { pub fn new() -> Self { - Rope { ..Rope::default() } + let mut rope = Self::default(); + rope.head_visited.insert(Location::default()); + rope.tail_visited.insert(Location::default()); + + rope } pub fn move_head(&mut self, moves: Move) { - let from = self.head; - for _ in 0..moves.amount { - let mut x = from.x; - let mut y = from.y; + let mut x = self.head.x; + let mut y = self.head.y; match moves.dir { - Up => y += 1, - Down => y -= 1, - Left => x -= 1, - Right => x += 1, + Up => { + y += 1; + } + Down => { + y -= 1; + } + Left => { + x -= 1; + } + Right => { + x += 1; + } } let to = Location::new(x, y); @@ -80,7 +96,42 @@ impl Rope { } } - fn move_tail(&mut self, head: Location) {} + fn must_tail_move(&mut self, head: Location) -> bool { + let distance = self.tail.get_distance(head); + + distance >= 2.0 + } + + fn move_tail(&mut self, head: Location) { + if !self.must_tail_move(head) { + return; + } + + let mut tail = self.tail.clone(); + + if tail.y != head.y { + if head.y - tail.y < 0 { + tail.y -= 1; + } else { + tail.y += 1; + } + } + + if tail.x != head.x { + if head.x - tail.x < 0 { + tail.x -= 1; + } else { + tail.x += 1; + } + } + + self.tail = tail; + self.tail_visited.insert(tail); + } + + fn get_tail_pos_count(&self) -> usize { + self.tail_visited.len() + } } // ---------------------------------------------------------------------------- @@ -93,6 +144,10 @@ fn main() { .lines() .map(Move::from_line) .for_each(|m| rope.move_head(m)); + + let tail_positions = rope.get_tail_pos_count(); + + println!("Part 1: Number of tail movements: {}", tail_positions); } #[cfg(test)] @@ -102,4 +157,27 @@ mod tests { fn get_data() -> &'static str { include_str!("test-input.txt") } + + #[test] + fn test_location_get_distance() { + let a = Location::new(0, 0); + + assert_eq!(a.get_distance(Location::new(0, 0)), 0.0); + assert_eq!(a.get_distance(Location::new(1, 0)), 1.0); + assert_eq!(a.get_distance(Location::new(1, 1)), 2.0f64.sqrt()); + } + + #[test] + fn test_get_tail_position_count() { + let mut rope = Rope::new(); + + assert_eq!(rope.get_tail_pos_count(), 1); + + get_data() + .lines() + .map(Move::from_line) + .for_each(|m| rope.move_head(m)); + + assert_eq!(rope.get_tail_pos_count(), 13); + } }