use aoc_runner_derive::{aoc, aoc_generator}; use cached::proc_macro::cached; use indicatif::{ProgressBar, ProgressFinish, ProgressStyle}; use itertools::Itertools; use std::collections::HashMap; type Edges = HashMap>; #[aoc_generator(day11)] fn parse(input: &str) -> (Edges, Edges) { let mut edges: Edges = HashMap::new(); let mut rev_edges: Edges = HashMap::new(); for l in input.lines() { let (k, rest) = l.split_once(": ").unwrap(); for v in rest.split_ascii_whitespace() { edges.entry(k.to_string()).or_default().push(v.to_string()); rev_edges .entry(v.to_string()) .or_default() .push(k.to_string()); } } (edges, rev_edges) } fn find_path(cur: &str, goal: &str, edges: &Edges) -> u64 { if cur == goal { return 1; } if let Some(nexts) = edges.get(cur) { nexts.iter().map(|n| find_path(n, goal, edges)).sum() } else { 0 } } #[aoc(day11, part1)] fn part1((fwd, rev): &(Edges, Edges)) -> u64 { let mut count = 0u64; let mut to_check = Vec::from_iter(rev["out"].iter()); let mut pb = ProgressBar::no_length() .with_style( ProgressStyle::with_template( "[{elapsed_precise}/{eta_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {per_sec}", ) .unwrap(), ) .with_finish(indicatif::ProgressFinish::AndLeave); find_path("you", "out", fwd) } #[aoc(day11, part2)] fn part2(input: &(Edges, Edges)) -> u64 { 0 } #[cfg(test)] mod tests { use rstest::rstest; use super::*; const EXAMPLE: &str = "aaa: you hhh you: bbb ccc bbb: ddd eee ccc: ddd eee fff ddd: ggg eee: out fff: out ggg: out hhh: ccc fff iii iii: out"; #[rstest] #[case(EXAMPLE, 5)] fn part1_example(#[case] input: &str, #[case] expected: u64) { assert_eq!(part1(&parse(input)), expected); } #[rstest] #[case(EXAMPLE, 0)] fn part2_example(#[case] input: &str, #[case] expected: u64) { assert_eq!(part2(&parse(input)), expected); } }