day(25): add solution
Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
parent
a61866c12e
commit
d752baf7a1
2 changed files with 160 additions and 0 deletions
13
samples/day25.txt
Normal file
13
samples/day25.txt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
jqt: rhn xhk nvd
|
||||||
|
rsh: frs pzl lsr
|
||||||
|
xhk: hfx
|
||||||
|
cmg: qnr nvd lhk bvb
|
||||||
|
rhn: xhk bvb hfx
|
||||||
|
bvb: xhk hfx
|
||||||
|
pzl: lsr hfx nvd
|
||||||
|
qnr: nvd
|
||||||
|
ntq: jqt hfx bvb xhk
|
||||||
|
nvd: lhk
|
||||||
|
lsr: lhk
|
||||||
|
rzs: qnr cmg lsr rsh
|
||||||
|
frs: qnr lhk lsr
|
147
src/bin/day25.rs
Normal file
147
src/bin/day25.rs
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
|
||||||
|
use aoc_2023::*;
|
||||||
|
|
||||||
|
type Output1 = usize;
|
||||||
|
type Output2 = Output1;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref EDGE_REGEX: Regex = Regex::new(r"(.*): (.*)").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Day25 {
|
||||||
|
edges: Vec<usize>,
|
||||||
|
nodes: Vec<(usize, usize)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Day25 {
|
||||||
|
fn neighbours(&self, u: usize) -> impl Iterator<Item = (usize, usize)> + '_ {
|
||||||
|
let (start, end) = self.nodes[u];
|
||||||
|
(start..end).map(|idx| (idx, self.edges[idx]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn furthest(&self, start: usize) -> usize {
|
||||||
|
let mut todo = VecDeque::new();
|
||||||
|
todo.push_back(start);
|
||||||
|
|
||||||
|
let mut seen = vec![false; self.nodes.len()];
|
||||||
|
seen[start] = true;
|
||||||
|
|
||||||
|
let mut result = start;
|
||||||
|
while let Some(u) = todo.pop_front() {
|
||||||
|
result = u;
|
||||||
|
|
||||||
|
for (_, v) in self.neighbours(u) {
|
||||||
|
if !seen[v] {
|
||||||
|
todo.push_back(v);
|
||||||
|
seen[v] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flow(&self, start: usize, end: usize) -> usize {
|
||||||
|
let mut todo = VecDeque::new();
|
||||||
|
let mut path = Vec::new();
|
||||||
|
let mut used = vec![false; self.edges.len()];
|
||||||
|
|
||||||
|
let mut result = 0;
|
||||||
|
|
||||||
|
for _ in 0..4 {
|
||||||
|
todo.push_back((start, usize::MAX));
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
let mut seen = vec![false; self.nodes.len()];
|
||||||
|
seen[start] = true;
|
||||||
|
|
||||||
|
while let Some((u, head)) = todo.pop_front() {
|
||||||
|
result += 1;
|
||||||
|
|
||||||
|
if u == end {
|
||||||
|
let mut index = head;
|
||||||
|
|
||||||
|
while index != usize::MAX {
|
||||||
|
let (edge, next) = path[index];
|
||||||
|
used[edge] = true;
|
||||||
|
index = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (edge, v) in self.neighbours(u) {
|
||||||
|
if !used[edge] && !seen[v] {
|
||||||
|
seen[v] = true;
|
||||||
|
todo.push_back((v, path.len()));
|
||||||
|
path.push((edge, head));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
todo.clear();
|
||||||
|
path.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Solution<Output1, Output2> for Day25 {
|
||||||
|
fn new<P: AsRef<Path>>(pathname: P) -> Self {
|
||||||
|
let mut mapping: HashMap<String, usize> = HashMap::new();
|
||||||
|
|
||||||
|
let mut graph: HashMap<usize, Vec<usize>> = HashMap::new();
|
||||||
|
let mut add_edge = |u, v| {
|
||||||
|
graph.entry(u).or_default().push(v);
|
||||||
|
};
|
||||||
|
|
||||||
|
let lines: Vec<String> = file_to_lines(pathname);
|
||||||
|
for (u, vs) in lines.into_iter().map(|l| {
|
||||||
|
let (_, [src, dest]) = EDGE_REGEX.captures(&l).unwrap().extract();
|
||||||
|
(
|
||||||
|
src.to_owned(),
|
||||||
|
dest.split(' ').map(str::to_owned).collect_vec(),
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
let next_idx = mapping.len();
|
||||||
|
let u_idx = *mapping.entry(u.clone()).or_insert(next_idx);
|
||||||
|
|
||||||
|
for v in vs {
|
||||||
|
let next_idx = mapping.len();
|
||||||
|
let v_idx = *mapping.entry(v.clone()).or_insert(next_idx);
|
||||||
|
|
||||||
|
add_edge(u_idx, v_idx);
|
||||||
|
add_edge(v_idx, u_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut edges = Vec::new();
|
||||||
|
let mut nodes = vec![(usize::MAX, usize::MAX); mapping.len()];
|
||||||
|
for (u, neighbours) in graph.into_iter() {
|
||||||
|
nodes[u] = (edges.len(), edges.len() + neighbours.len());
|
||||||
|
edges.extend(neighbours);
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { edges, nodes }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_1(&mut self) -> Output1 {
|
||||||
|
let u = self.furthest(0);
|
||||||
|
let v = self.furthest(u);
|
||||||
|
|
||||||
|
let size = self.flow(u, v);
|
||||||
|
size * (self.nodes.len() - size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_2(&mut self) -> Output2 {
|
||||||
|
2023
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
Day25::main()
|
||||||
|
}
|
||||||
|
|
||||||
|
test_sample!(day_25, Day25, 54, 2023);
|
Loading…
Reference in a new issue