add 24
This commit is contained in:
Generated
+7
@@ -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"
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "day24"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
###########
|
||||||
|
#0.1.....2#
|
||||||
|
#.#######.#
|
||||||
|
#4.......3#
|
||||||
|
###########
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
###################################################################################################################################################################################
|
||||||
|
#.....#.#.....#...#....4#.....#.#...#.........#...#...............#...................#...#.#...........#.#...........#.#.#.#.........#.#.......#...#...........#.....#...#7..#.#.#
|
||||||
|
###.#.#.###.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.###.#.###.#.#.#.###.###.#.#####.###.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#####.#.#.#.#.#####.#.#.#.###.#.#.#.#.#####.#.#.#.#
|
||||||
|
#.#.....#.#.#...#.........#.....#.....#.......#.#.#.............#.#.#.#.....#.#.......#.....#.........#...#.......#.....#.#.#.............#...........#.#.....#.#.....#.......#.#.#
|
||||||
|
#.#.#.#.#.#.#.#.#.#.#####.#####.###.###.#.###.#.###.###.#.#####.#.#.#.#.#.###.#.#.###.#.#.#.#.###.#########.###########.#.#.###.#.#.###.###.#.###.###.#.#.#####.#.###.#.#####.#.###
|
||||||
|
#...........#...#...#.....#.....#...#.#...#.#.....#.........#...#...#.....#.....#.#.#...#...#...#...#.....#.......#...#...#...............#...#...#.............#.....#.#.....#...#
|
||||||
|
###.#.#.###.#.#.#.#.###.#.###.#####.#.#.#.#.#.###.###.###.#.#.#.###.#.#.#.#.###.#.#.#.###.#####.#########.#.#.#.#.#.###.#.#.#.#.#####.#.#.#.#.###.#.#.#.#.#.#.#.#####.#.###.#.#.#.#
|
||||||
|
#3#...#.#.#.#.........#...............#...#.#.....#...#.....#...#.......#...#.....#.#.#...#.....#...#.....#.#.#.....#.....#...........#.#.#.#.....#.#.........#.#...#.#.#.#...#...#
|
||||||
|
#.###.###.#######.###.#.###.#.#.#.###.###.#######.###.#.#####.#####.#.#.#.#.#######.###.###.###.###.###.#.#########.#.#.#.#.#.#####.###.#.###.#.###.#.#####.###.###.###.#.#.#.###.#
|
||||||
|
#.#...#.....#.#.............#.....#.#.....#.#.....#.#.#.....#.....#.......#.....#.................#...........#...#.#.....#...#.....#...#.......#.#.....#...#...#.#.#...#...#...#.#
|
||||||
|
#.###.###.###.#.#.#.#####.#.###.#.#.###.#.#.#.#.#.#.#.#.#.#####.#####.#.#.#.#.#.#.###########.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.###.#.#.#####.#####.#.###.#.#.#.#.#.#.#####.#.###.#.#
|
||||||
|
#.....#.......#.#.#.#.#...............#...#.#.#.#...#...........#.....#.#...#.................#...#.#.#...#.............#...#.........#...............#...#.#.#.....#.....#.....#.#
|
||||||
|
#####.#.#######.#.###.#.#.#.#.###.#.#.#.###.###.###.#.#.#.#.#.#.###.#.#.#.#.#######.###.#.###.#.#.#.###.#.#.###.###.#.#.#.#.#####.#####.#.###.#####.###.#.#.#####.#.#.#####.#.#.#.#
|
||||||
|
#.#...#.........#...#.#...#.......#...#.#.......#...#.#.........#.#.#...#.#.#.#.........#.#.#.......#...#...#...#.#...#.......#...#.....#...#...#.#...#...#...#...........#...#.#.#
|
||||||
|
#.#####.#.###.#.#.#######.#.###.#.#.#.#########.#.#.#.#.#####.#.#.#######.#.#.###########.#.#########.###.#.#.#.#.###.#.#.###.#########.#.#.#.###.#.#.###.#.#.###.#####.#.###.#.#.#
|
||||||
|
#.......#.......#...#.#.#...#...#.....#.#...#...#.#.#.#.#...#.....#.#...#...#.............#.......#.......#...#.#.............#.......#.....#...#...#.#.....#.............#...#.#.#
|
||||||
|
#.#####.###.#####.#.#.#.#.#.#.#.#.#.#.#.#.###.###.#.###.###.#.#.###.#.#.#.#.###.#.###.#.#.#.#.#.#.#.#######.#.#.###.#.#.#.#.###.#.###.###.#####.#.#.#.#.#####.###.#.###.#####.###.#
|
||||||
|
#..6#...#...#...#...#.#.....#...#.#.#...#...........#.#.#...#.#.#.....#.....#.#.#.....#.......#.................#.#.....#.#.........#...#...#...........#.#2....#.#.......#.#.#.#.#
|
||||||
|
#.###.###.#.###.#####.#####.#.###.###.#.###.#.#####.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.###.#######.#.#.#.#.#####.#.#.#######.###.#####.###.#####.#####.#.#####.###.#######.###.###
|
||||||
|
#.#.....#...#...#...........#.#.......#.#...#.#.............#...#...#.....#...#.....#.......#.......#.......#...#...#.......#...#.......#.#...#...#.........#...#...#...#.......#.#
|
||||||
|
#.#.###.#.#.#.#.###.#######.#.#.###.###.#####.###.#.###.#######.#####.#####.#.#####.#.###.#.#.#.#.#####.###.#.#.#.#.#.#.#.#.#############.###.#.#.#.###.#.#.###.#.#.#.#.#####.#.#.#
|
||||||
|
#...#.........#.....#...#.#...#.....#...#...#.......#.....#...#...#...#...#.............#.#...#.............#.....#...#.#.#.......#.....#.....#.....#...........#...#...#.....#...#
|
||||||
|
#.#######.#.#.###.#.#.#.#.#.###.#.#.#.###.#.###.#.#.#.#####.#.#.#.#.#.#.#.#.#####.#####.#####.#.#######.###.#.#.###.#.###.#.#.#.#.#.###.#.#.###.#.#.#######.###.#.###.#.#.#.#.###.#
|
||||||
|
#.....#.......#...#.#...#.....#...#.#...........#.....#.....#.#.#...#.....#.................#.........#.#.......#...........#...#...#.......#0#...#.....#.......#.#...........#...#
|
||||||
|
#.#.#.#.#.###.#.#.#.###.###.#.#.###.#.#.#####.#######.#.#.#.#.#.###.###.###.#.#####.###.#####.#.#.###.###.###.###.#####.###.#.#.#.#.#.###.#.#.#.#.#.###.#.###.#.#.#.#.#.#.#####.###
|
||||||
|
#.#.#...#...#.#.......#.............#...........................#.......#...........#.#...#...#.#...#.....#...#.#.#.#.#.#.......#.#...#...#...#...............#.......#.....#.....#
|
||||||
|
#.#.###.#.#.#.#.#.#####.#.#####.#.#.###.#.#.#.#.#############.#.###.#.#.#.#.#####.#.#.###.#.###.#.#.#######.###.#.#.#.#.#.###.#.#####.#.###.###.#######.#.###.#####.#.#.#.#######.#
|
||||||
|
#...#.......#.....#...#...#...#.....#5....#...#.......#.#.#...#...........#.#.......#.#...#.#.......#.#.#...#...#.....#.............#...#...#.....#.................#.....#.#...#.#
|
||||||
|
#######.#.#.#######.#####.###.#.#.#######.#.#.#.#.#.#.#.#.#.###.#.###.#.#.#.###.###.#.#.#.###.#.###.#.#.###.#.###.#####.###.#######.#.#.#.#.#.#.#.#########.###.#.#.#.#.#.#.#.#.###
|
||||||
|
#.#.........#...........#.........#.........#.#.#...........#...#.....#...................#...........#...#...#...#.#.......#...#.....#.#.#.....#.#.............#.........#.#...#.#
|
||||||
|
#.#.#.###.#.###.#.###.#.###.#.#######.#.###.#.#.#.#########.#.###.#.#####.###.#.#.###.#.#.#.###.#.#####.###.#.###.#.#.###.#.#.#.#.#.#.#.#.###.#.#.###.#.#####.#.#.#######.#.#####.#
|
||||||
|
#.........#.#.....#.....#...#...#.......#.....#.................#...#...#.....#...#...#.#.#.#...#...........#.#.....#.#.....#...#.#...#.......#.........#.....#.....#.......#...#.#
|
||||||
|
#.#####.#.#.#.#.#.#.#####.###.###.#.#####.###.#####.###.#.#.#.#.#.###.#.#.#.#.#.#####.###.###.#.#.#.#.#.###.#.#.#.#.#.#.#.#####.#.#.#.#.#.#########.#.#.#.###.#.###.#.#.#.#.#.#.###
|
||||||
|
#.......#...#...#.....#.#...#...#...#.#.............#.....#.............#.#.......#.......#...#...#...#.....#.......#...#...........#.#...#.#.......#...........#.#.....#.....#...#
|
||||||
|
#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#####.#.###.#.#.#####.#.#.#.#####.#.#.###.###.#.#.#.#.#.#.#.#####.#.#.#####.###.###.###.###.#.#.#.#.#.#.#########.#####.#.#.#.#.#.#
|
||||||
|
#.#.#.#.............#...#...#.#.....#...........#.........#...#.#.#...#.#.........#.........#.........#.....#.........#...#...#...#..1#.....#.#.#...#.#.....#...#...........#.....#
|
||||||
|
###################################################################################################################################################################################
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user