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); } }