#![warn(clippy::pedantic)] use std::{ collections::{HashMap, HashSet}, io::{stdin, BufRead}, }; type Point<'a> = &'a str; fn walk<'a>( connections: &HashMap, HashSet>>, visited: &[Point<'a>], extra_cave: Option>, from: Point<'a>, ) -> usize { let mut res = 0; let mut visited = Vec::from(visited); visited.push(from); for target in &connections[from] { if *target == "end" { res += 1; continue; } let is_uppercase = target.chars().all(|c| c.is_ascii_uppercase()); let was_visited = visited.contains(target); if is_uppercase || !was_visited { res += walk(connections, &visited, extra_cave, target); } else if extra_cave.is_none() { res += walk(connections, &visited, Some(target), target); } } res } fn main() { let lines: Vec<_> = stdin().lock().lines().collect::>().unwrap(); let connections: HashMap> = lines.iter().fold(HashMap::new(), |mut map, line| { let mut parts = line.split('-'); let p1 = parts.next().unwrap(); let p2 = parts.next().unwrap(); if p1 != "end" && p2 != "start" { map.entry(p1).or_default().insert(p2); } if p2 != "end" && p1 != "start" { map.entry(p2).or_default().insert(p1); } map }); println!("{}", walk(&connections, &[], Some(""), "start")); println!("{}", walk(&connections, &[], None, "start")); }