pub fn process_part1(input: &str) -> i32 { let mut sum = 0; let mut number = String::new(); for &byte in input.as_bytes() { if byte == b'-' || byte.is_ascii_digit() { number.push(byte as char); } else if !number.is_empty() { sum += number.parse::().unwrap(); number.clear(); } } sum } pub fn process_part2(input: &str) -> i32 { let unreded_input = input .split("red") .map(|part| { let open = find_open(part); let close = find_close(part); let new = &part[..open as usize]; &new[close as usize..] }) .collect::>() .join(", "); println!("{unreded_input}"); process_part1(&unreded_input) } fn find_open(string: &str) -> u32 { let mut bytes = string.as_bytes().to_vec(); bytes.reverse(); // count of traversed objects // increments when seeing } decrements when seeing { // while == 0, potentially inside an object // while > 0 peeking inside another object // when < 0 left object red is inside of // when == 0 and encountered [ then inside array let mut count = 0; let mut idx = bytes.len() - 1; for byte in bytes.clone() { if byte == b'}' { count += 1 } else if byte == b'{' { count -= 1 } else if byte == b'[' && count == 0 { return bytes.len() as u32 - 1; } if count < 0 || idx == 0 { break; } idx -= 1; } if count < 0 { idx as u32 } else { bytes.len() as u32 - 1 } } fn find_close(string: &str) -> u32 { let bytes = string.as_bytes().to_vec(); // count of traversed objects // increments when seeing { decrements when seeing } // while == 0, potentially inside an object // while > 0 peeking inside another object // when < 0 left object red is inside of // when == 0 and encountered ] then inside array let mut count = 0; let mut idx = 0; for byte in bytes.clone() { if byte == b'}' { count -= 1 } else if byte == b'{' { count += 1 } else if byte == b']' && count == 0 { return 0; } if count < 0 || idx == bytes.len() - 1 { break; } idx += 1; } if count < 0 { idx as u32 } else { 0 } } #[cfg(test)] mod tests_12 { use super::*; #[test] fn it_works() { let result_a = process_part1("[1,2,3]"); let result_b = process_part1(r#"{"a":2,"b":4}"#); assert_eq!(result_a, 6); assert_eq!(result_b, 6); let result_a = process_part1("[[[3]]]"); let result_b = process_part1(r#"{"a":{"b":4},"c":-1}"#); assert_eq!(result_a, 3); assert_eq!(result_b, 3); let result_a = process_part1(r#"{"a":[-1,1]}"#); let result_b = process_part1(r#"[-1,{"a":1}]"#); assert_eq!(result_a, 0); assert_eq!(result_b, 0); let result_a = process_part1("[]"); let result_b = process_part1("{}"); assert_eq!(result_a, 0); assert_eq!(result_b, 0); } #[test] fn part2() { let result_a = process_part2("[1,2,3]"); let result_b = process_part2(r#"{"a":2,"b":4}"#); assert_eq!(result_a, 6); assert_eq!(result_b, 6); let result_a = process_part2("[[[3]]]"); let result_b = process_part2(r#"{"a":{"b":4},"c":-1}"#); assert_eq!(result_a, 3); assert_eq!(result_b, 3); let result_a = process_part2(r#"{"a":[-1,1]}"#); let result_b = process_part2(r#"[-1,{"a":1}]"#); assert_eq!(result_a, 0); assert_eq!(result_b, 0); let result_a = process_part2("[]"); let result_b = process_part2("{}"); assert_eq!(result_a, 0); assert_eq!(result_b, 0); let result_a = process_part2(r#"[1,{"c":"red","b":2},3]"#); assert_eq!(result_a, 4); let result_a = process_part2(r#"{"d":"red","e":[1,2,3,4],"f":5}"#); assert_eq!(result_a, 0); let result_a = process_part2(r#"[1,"red",5]"#); assert_eq!(result_a, 6); } }