This commit is contained in:
timeshifter
2026-07-04 18:36:44 +02:00
parent 8e07b24c81
commit 219387f8d4
5 changed files with 232 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "day24"
version = "0.1.0"
+6
View File
@@ -0,0 +1,6 @@
[package]
name = "day24"
version = "0.1.0"
edition = "2024"
[dependencies]
+5
View File
@@ -0,0 +1,5 @@
###########
#0.1.....2#
#.#######.#
#4.......3#
###########
+37
View File
@@ -0,0 +1,37 @@
###################################################################################################################################################################################
#.....#.#.....#...#....4#.....#.#...#.........#...#...............#...................#...#.#...........#.#...........#.#.#.#.........#.#.......#...#...........#.....#...#7..#.#.#
###.#.#.###.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.###.#.###.#.#.#.###.###.#.#####.###.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#####.#.#.#.#.#####.#.#.#.###.#.#.#.#.#####.#.#.#.#
#.#.....#.#.#...#.........#.....#.....#.......#.#.#.............#.#.#.#.....#.#.......#.....#.........#...#.......#.....#.#.#.............#...........#.#.....#.#.....#.......#.#.#
#.#.#.#.#.#.#.#.#.#.#####.#####.###.###.#.###.#.###.###.#.#####.#.#.#.#.#.###.#.#.###.#.#.#.#.###.#########.###########.#.#.###.#.#.###.###.#.###.###.#.#.#####.#.###.#.#####.#.###
#...........#...#...#.....#.....#...#.#...#.#.....#.........#...#...#.....#.....#.#.#...#...#...#...#.....#.......#...#...#...............#...#...#.............#.....#.#.....#...#
###.#.#.###.#.#.#.#.###.#.###.#####.#.#.#.#.#.###.###.###.#.#.#.###.#.#.#.#.###.#.#.#.###.#####.#########.#.#.#.#.#.###.#.#.#.#.#####.#.#.#.#.###.#.#.#.#.#.#.#.#####.#.###.#.#.#.#
#3#...#.#.#.#.........#...............#...#.#.....#...#.....#...#.......#...#.....#.#.#...#.....#...#.....#.#.#.....#.....#...........#.#.#.#.....#.#.........#.#...#.#.#.#...#...#
#.###.###.#######.###.#.###.#.#.#.###.###.#######.###.#.#####.#####.#.#.#.#.#######.###.###.###.###.###.#.#########.#.#.#.#.#.#####.###.#.###.#.###.#.#####.###.###.###.#.#.#.###.#
#.#...#.....#.#.............#.....#.#.....#.#.....#.#.#.....#.....#.......#.....#.................#...........#...#.#.....#...#.....#...#.......#.#.....#...#...#.#.#...#...#...#.#
#.###.###.###.#.#.#.#####.#.###.#.#.###.#.#.#.#.#.#.#.#.#.#####.#####.#.#.#.#.#.#.###########.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.###.#.#.#####.#####.#.###.#.#.#.#.#.#.#####.#.###.#.#
#.....#.......#.#.#.#.#...............#...#.#.#.#...#...........#.....#.#...#.................#...#.#.#...#.............#...#.........#...............#...#.#.#.....#.....#.....#.#
#####.#.#######.#.###.#.#.#.#.###.#.#.#.###.###.###.#.#.#.#.#.#.###.#.#.#.#.#######.###.#.###.#.#.#.###.#.#.###.###.#.#.#.#.#####.#####.#.###.#####.###.#.#.#####.#.#.#####.#.#.#.#
#.#...#.........#...#.#...#.......#...#.#.......#...#.#.........#.#.#...#.#.#.#.........#.#.#.......#...#...#...#.#...#.......#...#.....#...#...#.#...#...#...#...........#...#.#.#
#.#####.#.###.#.#.#######.#.###.#.#.#.#########.#.#.#.#.#####.#.#.#######.#.#.###########.#.#########.###.#.#.#.#.###.#.#.###.#########.#.#.#.###.#.#.###.#.#.###.#####.#.###.#.#.#
#.......#.......#...#.#.#...#...#.....#.#...#...#.#.#.#.#...#.....#.#...#...#.............#.......#.......#...#.#.............#.......#.....#...#...#.#.....#.............#...#.#.#
#.#####.###.#####.#.#.#.#.#.#.#.#.#.#.#.#.###.###.#.###.###.#.#.###.#.#.#.#.###.#.###.#.#.#.#.#.#.#.#######.#.#.###.#.#.#.#.###.#.###.###.#####.#.#.#.#.#####.###.#.###.#####.###.#
#..6#...#...#...#...#.#.....#...#.#.#...#...........#.#.#...#.#.#.....#.....#.#.#.....#.......#.................#.#.....#.#.........#...#...#...........#.#2....#.#.......#.#.#.#.#
#.###.###.#.###.#####.#####.#.###.###.#.###.#.#####.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.###.#######.#.#.#.#.#####.#.#.#######.###.#####.###.#####.#####.#.#####.###.#######.###.###
#.#.....#...#...#...........#.#.......#.#...#.#.............#...#...#.....#...#.....#.......#.......#.......#...#...#.......#...#.......#.#...#...#.........#...#...#...#.......#.#
#.#.###.#.#.#.#.###.#######.#.#.###.###.#####.###.#.###.#######.#####.#####.#.#####.#.###.#.#.#.#.#####.###.#.#.#.#.#.#.#.#.#############.###.#.#.#.###.#.#.###.#.#.#.#.#####.#.#.#
#...#.........#.....#...#.#...#.....#...#...#.......#.....#...#...#...#...#.............#.#...#.............#.....#...#.#.#.......#.....#.....#.....#...........#...#...#.....#...#
#.#######.#.#.###.#.#.#.#.#.###.#.#.#.###.#.###.#.#.#.#####.#.#.#.#.#.#.#.#.#####.#####.#####.#.#######.###.#.#.###.#.###.#.#.#.#.#.###.#.#.###.#.#.#######.###.#.###.#.#.#.#.###.#
#.....#.......#...#.#...#.....#...#.#...........#.....#.....#.#.#...#.....#.................#.........#.#.......#...........#...#...#.......#0#...#.....#.......#.#...........#...#
#.#.#.#.#.###.#.#.#.###.###.#.#.###.#.#.#####.#######.#.#.#.#.#.###.###.###.#.#####.###.#####.#.#.###.###.###.###.#####.###.#.#.#.#.#.###.#.#.#.#.#.###.#.###.#.#.#.#.#.#.#####.###
#.#.#...#...#.#.......#.............#...........................#.......#...........#.#...#...#.#...#.....#...#.#.#.#.#.#.......#.#...#...#...#...............#.......#.....#.....#
#.#.###.#.#.#.#.#.#####.#.#####.#.#.###.#.#.#.#.#############.#.###.#.#.#.#.#####.#.#.###.#.###.#.#.#######.###.#.#.#.#.#.###.#.#####.#.###.###.#######.#.###.#####.#.#.#.#######.#
#...#.......#.....#...#...#...#.....#5....#...#.......#.#.#...#...........#.#.......#.#...#.#.......#.#.#...#...#.....#.............#...#...#.....#.................#.....#.#...#.#
#######.#.#.#######.#####.###.#.#.#######.#.#.#.#.#.#.#.#.#.###.#.###.#.#.#.###.###.#.#.#.###.#.###.#.#.###.#.###.#####.###.#######.#.#.#.#.#.#.#.#########.###.#.#.#.#.#.#.#.#.###
#.#.........#...........#.........#.........#.#.#...........#...#.....#...................#...........#...#...#...#.#.......#...#.....#.#.#.....#.#.............#.........#.#...#.#
#.#.#.###.#.###.#.###.#.###.#.#######.#.###.#.#.#.#########.#.###.#.#####.###.#.#.###.#.#.#.###.#.#####.###.#.###.#.#.###.#.#.#.#.#.#.#.#.###.#.#.###.#.#####.#.#.#######.#.#####.#
#.........#.#.....#.....#...#...#.......#.....#.................#...#...#.....#...#...#.#.#.#...#...........#.#.....#.#.....#...#.#...#.......#.........#.....#.....#.......#...#.#
#.#####.#.#.#.#.#.#.#####.###.###.#.#####.###.#####.###.#.#.#.#.#.###.#.#.#.#.#.#####.###.###.#.#.#.#.#.###.#.#.#.#.#.#.#.#####.#.#.#.#.#.#########.#.#.#.###.#.###.#.#.#.#.#.#.###
#.......#...#...#.....#.#...#...#...#.#.............#.....#.............#.#.......#.......#...#...#...#.....#.......#...#...........#.#...#.#.......#...........#.#.....#.....#...#
#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#####.#.###.#.#.#####.#.#.#.#####.#.#.###.###.#.#.#.#.#.#.#.#####.#.#.#####.###.###.###.###.#.#.#.#.#.#.#########.#####.#.#.#.#.#.#
#.#.#.#.............#...#...#.#.....#...........#.........#...#.#.#...#.#.........#.........#.........#.....#.........#...#...#...#..1#.....#.#.#...#.#.....#...#...........#.....#
###################################################################################################################################################################################
+177
View File
@@ -0,0 +1,177 @@
use std::collections::{BTreeSet, HashSet, VecDeque};
#[cfg(debug_assertions)]
const TO_VISIT: usize = 4;
#[cfg(debug_assertions)]
const TO_VISIT_CHAR: char = '4';
#[cfg(debug_assertions)]
const FILENAME: &str = "example.txt";
#[cfg(not(debug_assertions))]
const TO_VISIT: usize = 7;
#[cfg(not(debug_assertions))]
const TO_VISIT_CHAR: char = '7';
#[cfg(not(debug_assertions))]
const FILENAME: &str = "input.txt";
fn main() {
let mut position = (0, 0);
let mut targets = HashSet::new();
let map: Vec<Vec<_>> = std::fs::read_to_string(FILENAME)
.unwrap()
.lines()
.enumerate()
.map(|(y, l)| {
l.chars()
.enumerate()
.map({
|(x, c)| match c {
'#' => Item::Wall,
'0' => {
position = (x, y);
Item::Passage
}
'1'..=TO_VISIT_CHAR => {
targets.insert((x, y));
Item::Passage
}
_ => Item::Passage,
}
})
.collect()
})
.collect();
let grid = Grid::new(map, targets);
let state = State::new(position);
let result = bfs(state.clone(), &grid) - 1; // 460
println!("{result}");
let result = bfs_2(state, &grid); // 668
println!("{result}");
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct State {
position: (usize, usize),
visited: BTreeSet<(usize, usize)>,
}
impl State {
fn is_goal_state(&self) -> bool {
self.visited.len() == TO_VISIT
}
fn is_goal_state_2(&self, start_position: (usize, usize)) -> bool {
self.visited.len() == TO_VISIT && self.position == start_position
}
fn get_neighbor_states(&self, grid: &Grid) -> impl Iterator<Item = State> {
[
(self.position.0 - 1, self.position.1),
(self.position.0, self.position.1 - 1),
(self.position.0, self.position.1 + 1),
(self.position.0 + 1, self.position.1),
]
.into_iter()
.filter(|(x, y)| grid.is_passage(*x, *y))
.map(|(x, y)| {
let mut state = self.clone();
state.position = (x, y);
state
})
}
fn new(position: (usize, usize)) -> Self {
let visited = BTreeSet::new();
Self { position, visited }
}
}
#[derive(Debug)]
struct Grid {
map: Vec<Vec<Item>>,
targets: HashSet<(usize, usize)>,
}
impl Grid {
fn is_target_position(&self, position: (usize, usize)) -> bool {
self.targets.contains(&position)
}
fn is_passage(&self, x: usize, y: usize) -> bool {
match self.map[y][x] {
Item::Passage => true,
Item::Wall => false,
}
}
fn new(map: Vec<Vec<Item>>, targets: HashSet<(usize, usize)>) -> Self {
Self { map, targets }
}
}
#[derive(Debug)]
enum Item {
Passage,
Wall,
}
fn bfs(start: State, grid: &Grid) -> usize {
let mut queue = VecDeque::new();
let mut visited = HashSet::new();
visited.insert(start.clone());
queue.push_back((start, 0));
while let Some((mut state, distance)) = queue.pop_front() {
if state.is_goal_state() {
return distance;
}
if grid.is_target_position(state.position) {
state.visited.insert(state.position);
}
for neighbor in state.get_neighbor_states(grid) {
if !visited.contains(&neighbor) {
visited.insert(neighbor.clone());
queue.push_back((neighbor, distance + 1));
}
}
}
panic!("goal unreachable");
}
fn bfs_2(start: State, grid: &Grid) -> usize {
let mut queue = VecDeque::new();
let mut visited = HashSet::new();
visited.insert(start.clone());
let start_position = start.position;
queue.push_back((start, 0));
while let Some((mut state, distance)) = queue.pop_front() {
if state.is_goal_state_2(start_position) {
return distance;
}
if grid.is_target_position(state.position) {
state.visited.insert(state.position);
}
for neighbor in state.get_neighbor_states(grid) {
if !visited.contains(&neighbor) {
visited.insert(neighbor.clone());
queue.push_back((neighbor, distance + 1));
}
}
}
panic!("goal unreachable");
}