summaryrefslogtreecommitdiff
path: root/src/bin/day12.rs
blob: 35da4fee0c31dd3f0a662345e8bc2c0ef01b91b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use json::JsonValue;

fn main() {
    let input = &advent::read_file(12);
    println!("12a: {}", sum_numbers(input));
    println!("12b: {}", sum_numbers_red(input));
}

fn sum_numbers(input: &str) -> isize {
    let json = json::parse(input).unwrap();
    sum_numbers_json(&json, false)
}

fn sum_numbers_red(input: &str) -> isize {
    let json = json::parse(input).unwrap();
    sum_numbers_json(&json, true)
}

fn contains_red(object: &JsonValue) -> bool {
    if !object.is_object() {
        return false;
    }
    object.entries().any(|(_, val)| val == "red")
}

fn sum_numbers_json(input: &JsonValue, ignore_red: bool) -> isize {
    let mut sum = 0;

    match input {
        JsonValue::Number(_) => sum += input.as_isize().unwrap(),
        JsonValue::Object(_) => {
            if !(ignore_red && contains_red(input)) {
                for (_, entry) in input.entries() {
                    sum += sum_numbers_json(entry, ignore_red);
                }
            }
        },
        JsonValue::Array(_) => {
            for member in input.members() {
                sum += sum_numbers_json(member, ignore_red);
            }
        },
        JsonValue::String(_) => {},
        JsonValue::Short(_) => {},
        _ => unimplemented!(),
    }

    sum
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test() {
        assert_eq!(sum_numbers("[1,2,3]"), 6);
        assert_eq!(sum_numbers(r#"{"a":2,"b":4}"#), 6);
        assert_eq!(sum_numbers(r#"[[[3]]]"#), 3);
        assert_eq!(sum_numbers(r#"{"a":{"b":4},"c":-1}"#), 3);
        assert_eq!(sum_numbers(r#"{"a":[-1,1]}"#), 0);
        assert_eq!(sum_numbers(r#"[-1,{"a":1}]"#), 0);
        assert_eq!(sum_numbers("[]"), 0);
        assert_eq!(sum_numbers("{}"), 0);
    }

    #[test]
    fn test_red() {
        assert_eq!(sum_numbers_red("[1,2,3]"), 6);
        assert_eq!(sum_numbers_red(r#"[1,{"c":"red","b":2},3]"#), 4);
        assert_eq!(sum_numbers_red(r#"{"d":"red","e":[1,2,3,4],"f":5}"#), 0);
        assert_eq!(sum_numbers_red(r#"[1,"red",5]"#), 6);
    }
}