Day 9, both puzzles

This commit is contained in:
jazzpi 2022-12-15 11:35:33 +01:00
parent 9a64352fc3
commit 3f05695ea3
4 changed files with 164 additions and 0 deletions

14
src/bin/d9p1.rs Normal file
View File

@ -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());
}

14
src/bin/d9p2.rs Normal file
View File

@ -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());
}

135
src/day9.rs Normal file
View File

@ -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<Motion> {
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<Coord>,
pub visited: HashSet<Coord>,
}
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<i64> = self.knots.iter().map(|v| v.0).collect();
let visited_x: Vec<i64> = self.visited.iter().map(|v| v.0).collect();
let knots_y: Vec<i64> = self.knots.iter().map(|v| v.1).collect();
let visited_y: Vec<i64> = 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();
}
}

View File

@ -6,4 +6,5 @@ pub mod day5;
pub mod day6;
pub mod day7;
pub mod day8;
pub mod day9;
pub mod util;