Complete day 9 part 1

This commit is contained in:
Timothy Warren 2022-12-13 16:19:26 -05:00
parent 9f337f8a6d
commit 5717adcf1c

View File

@ -11,7 +11,7 @@ use Direction::*;
struct Move { struct Move {
dir: Direction, dir: Direction,
amount: usize, amount: isize,
} }
impl Move { impl Move {
@ -25,7 +25,7 @@ impl Move {
"R" => Right, "R" => Right,
_ => panic!("Invalid direction!"), _ => panic!("Invalid direction!"),
}; };
let amount = parts[1].parse::<usize>().unwrap(); let amount = parts[1].parse::<isize>().unwrap();
Move { dir, amount } Move { dir, amount }
} }
@ -33,17 +33,23 @@ impl Move {
#[derive(Debug, Default, Copy, Clone, Eq, Hash, PartialEq)] #[derive(Debug, Default, Copy, Clone, Eq, Hash, PartialEq)]
struct Location { struct Location {
x: usize, x: isize,
y: usize, y: isize,
} }
impl Location { impl Location {
fn new(x: usize, y: usize) -> Self { fn new(x: isize, y: isize) -> Self {
Location { x, y } 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)] #[derive(Debug, Default)]
struct Rope { struct Rope {
@ -55,21 +61,31 @@ struct Rope {
impl Rope { impl Rope {
pub fn new() -> Self { 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) { pub fn move_head(&mut self, moves: Move) {
let from = self.head;
for _ in 0..moves.amount { for _ in 0..moves.amount {
let mut x = from.x; let mut x = self.head.x;
let mut y = from.y; let mut y = self.head.y;
match moves.dir { match moves.dir {
Up => y += 1, Up => {
Down => y -= 1, y += 1;
Left => x -= 1, }
Right => x += 1, Down => {
y -= 1;
}
Left => {
x -= 1;
}
Right => {
x += 1;
}
} }
let to = Location::new(x, y); 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() .lines()
.map(Move::from_line) .map(Move::from_line)
.for_each(|m| rope.move_head(m)); .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)] #[cfg(test)]
@ -102,4 +157,27 @@ mod tests {
fn get_data() -> &'static str { fn get_data() -> &'static str {
include_str!("test-input.txt") 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);
}
} }