day 10 part 1 first attempt
This commit is contained in:
parent
fe9cf52452
commit
998dfd5c61
2 changed files with 286 additions and 0 deletions
146
src/bin/day10.rs
Normal file
146
src/bin/day10.rs
Normal file
|
@ -0,0 +1,146 @@
|
|||
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
||||
|
||||
use aoc23::read;
|
||||
use chumsky::prelude::*;
|
||||
use std::{
|
||||
collections::{BTreeSet, HashMap, HashSet},
|
||||
fmt::{self, Debug}
|
||||
};
|
||||
|
||||
macro_rules! cells {
|
||||
($($ident:ident = $char:literal),+) => {
|
||||
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||
enum Cell { $($ident),+ }
|
||||
|
||||
impl Cell {
|
||||
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
|
||||
choice((
|
||||
$(just($char).map(|_| Self::$ident)),+
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Cell {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
$(Self::$ident => write!(f, "{}", $char)),+
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cells! {
|
||||
NorthSouthPipe = '|',
|
||||
EastWestPipe = '-',
|
||||
NorthEastPipe = 'L',
|
||||
NorthWestPipe = 'J',
|
||||
SouthWestPipe = '7',
|
||||
SouthEastPipe = 'F',
|
||||
Ground = '.',
|
||||
Start = 'S'
|
||||
}
|
||||
|
||||
fn parser() -> impl Parser<char, Vec<Vec<Cell>>, Error = Simple<char>> {
|
||||
Cell::parser()
|
||||
.repeated()
|
||||
.then_ignore(just("\n"))
|
||||
.repeated()
|
||||
.then_ignore(end())
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||
struct Node {
|
||||
row: usize,
|
||||
col: usize
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct AdjList(HashMap<Node, HashSet<Node>>);
|
||||
|
||||
impl AdjList {
|
||||
fn add_edge(&mut self, from: Node, to: Node) {
|
||||
self.0.entry(from).or_default().insert(to);
|
||||
// doesn't work that way due to the way we handle start
|
||||
// self.0.entry(to).or_default().insert(from);
|
||||
}
|
||||
|
||||
fn dij(&self, start: Node) -> HashMap<Node, usize> {
|
||||
let mut dists = HashMap::new();
|
||||
let mut q: BTreeSet<(usize, Node)> = BTreeSet::new();
|
||||
|
||||
dists.insert(start, 0);
|
||||
q.insert((0, start));
|
||||
|
||||
while let Some((dist, node)) = q.pop_first() {
|
||||
for next in self.0.get(&node).into_iter().flatten() {
|
||||
let next_dist = dists.get(next);
|
||||
if next_dist.map(|d| *d > dist + 1).unwrap_or(true) {
|
||||
if let Some(old_dist) = next_dist {
|
||||
q.remove(&(*old_dist, *next));
|
||||
}
|
||||
dists.insert(*next, dist + 1);
|
||||
q.insert((dist + 1, *next));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dists
|
||||
}
|
||||
}
|
||||
|
||||
const NORTH: (isize, isize) = (-1, 0);
|
||||
const EAST: (isize, isize) = (0, 1);
|
||||
const SOUTH: (isize, isize) = (1, 0);
|
||||
const WEST: (isize, isize) = (0, -1);
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let grid = read("inputs/day10.txt", parser())?;
|
||||
|
||||
let mut adj = AdjList::default();
|
||||
let mut start = None;
|
||||
for i in 0 .. grid.len() {
|
||||
for j in 0 .. grid[i].len() {
|
||||
let node = Node { row: i, col: j };
|
||||
let others: &[(isize, isize)] = match grid[i][j] {
|
||||
Cell::NorthSouthPipe => &[NORTH, SOUTH],
|
||||
Cell::EastWestPipe => &[EAST, WEST],
|
||||
Cell::NorthEastPipe => &[NORTH, EAST],
|
||||
Cell::NorthWestPipe => &[NORTH, WEST],
|
||||
Cell::SouthWestPipe => &[SOUTH, WEST],
|
||||
Cell::SouthEastPipe => &[SOUTH, EAST],
|
||||
Cell::Ground => &[],
|
||||
Cell::Start => {
|
||||
assert!(start.is_none());
|
||||
start = Some(node);
|
||||
// we can do this but that means in dijkstra we need to handle
|
||||
// connections going nowhere
|
||||
&[NORTH, EAST, SOUTH, WEST]
|
||||
}
|
||||
};
|
||||
for (row_diff, col_diff) in others {
|
||||
let other = match (
|
||||
i.checked_add_signed(*row_diff),
|
||||
j.checked_add_signed(*col_diff)
|
||||
) {
|
||||
(Some(row), Some(col)) if row < grid.len() && col < grid[i].len() => {
|
||||
Node { row, col }
|
||||
},
|
||||
_ => continue
|
||||
};
|
||||
adj.add_edge(node, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 6749 is too low
|
||||
println!(
|
||||
"{:?}",
|
||||
adj.dij(start.unwrap())
|
||||
.into_iter()
|
||||
.max_by_key(|(_, dist)| *dist)
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue