Day 10. Took a bit longer because I tried petgraph, which was not as helpful as I'd hoped.

This commit is contained in:
2020-12-10 11:02:46 -08:00
parent cc049417d6
commit 0e7746bdde
6 changed files with 247 additions and 0 deletions

View File

@@ -6,4 +6,5 @@ edition = "2018"
[dependencies]
nom = "6.0.1"
petgraph = "0.5.1"
thiserror = "1.0.22"

93
inputs/day10.txt Normal file
View File

@@ -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

11
inputs/day10_test1.txt Normal file
View File

@@ -0,0 +1,11 @@
16
10
15
5
1
11
7
19
6
12
4

31
inputs/day10_test2.txt Normal file
View File

@@ -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

109
src/bin/joltage.rs Normal file
View File

@@ -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<u64, u64, petgraph::Directed>,
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<u64, u64, petgraph::Directed>,
cheat_codes: &mut HashMap<u64, usize>,
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(())
}

View File

@@ -40,6 +40,8 @@ pub enum TopLevelError {
#[from]
source: ExecutionError,
},
#[error("Numeric conversion error: {0}")]
NumConversionError(#[from] ParseIntError),
}
#[derive(Error, Debug)]