advent_of_code/year2018/
day08.rs1use crate::input::Input;
2type InputNumber = u8;
3
4pub fn solve(input: &Input) -> Result<usize, String> {
5 let data = input
6 .text
7 .split_whitespace()
8 .map(|word| {
9 word.parse::<InputNumber>()
10 .map_err(|error| format!("Invalid input: {error}"))
11 })
12 .collect::<Result<Vec<InputNumber>, _>>()?;
13 Ok(evaluate_node(&data, 0, input.is_part_one())?.1)
14}
15
16fn evaluate_node(
17 data: &[InputNumber],
18 start: usize,
19 part1: bool,
20) -> Result<(usize, usize), String> {
21 if data.len() < start + 2 {
22 return Err("Invalid input".to_string());
23 }
24
25 let mut children_values = Vec::new();
26 let mut offset_after_children = start + 2;
27
28 let num_child_nodes = data[start];
29 for _ in 0..num_child_nodes {
30 let (offset_after_child, child_value) = evaluate_node(data, offset_after_children, part1)?;
31 offset_after_children = offset_after_child;
32 children_values.push(child_value);
33 }
34
35 let metadata_entries = data[start + 1] as usize;
36 let node_value = data
37 .iter()
38 .skip(offset_after_children)
39 .take(metadata_entries)
40 .map(|&metadata| {
41 if part1 || num_child_nodes == 0 {
42 metadata as usize
43 } else if metadata >= 1 && metadata as usize <= children_values.len() {
44 children_values[(metadata - 1) as usize]
45 } else {
46 0
47 }
48 })
49 .sum::<usize>()
50 + if part1 {
51 children_values.iter().sum()
52 } else {
53 0
54 };
55
56 let offset_after_current = offset_after_children
57 .checked_add(metadata_entries)
58 .ok_or("Overflow in computation")?;
59 Ok((offset_after_current, node_value))
60}
61
62#[test]
63fn tests() {
64 use crate::input::{test_part_one, test_part_two};
65
66 test_part_one!("2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2" => 138);
67 test_part_two!("2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2" => 66);
68
69 let input = include_str!("day08_input.txt");
70 test_part_one!(input => 47112);
71 test_part_two!(input => 28237);
72}