From 3f05695ea3f19b331c3f77aa0090dc340edc7474 Mon Sep 17 00:00:00 2001 From: jazzpi Date: Thu, 15 Dec 2022 11:35:33 +0100 Subject: [PATCH] Day 9, both puzzles --- src/bin/d9p1.rs | 14 +++++ src/bin/d9p2.rs | 14 +++++ src/day9.rs | 135 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 4 files changed, 164 insertions(+) create mode 100644 src/bin/d9p1.rs create mode 100644 src/bin/d9p2.rs create mode 100644 src/day9.rs diff --git a/src/bin/d9p1.rs b/src/bin/d9p1.rs new file mode 100644 index 0000000..10a623a --- /dev/null +++ b/src/bin/d9p1.rs @@ -0,0 +1,14 @@ +use aoc22::{day9, util}; + +pub fn main() { + let motions = day9::parse_motions(&util::parse_input()); + let mut state = day9::State::new(1); + + for motion in &motions { + day9::execute_motion(&mut state, &motion); + } + + println!("State after all motions:"); + state.print(); + println!("Visited fields: {}", state.visited.len()); +} diff --git a/src/bin/d9p2.rs b/src/bin/d9p2.rs new file mode 100644 index 0000000..b4cf5d6 --- /dev/null +++ b/src/bin/d9p2.rs @@ -0,0 +1,14 @@ +use aoc22::{day9, util}; + +pub fn main() { + let motions = day9::parse_motions(&util::parse_input()); + let mut state = day9::State::new(9); + + for motion in &motions { + day9::execute_motion(&mut state, &motion); + } + + println!("State after all motions:"); + state.print(); + println!("Visited fields: {}", state.visited.len()); +} diff --git a/src/day9.rs b/src/day9.rs new file mode 100644 index 0000000..1e8c1d8 --- /dev/null +++ b/src/day9.rs @@ -0,0 +1,135 @@ +use std::collections::HashSet; + +#[derive(Debug)] +pub enum Dir { + Left, + Right, + Up, + Down, +} + +pub type Motion = (Dir, usize); + +pub fn parse_motions(input: &String) -> Vec { + let mut result = Vec::new(); + + for line in input.lines() { + let (d, n) = line.split_once(' ').unwrap(); + let dir = match d { + "L" => Dir::Left, + "R" => Dir::Right, + "U" => Dir::Up, + "D" => Dir::Down, + _ => panic!("Unknown direction {}", d), + }; + let n = n.parse().unwrap(); + result.push((dir, n)); + } + + result +} + +pub type Coord = (i64, i64); + +pub struct State { + pub head: Coord, + pub knots: Vec, + pub visited: HashSet, +} + +impl State { + pub fn new(n_knots: usize) -> State { + let mut s = State { + head: (0, 0), + knots: vec![(0, 0); n_knots], + visited: HashSet::new(), + }; + s.visited.insert((0, 0)); + s + } + + pub fn print(&self) { + let knots_x: Vec = self.knots.iter().map(|v| v.0).collect(); + let visited_x: Vec = self.visited.iter().map(|v| v.0).collect(); + let knots_y: Vec = self.knots.iter().map(|v| v.1).collect(); + let visited_y: Vec = self.visited.iter().map(|v| v.1).collect(); + let min_x = 0 + .min(self.head.0) + .min(*knots_x.iter().min().unwrap()) + .min(*visited_x.iter().min().unwrap()); + let max_x = 0 + .max(self.head.0) + .max(*knots_x.iter().max().unwrap()) + .max(*visited_x.iter().max().unwrap()); + let min_y = 0 + .min(self.head.1) + .min(*knots_y.iter().min().unwrap()) + .min(*visited_y.iter().min().unwrap()); + let max_y = 0 + .max(self.head.1) + .max(*knots_y.iter().max().unwrap()) + .max(*visited_y.iter().max().unwrap()); + + for y in min_y..max_y + 1 { + 'x: for x in min_x..max_x + 1 { + let c = (x, y); + if self.head == c { + print!("H"); + } else { + for (i, knot) in self.knots.iter().enumerate() { + if c == *knot { + print!("{}", i + 1); + continue 'x; + } + } + if self.visited.contains(&c) { + print!("#"); + } else if c == (0, 0) { + print!("s"); + } else { + print!("."); + } + } + } + print!("\n"); + } + } +} + +pub fn execute_motion(state: &mut State, motion: &Motion) { + for _ in 0..motion.1 { + let head = &mut state.head; + *head = match motion.0 { + Dir::Left => (head.0 - 1, head.1), + Dir::Right => (head.0 + 1, head.1), + Dir::Up => (head.0, head.1 - 1), + Dir::Down => (head.0, head.1 + 1), + }; + tail_catchup(state); + state.visited.insert(*state.knots.last().unwrap()); + } +} + +pub fn tail_catchup(state: &mut State) { + let mut prev = state.head.clone(); + let knots = &mut state.knots; + for i in 0..knots.len() { + let knot = knots.get_mut(i).unwrap(); + let dx = prev.0 - knot.0; + let dy = prev.1 - knot.1; + if dx > 1 { + knot.0 += 1; + knot.1 += dy / dy.abs().max(1); + } else if dx < -1 { + knot.0 -= 1; + knot.1 += dy / dy.abs().max(1); + } else if dy > 1 { + knot.1 += 1; + knot.0 += dx / dx.abs().max(1); + } else if dy < -1 { + knot.1 -= 1; + knot.0 += dx / dx.abs().max(1); + } + prev = knot.clone(); + } +} diff --git a/src/lib.rs b/src/lib.rs index 212f967..73bc0a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,4 +6,5 @@ pub mod day5; pub mod day6; pub mod day7; pub mod day8; +pub mod day9; pub mod util;