Day 9, both puzzles
This commit is contained in:
parent
9a64352fc3
commit
3f05695ea3
14
src/bin/d9p1.rs
Normal file
14
src/bin/d9p1.rs
Normal 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
14
src/bin/d9p2.rs
Normal 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
135
src/day9.rs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
@ -6,4 +6,5 @@ pub mod day5;
|
|||||||
pub mod day6;
|
pub mod day6;
|
||||||
pub mod day7;
|
pub mod day7;
|
||||||
pub mod day8;
|
pub mod day8;
|
||||||
|
pub mod day9;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user