Rust
Somehow got the right answer for part 1 iteratively, but it wasn't actually correct at all, so switched to the standard recursion + memoisation. Gotta love just chucking an iterator into the value type of a HashMap and going BRRRR (1.2 ms).
solution
pub fn day11(input: &str) -> (u64, u64) {
let array = input.trim().lines();
let mut conns = HashMap::new();
for line in array {
let mut iter = line.split_whitespace();
conns.insert(&iter.next().unwrap()[0..3], iter);
}
fn find_path<'a>(
start: &'a str,
end: &'a str,
conns: &HashMap<&'a str, SplitWhitespace<'a>>,
devices: &mut HashMap<&'a str, u64>,
) -> u64 {
let mut sum = 0;
let Some(list) = conns.get(start) else {
return 0;
};
for i in list.clone() {
if i == end {
sum += 1;
} else if let Some(precomp) = devices.get(i) {
sum += precomp;
} else {
sum += find_path(i, end, conns, devices);
}
}
devices.insert(start, sum);
sum
}
let part1 = find_path("you", "out", &conns, &mut HashMap::new());
// If dac -> fft and fft -> dac are both non-zero, then there are loops. That makes an
// infinite number of paths so the question posed would be meaningless.
let dac_to_fft = find_path("dac", "fft", &conns, &mut HashMap::new());
let part2 = if dac_to_fft == 0 {
find_path("svr", "fft", &conns, &mut HashMap::new())
* find_path("fft", "dac", &conns, &mut HashMap::new())
* find_path("dac", "out", &conns, &mut HashMap::new())
} else {
find_path("svr", "dac", &conns, &mut HashMap::new())
* dac_to_fft
* find_path("fft", "out", &conns, &mut HashMap::new())
};
(part1, part2)
}