From b542304187843b4e3e1edc11e0b6cd8de1719b4d Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sat, 11 Dec 2021 22:19:43 -0800 Subject: [PATCH] Day 12 part 2 --- 2021/src/day12.rs | 91 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/2021/src/day12.rs b/2021/src/day12.rs index d6b8491..a502388 100644 --- a/2021/src/day12.rs +++ b/2021/src/day12.rs @@ -39,7 +39,6 @@ fn search(node: &str, nodes: &HashMap<&str, Vec<&str>>, path: String, paths: &mu fn paths(nodes: &HashMap<&str, Vec<&str>>) -> usize { let mut paths = Vec::new(); search("start", nodes, "start".to_string(), &mut paths); - //dbg!(&paths); paths.len() } @@ -54,13 +53,72 @@ fn part1(input: &str) -> Result { Ok(paths(&nodes)) } -/* -#[aoc(day12, part2)] -fn part2(input: &[u64]) -> Result { -todo!("part2"); -Ok(0) +fn search2<'a>( + node: &str, + nodes: &HashMap<&'a str, Vec<&'a str>>, + path: &[&'a str], + paths: &mut Vec>, + double: &'a str, + smalls: &[&'a str], +) { + if node == "end" { + paths.push(path.to_vec()); + return; + } + for neighbor in &nodes[node] { + // If lowercase. + if neighbor.as_bytes()[0] & 0x20 != 0 { + if neighbor == &double { + // Allow two passes for this small node. + if path.iter().filter(|p| p == &neighbor).count() >= 2 { + continue; + } + } else { + // Only allow one pass for this small node. + if path.contains(neighbor) { + continue; + } + } + } + let mut child_path = path.to_vec(); + child_path.push(neighbor); + search2(neighbor, nodes, &child_path, paths, double, smalls); + } +} +fn paths2(nodes: &HashMap<&str, Vec<&str>>) -> usize { + let mut paths = Vec::new(); + let smalls: Vec<_> = nodes + .keys() + .filter(|n| n.as_bytes()[0] & 0x20 != 0) + .filter(|&n| n != &"start" && n != &"end") + .cloned() + .collect(); + + for double in &smalls { + search2( + "start", + nodes, + &vec!["start"], + &mut paths, + double, + smalls.as_slice(), + ); + } + paths.sort(); + paths.dedup(); + paths.len() +} + +#[aoc(day12, part2)] +fn part2(input: &str) -> Result { + let mut nodes = HashMap::new(); + input.lines().for_each(|p| { + let (n1, n2) = p.split_once('-').expect("missing dash"); + nodes.entry(n1).or_insert(Vec::new()).push(n2); + nodes.entry(n2).or_insert(Vec::new()).push(n1); + }); + Ok(paths2(&nodes)) } -*/ #[cfg(test)] mod tests { @@ -83,14 +141,19 @@ b-end Ok(()) } - /* #[test] - fn test_part2()->Result<()> { - let input = r#" + fn test_part2() -> Result<()> { + let input = r#" +start-A +start-b +A-c +A-b +b-d +A-end +b-end "# - .trim(); - assert_eq!(part2(&parse(input)?)?, u64::MAX); - Ok(()) + .trim(); + assert_eq!(part2(input)?, 36); + Ok(()) } - */ }