year2015/
day12.rs

1use utils::parser::{ParseError, ParseResult};
2use utils::prelude::*;
3
4/// JSON document numbers.
5#[derive(Clone, Debug)]
6pub struct Day12 {
7    part1: i32,
8    part2: i32,
9}
10
11impl Day12 {
12    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13        let (part1, part2) = Self::parse.parse_complete(input)?;
14        Ok(Self { part1, part2 })
15    }
16
17    #[must_use]
18    pub fn part1(&self) -> i32 {
19        self.part1
20    }
21
22    #[must_use]
23    pub fn part2(&self) -> i32 {
24        self.part2
25    }
26
27    fn parse(input: &[u8]) -> ParseResult<(i32, i32)> {
28        match input {
29            [b'{', ..] => Self::parse_object(&input[1..]),
30            [b'[', ..] => Self::parse_array(&input[1..]),
31            _ => Err((ParseError::Expected("'{' or '['"), input)),
32        }
33    }
34
35    fn parse_object(mut input: &[u8]) -> ParseResult<(i32, i32)> {
36        let (mut part1, mut part2) = (0, 0);
37        let mut red = false;
38        loop {
39            match input {
40                [b'1'..=b'9', ..] | [b'-', b'1'..=b'9', ..] => {
41                    let (num, remaining) = parser::i32().parse(input)?;
42                    input = remaining;
43                    part1 += num;
44                    part2 += num;
45                }
46                [b'"', b'r', b'e', b'd', b'"', ..] => {
47                    input = &input[5..];
48                    red = true;
49                }
50                [b'{', ..] => {
51                    let (result, remaining) = Self::parse_object(&input[1..])?;
52                    input = remaining;
53                    part1 += result.0;
54                    part2 += result.1;
55                }
56                [b'[', ..] => {
57                    let (result, remaining) = Self::parse_array(&input[1..])?;
58                    input = remaining;
59                    part1 += result.0;
60                    part2 += result.1;
61                }
62                [b'}', ..] => return Ok(((part1, if red { 0 } else { part2 }), &input[1..])),
63                [] => return Err((ParseError::ExpectedByte(b']'), input)),
64                _ => input = &input[1..],
65            }
66        }
67    }
68
69    fn parse_array(mut input: &[u8]) -> ParseResult<(i32, i32)> {
70        let (mut part1, mut part2) = (0, 0);
71        loop {
72            match input {
73                [b'1'..=b'9', ..] | [b'-', b'1'..=b'9', ..] => {
74                    let (num, remaining) = parser::i32().parse(input)?;
75                    input = remaining;
76                    part1 += num;
77                    part2 += num;
78                }
79                [b'{', ..] => {
80                    let (result, remaining) = Self::parse_object(&input[1..])?;
81                    input = remaining;
82                    part1 += result.0;
83                    part2 += result.1;
84                }
85                [b'[', ..] => {
86                    let (result, remaining) = Self::parse_array(&input[1..])?;
87                    input = remaining;
88                    part1 += result.0;
89                    part2 += result.1;
90                }
91                [b']', ..] => return Ok(((part1, part2), &input[1..])),
92                [] => return Err((ParseError::ExpectedByte(b']'), input)),
93                _ => input = &input[1..],
94            }
95        }
96    }
97}
98
99examples!(Day12 -> (i32, i32) [
100    {input: r#"[1,2,3]"#, part1: 6, part2: 6},
101    {input: r#"{"a":2,"b":4}"#, part1: 6},
102    {input: r#"[[[3]]]"#, part1: 3},
103    {input: r#"{"a":{"b":4},"c":-1}"#, part1: 3},
104    {input: r#"{"a":[-1,1]}"#, part1: 0},
105    {input: r#"[-1,{"a":1}]"#, part1: 0},
106    {input: r#"[]"#, part1: 0},
107    {input: r#"{}"#, part1: 0},
108    {input: r#"[1,{"c":"red","b":2},3]"#, part2: 4},
109    {input: r#"{"d":"red","e":[1,2,3,4],"f":5}"#, part2: 0},
110    {input: r#"[1,"red",5]"#, part2: 6},
111]);