142 lines
4.1 KiB
Rust
142 lines
4.1 KiB
Rust
|
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::<i32>().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::<Vec<&str>>()
|
||
|
.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);
|
||
|
}
|
||
|
}
|