Complete day 9

This commit is contained in:
Timothy Warren 2022-12-13 17:11:45 -05:00
parent cd870f4572
commit eb767eb50b
2 changed files with 83 additions and 33 deletions

View File

@ -53,25 +53,35 @@ impl Location {
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct Rope { struct Rope {
head: Location, knots: Vec<Location>,
tail: Location, knot_count: usize,
head_visited: HashSet<Location>, head_visited: HashSet<Location>,
tail_visited: HashSet<Location>, tail_visited: HashSet<Location>,
} }
impl Rope { impl Rope {
pub fn new() -> Self { pub fn new(knot_count: usize) -> Self {
let mut rope = Self::default(); let mut rope = Self::default();
rope.knot_count = knot_count;
rope.head_visited.insert(Location::default()); rope.head_visited.insert(Location::default());
rope.tail_visited.insert(Location::default()); rope.tail_visited.insert(Location::default());
rope.knots.resize_with(knot_count, Location::default);
rope rope
} }
pub fn get_knot(&self, idx: usize) -> Location {
self.knots[idx]
}
pub fn is_tail(&self, idx: usize) -> bool {
idx == (self.knot_count - 1)
}
pub fn move_head(&mut self, moves: Move) { pub fn move_head(&mut self, moves: Move) {
for _ in 0..moves.amount { for _ in 0..moves.amount {
let mut x = self.head.x; let mut x = self.knots[0].x;
let mut y = self.head.y; let mut y = self.knots[0].y;
match moves.dir { match moves.dir {
Up => { Up => {
@ -89,44 +99,50 @@ impl Rope {
} }
let to = Location::new(x, y); let to = Location::new(x, y);
self.knots[0] = to;
self.move_tail(to); for i in 1..self.knot_count {
self.head = to; self.move_knot(i, i - 1);
self.head_visited.insert(to); }
// self.head = to;
// self.head_visited.insert(to);
} }
} }
fn must_tail_move(&mut self, head: Location) -> bool { fn must_move(&mut self, current: usize, prev: usize) -> bool {
let distance = self.tail.get_distance(head); let distance = self.get_knot(current).get_distance(self.get_knot(prev));
distance >= 2.0 distance >= 2.0
} }
fn move_tail(&mut self, head: Location) { fn move_knot(&mut self, c: usize, p: usize) {
if !self.must_tail_move(head) { if !self.must_move(c, p) {
return; return;
} }
let mut tail = self.tail.clone(); let mut current = self.get_knot(c);
let prev = self.get_knot(p);
if tail.y != head.y { if current.y != prev.y {
if head.y - tail.y < 0 { if prev.y - current.y < 0 {
tail.y -= 1; current.y -= 1;
} else { } else {
tail.y += 1; current.y += 1;
} }
} }
if tail.x != head.x { if current.x != prev.x {
if head.x - tail.x < 0 { if prev.x - current.x < 0 {
tail.x -= 1; current.x -= 1;
} else { } else {
tail.x += 1; current.x += 1;
} }
} }
self.tail = tail; self.knots[c] = current;
self.tail_visited.insert(tail); if self.is_tail(c) {
self.tail_visited.insert(current);
}
} }
fn get_tail_pos_count(&self) -> usize { fn get_tail_pos_count(&self) -> usize {
@ -138,7 +154,8 @@ impl Rope {
fn main() { fn main() {
let file_str = include_str!("input.txt"); let file_str = include_str!("input.txt");
let mut rope = Rope::new();
let mut rope = Rope::new(2);
file_str file_str
.lines() .lines()
@ -147,17 +164,30 @@ fn main() {
let tail_positions = rope.get_tail_pos_count(); let tail_positions = rope.get_tail_pos_count();
println!("Part 1: Number of tail movements: {}", tail_positions); println!(
"Part 1: Number of tail movements with 2 knots: {}",
tail_positions
);
let mut rope = Rope::new(10);
file_str
.lines()
.map(Move::from_line)
.for_each(|m| rope.move_head(m));
let tail_positions = rope.get_tail_pos_count();
println!(
"Part 2: Number of tail movements with 10 knots: {}",
tail_positions
);
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
fn get_data() -> &'static str {
include_str!("test-input.txt")
}
#[test] #[test]
fn test_location_get_distance() { fn test_location_get_distance() {
let a = Location::new(0, 0); let a = Location::new(0, 0);
@ -169,15 +199,27 @@ mod tests {
#[test] #[test]
fn test_get_tail_position_count() { fn test_get_tail_position_count() {
let mut rope = Rope::new(); let file_str = include_str!("test-input.txt");
let mut rope = Rope::new(2);
assert_eq!(rope.get_tail_pos_count(), 1); file_str
get_data()
.lines() .lines()
.map(Move::from_line) .map(Move::from_line)
.for_each(|m| rope.move_head(m)); .for_each(|m| rope.move_head(m));
assert_eq!(rope.get_tail_pos_count(), 13); assert_eq!(rope.get_tail_pos_count(), 13);
} }
#[test]
fn test_get_tail_position_count_10_knots() {
let file_str = include_str!("test-input2.txt");
let mut rope = Rope::new(10);
file_str
.lines()
.map(Move::from_line)
.for_each(|m| rope.move_head(m));
assert_eq!(rope.get_tail_pos_count(), 36);
}
} }

8
day9/src/test-input2.txt Normal file
View File

@ -0,0 +1,8 @@
R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20