diff --git a/src/bin/11.rs b/src/bin/11.rs new file mode 100644 index 0000000..d74207c --- /dev/null +++ b/src/bin/11.rs @@ -0,0 +1,77 @@ +use aoc::*; +use cached::proc_macro::cached; +use std::collections::HashMap; + +fn main() { + let input = include_str!("../../input/11"); + println!("Part 1: {}", part1(input)); + println!("Part 2: {}", part2(input)); +} + +#[test] +fn example() { + let input = include_str!("../../input/11-test-1"); + assert_eq!(part1(input), 5); + + let input = include_str!("../../input/11-test-2"); + assert_eq!(part2(input), 2); +} + +fn part1(input: &str) -> usize { + let network = parse_input(input); + possible_paths(&network, "you") +} + +fn part2(input: &str) -> usize { + let network = parse_input(input); + possible_server_paths(&network, "svr", false, false) +} + +#[cached(key = "String", convert = r#"{ at.to_string() }"#)] +fn possible_paths(net: &Network, at: &str) -> usize { + if at == "out" { + return 1; + } + + net[at].iter().map(|next| possible_paths(net, next)).sum() +} + +#[cached( + key = "(String, bool, bool)", + convert = r#"{ (at.to_string(), visited_dac, visited_fft) }"# +)] +fn possible_server_paths( + net: &Network, + at: &str, + mut visited_dac: bool, + mut visited_fft: bool, +) -> usize { + if at == "out" { + return if visited_dac && visited_fft { 1 } else { 0 }; + } + + if at == "dac" { + visited_dac = true; + } + + if at == "fft" { + visited_fft = true; + } + + net[at] + .iter() + .map(|next| possible_server_paths(net, next, visited_dac, visited_fft)) + .sum() +} + +type Network = HashMap>; + +fn parse_input(input: &str) -> Network { + input.lines().map(parse_line).collect() +} + +fn parse_line(line: &str) -> (String, Vec) { + let (key, values) = line.split_once(": ").unwrap(); + let values = parse_ws_separated(values).collect(); + (key.to_string(), values) +} diff --git a/template.rs b/template.rs index 76cdc08..cae10b2 100644 --- a/template.rs +++ b/template.rs @@ -1,16 +1,16 @@ use aoc::*; -const INPUT: &str = include_str!("../../input/DAY"); - fn main() { - println!("Part 1: {}", part1(INPUT)); - println!("Part 2: {}", part2(INPUT)); + let input = include_str!("../../input/DAY"); + println!("Part 1: {}", part1(input)); + println!("Part 2: {}", part2(input)); } #[test] fn example() { - assert_example!(part1, "DAY-test", 0); - assert_example!(part2, "DAY-test", 0); + let input = include_str!("../../input/DAY-test"); + assert_eq!(part1(input), 0); + assert_eq!(part2(input), 0); } fn part1(input: &str) -> usize {