diff --git a/Cargo.toml b/Cargo.toml index 6b3ea9b..03ebdb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,5 @@ edition = "2018" [dependencies] nom = "6.0.1" +petgraph = "0.5.1" thiserror = "1.0.22" \ No newline at end of file diff --git a/inputs/day10.txt b/inputs/day10.txt new file mode 100644 index 0000000..8c44b72 --- /dev/null +++ b/inputs/day10.txt @@ -0,0 +1,93 @@ +97 +62 +23 +32 +51 +19 +98 +26 +90 +134 +73 +151 +116 +76 +6 +94 +113 +127 +119 +44 +115 +50 +143 +150 +86 +91 +36 +104 +131 +101 +38 +66 +46 +96 +54 +70 +8 +30 +1 +108 +69 +139 +24 +29 +77 +124 +107 +14 +137 +16 +140 +80 +68 +25 +31 +59 +45 +126 +148 +67 +13 +125 +53 +57 +41 +47 +35 +145 +120 +12 +37 +5 +110 +138 +130 +2 +63 +83 +22 +79 +52 +7 +95 +58 +149 +123 +89 +109 +15 +144 +114 +9 +78 diff --git a/inputs/day10_test1.txt b/inputs/day10_test1.txt new file mode 100644 index 0000000..cd1b40b --- /dev/null +++ b/inputs/day10_test1.txt @@ -0,0 +1,11 @@ +16 +10 +15 +5 +1 +11 +7 +19 +6 +12 +4 \ No newline at end of file diff --git a/inputs/day10_test2.txt b/inputs/day10_test2.txt new file mode 100644 index 0000000..be5c492 --- /dev/null +++ b/inputs/day10_test2.txt @@ -0,0 +1,31 @@ +28 +33 +18 +42 +31 +14 +46 +20 +48 +47 +24 +23 +49 +45 +19 +38 +39 +11 +1 +32 +25 +35 +8 +17 +7 +9 +4 +2 +34 +10 +3 \ No newline at end of file diff --git a/src/bin/joltage.rs b/src/bin/joltage.rs new file mode 100644 index 0000000..e8af043 --- /dev/null +++ b/src/bin/joltage.rs @@ -0,0 +1,109 @@ +use advent2020::errors::TopLevelError; +use petgraph::graphmap::GraphMap; +use std::collections::HashMap; +use std::env; +use std::fs; +use std::str::FromStr; + +fn visit_all_nodes( + graph: &GraphMap, + start: u64, + end: u64, +) -> Result<(usize, usize, usize), TopLevelError> { + let mut ones = 0; + let mut twos = 0; + let mut threes = 0; + let mut current = start; + while current != end { + let (_, next, edge_length) = graph + .edges(current) + .min() + .ok_or(TopLevelError::UnknownError)?; + match edge_length { + 0 => return Err(TopLevelError::UnknownError), + 1 => ones += 1, + 2 => twos += 1, + 3 => threes += 1, + _ => return Err(TopLevelError::UnknownError), + } + current = next; + } + Ok((ones, twos, threes)) +} + +fn path_counts( + graph: &GraphMap, + cheat_codes: &mut HashMap, + start: u64, + end: u64, +) -> usize { + if start == end { + return 1; + } + + let mut sum = 0; + + for (_, to, _) in graph.edges(start) { + match cheat_codes.get(&to) { + None => { + let result = path_counts(graph, cheat_codes, to, end); + cheat_codes.insert(to, result); + sum += result; + } + Some(result) => { + sum += result; + } + } + } + + sum +} + +fn main() -> Result<(), TopLevelError> { + let filename = env::args().nth(1).expect("No file argument given."); + let contents = fs::read_to_string(filename)?; + let mut graph = GraphMap::new(); + let mut nodes = Vec::new(); + + // add the nodes in the graph, which are weighted by their values + let mut max_jolts = 0; + for line in contents.lines() { + let value = u64::from_str(line)?; + if value > max_jolts { + max_jolts = value; + } + graph.add_node(value); + nodes.push(value); + } + max_jolts += 3; + + graph.add_node(0); + nodes.push(0); // outlet + graph.add_node(max_jolts); + nodes.push(max_jolts); // my device + + for start in nodes.iter() { + for end in nodes.iter() { + if (*end >= (start + 1)) && (*end <= (start + 3)) { + graph.add_edge(*start, *end, end - start); + } + } + } + + let (one_count, two_count, three_count) = visit_all_nodes(&graph, 0, max_jolts)?; + println!("Found a path that visits all nodes:"); + println!(" jumps of size 1: {}", one_count); + println!(" jumps of size 2: {}", two_count); + println!(" jumps of size 3: {}", three_count); + println!( + " product of size 1 and size 3: {}", + one_count * three_count + ); + let mut cheat_codes = HashMap::with_capacity(10000); + println!( + "Total number of paths: {}", + path_counts(&graph, &mut cheat_codes, 0, max_jolts) + ); + + Ok(()) +} diff --git a/src/errors.rs b/src/errors.rs index fd43a09..67491a8 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -40,6 +40,8 @@ pub enum TopLevelError { #[from] source: ExecutionError, }, + #[error("Numeric conversion error: {0}")] + NumConversionError(#[from] ParseIntError), } #[derive(Error, Debug)]