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