y2024d16p2

This commit is contained in:
Fabian Schmidt 2024-12-17 11:22:59 +01:00
parent ff241d76cb
commit e55dcd47a3

View File

@ -1,7 +1,4 @@
use std::{ use std::{collections::HashMap, error::Error};
collections::{HashMap, HashSet},
error::Error,
};
use itertools::Itertools; use itertools::Itertools;
@ -37,6 +34,7 @@ pub fn process_part1(input: &str) -> usize {
}]; }];
let mut arrived: Vec<Reindeer> = Vec::new(); let mut arrived: Vec<Reindeer> = Vec::new();
let mut visited = HashMap::new(); let mut visited = HashMap::new();
let mut iter = 0;
while !next_paths.is_empty() { while !next_paths.is_empty() {
next_paths = next_paths next_paths = next_paths
.iter() .iter()
@ -59,7 +57,9 @@ pub fn process_part1(input: &str) -> usize {
arrived.push(arrived_reindeer); arrived.push(arrived_reindeer);
} }
} }
iter += 1;
} }
println!("Iterations to goal {iter}");
arrived.iter().map(|reindeer| reindeer.score).min().unwrap() arrived.iter().map(|reindeer| reindeer.score).min().unwrap()
} }
@ -89,15 +89,15 @@ pub fn process_part2(input: &str) -> usize {
.collect_vec() .collect_vec()
}) })
.collect_vec(); .collect_vec();
let mut visited = HashSet::new(); let mut smallest_score = usize::MAX;
visited.insert(start); let mut visited = HashMap::new();
visited.insert((start, Orientation::East), 0);
let mut next_paths = vec![Reindeer { let mut next_paths = vec![Reindeer {
coords: start, coords: start,
visited, visited: visited.clone(),
..Default::default() ..Default::default()
}]; }];
let mut arrived: Vec<Reindeer> = Vec::new(); let mut arrived: Vec<Reindeer> = Vec::new();
let mut visited = HashMap::new();
while !next_paths.is_empty() { while !next_paths.is_empty() {
next_paths = next_paths next_paths = next_paths
.iter() .iter()
@ -105,33 +105,47 @@ pub fn process_part2(input: &str) -> usize {
.collect_vec() .collect_vec()
.concat(); .concat();
for (idx, reindeer) in next_paths.clone().iter().enumerate().rev() { for (idx, reindeer) in next_paths.clone().iter().enumerate().rev() {
if let Some(_score) = visited.get_mut(&reindeer.coords) { if reindeer.score > smallest_score
//if *score < reindeer.score { || reindeer
// next_paths.remove(idx); .visited
// continue; .contains_key(&(reindeer.coords, reindeer.orientation))
//} else { {
// *score = reindeer.score; next_paths.remove(idx);
//} continue;
} else {
visited.insert(reindeer.coords, reindeer.score);
} }
if reindeer.state == ReindeerState::Arrived { next_paths[idx]
.visited
.insert((reindeer.coords, reindeer.orientation), reindeer.score);
if let Some(score) = visited.get_mut(&(reindeer.coords, reindeer.orientation)) {
if *score < reindeer.score {
next_paths.remove(idx);
continue;
} else {
*score = reindeer.score;
}
} else {
visited.insert((reindeer.coords, reindeer.orientation), reindeer.score);
}
if reindeer.state == ReindeerState::Arrived && reindeer.score <= smallest_score {
smallest_score = reindeer.score;
let arrived_reindeer = next_paths.remove(idx); let arrived_reindeer = next_paths.remove(idx);
arrived.push(arrived_reindeer); arrived.push(arrived_reindeer);
} }
} }
arrived.retain(|reindeer| reindeer.score == smallest_score);
} }
let min_score = arrived.iter().map(|reindeer| reindeer.score).min().unwrap();
let visited = arrived let visited = arrived
.into_iter() .iter()
.filter(|reindeer| reindeer.score == min_score) .map(|reindeer| {
.collect_vec(); reindeer
println!("{visited:?}"); .visited
let visited = visited .keys()
.into_iter() .map(|(coords, _)| coords)
.map(|reindeer| reindeer.visited.into_iter().collect_vec()) .collect_vec()
})
.collect_vec() .collect_vec()
.concat(); .concat();
log_maze(&grid, &arrived);
visited.iter().unique().count() visited.iter().unique().count()
} }
@ -177,7 +191,7 @@ struct Reindeer {
orientation: Orientation, orientation: Orientation,
coords: (usize, usize), coords: (usize, usize),
score: usize, score: usize,
visited: HashSet<(usize, usize)>, visited: HashMap<((usize, usize), Orientation), usize>,
state: ReindeerState, state: ReindeerState,
} }
@ -195,28 +209,23 @@ impl Reindeer {
Orientation::South => (self.coords.0, self.coords.1 + 1), Orientation::South => (self.coords.0, self.coords.1 + 1),
Orientation::North => (self.coords.0, self.coords.1 - 1), Orientation::North => (self.coords.0, self.coords.1 - 1),
}; };
let mut visited = self.visited.clone();
visited.insert(coords);
if tile == GridTile::Wall { if tile == GridTile::Wall {
Reindeer { Reindeer {
state: ReindeerState::Stuck, state: ReindeerState::Stuck,
visited, ..self.clone()
..*self
} }
} else if tile == GridTile::End { } else if tile == GridTile::End {
Reindeer { Reindeer {
score: self.score + 1, score: self.score + 1,
state: ReindeerState::Arrived, state: ReindeerState::Arrived,
coords, coords,
visited, ..self.clone()
..*self
} }
} else { } else {
Reindeer { Reindeer {
score: self.score + 1, score: self.score + 1,
coords, coords,
visited, ..self.clone()
..*self
} }
} }
} }
@ -234,13 +243,10 @@ impl Reindeer {
Orientation::South => (self.coords.0 - 1, self.coords.1), Orientation::South => (self.coords.0 - 1, self.coords.1),
Orientation::North => (self.coords.0 + 1, self.coords.1), Orientation::North => (self.coords.0 + 1, self.coords.1),
}; };
let mut visited = self.visited.clone();
visited.insert(coords);
if tile == GridTile::Wall { if tile == GridTile::Wall {
Reindeer { Reindeer {
state: ReindeerState::Stuck, state: ReindeerState::Stuck,
visited, ..self.clone()
..*self
} }
} else if tile == GridTile::End { } else if tile == GridTile::End {
Reindeer { Reindeer {
@ -248,15 +254,14 @@ impl Reindeer {
state: ReindeerState::Arrived, state: ReindeerState::Arrived,
coords, coords,
orientation: self.orientation.turn_clockwise(), orientation: self.orientation.turn_clockwise(),
visited, ..self.clone()
} }
} else { } else {
Reindeer { Reindeer {
score: self.score + 1001, score: self.score + 1001,
orientation: self.orientation.turn_clockwise(), orientation: self.orientation.turn_clockwise(),
coords, coords,
visited, ..self.clone()
..*self
} }
} }
} }
@ -274,13 +279,10 @@ impl Reindeer {
Orientation::South => (self.coords.0 + 1, self.coords.1), Orientation::South => (self.coords.0 + 1, self.coords.1),
Orientation::North => (self.coords.0 - 1, self.coords.1), Orientation::North => (self.coords.0 - 1, self.coords.1),
}; };
let mut visited = self.visited.clone();
visited.insert(coords);
if tile == GridTile::Wall { if tile == GridTile::Wall {
Reindeer { Reindeer {
state: ReindeerState::Stuck, state: ReindeerState::Stuck,
visited, ..self.clone()
..*self
} }
} else if tile == GridTile::End { } else if tile == GridTile::End {
Reindeer { Reindeer {
@ -288,15 +290,14 @@ impl Reindeer {
state: ReindeerState::Arrived, state: ReindeerState::Arrived,
coords, coords,
orientation: self.orientation.turn_counterclockwise(), orientation: self.orientation.turn_counterclockwise(),
visited, ..self.clone()
} }
} else { } else {
Reindeer { Reindeer {
score: self.score + 1001, score: self.score + 1001,
orientation: self.orientation.turn_counterclockwise(), orientation: self.orientation.turn_counterclockwise(),
coords, coords,
visited, ..self.clone()
..*self
} }
} }
} }
@ -342,6 +343,47 @@ impl TryFrom<char> for GridTile {
} }
} }
fn log_maze(grid: &[Vec<GridTile>], visited: &Vec<Reindeer>) {
for (yidx, row) in grid.iter().enumerate() {
for (xidx, tile) in row.iter().enumerate() {
let contains = {
let mut contains = false;
for reindeer in visited {
if reindeer
.visited
.contains_key(&((xidx, yidx), Orientation::East))
|| reindeer
.visited
.contains_key(&((xidx, yidx), Orientation::West))
|| reindeer
.visited
.contains_key(&((xidx, yidx), Orientation::North))
|| reindeer
.visited
.contains_key(&((xidx, yidx), Orientation::South))
{
contains = true;
break;
}
}
contains
};
if contains && !(*tile == GridTile::Start || *tile == GridTile::End) {
print!("O");
} else if *tile == GridTile::Wall {
print!("#");
} else if *tile == GridTile::Path {
print!(".");
} else if *tile == GridTile::Start {
print!("S");
} else if *tile == GridTile::End {
print!("E");
}
}
println!();
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;