|
@@ -0,0 +1,60 @@
|
|
1
|
+use std::error::Error;
|
|
2
|
+use std::fs;
|
|
3
|
+use std::result;
|
|
4
|
+
|
|
5
|
+type Result<T> = result::Result<T, Box<Error>>;
|
|
6
|
+
|
|
7
|
+const INPUT: &str = "inputs/8.txt";
|
|
8
|
+
|
|
9
|
+pub fn solve_part1() -> Result<u32> {
|
|
10
|
+ let license = read_license(INPUT)?;
|
|
11
|
+ Ok(sum_metadata(&license, 0, 0).0)
|
|
12
|
+}
|
|
13
|
+
|
|
14
|
+fn read_license(filename: &str) -> Result<Vec<u32>> {
|
|
15
|
+ let license = fs::read_to_string(filename)?;
|
|
16
|
+ let license = license.trim();
|
|
17
|
+ Ok(license
|
|
18
|
+ .split(' ')
|
|
19
|
+ .map(|num| num.parse().unwrap())
|
|
20
|
+ .collect())
|
|
21
|
+}
|
|
22
|
+
|
|
23
|
+fn sum_metadata(license: &[u32], mut index: usize, mut sum_acc: u32) -> (u32, usize) {
|
|
24
|
+ let num_children = license[index];
|
|
25
|
+ let num_metadata = license[index + 1];
|
|
26
|
+ index += 2;
|
|
27
|
+ if num_children != 0 {
|
|
28
|
+ for _ in 0..num_children {
|
|
29
|
+ let (child_sum_acc, child_index) = sum_metadata(license, index, sum_acc);
|
|
30
|
+ sum_acc = child_sum_acc;
|
|
31
|
+ index = child_index;
|
|
32
|
+ }
|
|
33
|
+ }
|
|
34
|
+ if num_metadata != 0 {
|
|
35
|
+ let sum: u32 = license[index..index + num_metadata as usize].iter().sum();
|
|
36
|
+ index += num_metadata as usize;
|
|
37
|
+ sum_acc += sum;
|
|
38
|
+ }
|
|
39
|
+ (sum_acc, index)
|
|
40
|
+}
|
|
41
|
+
|
|
42
|
+#[cfg(test)]
|
|
43
|
+mod tests {
|
|
44
|
+ use super::*;
|
|
45
|
+
|
|
46
|
+ const TEST_INPUT: &str = "inputs/8_test.txt";
|
|
47
|
+ fn test_license() -> Vec<u32> {
|
|
48
|
+ vec![2, 3, 0, 3, 10, 11, 12, 1, 1, 0, 1, 99, 2, 1, 1, 2]
|
|
49
|
+ }
|
|
50
|
+
|
|
51
|
+ #[test]
|
|
52
|
+ fn reads_license_file() {
|
|
53
|
+ assert_eq!(read_license(TEST_INPUT).unwrap(), test_license());
|
|
54
|
+ }
|
|
55
|
+
|
|
56
|
+ #[test]
|
|
57
|
+ fn sums_license_metadata() {
|
|
58
|
+ assert_eq!(sum_metadata(&test_license(), 0, 0).0, 138);
|
|
59
|
+ }
|
|
60
|
+}
|