y2015d12p2

This commit is contained in:
Fabian Schmidt 2024-10-30 10:39:32 +01:00
parent 19f50f48d6
commit ea1e7aadec

View File

@ -13,76 +13,112 @@ pub fn process_part1(input: &str) -> i32 {
} }
pub fn process_part2(input: &str) -> i32 { pub fn process_part2(input: &str) -> i32 {
let unreded_input = input let red_indices = input
.split("red") .match_indices("red")
.map(|part| { .map(|(idx, _)| idx)
let open = find_open(part); .collect::<Vec<usize>>();
let close = find_close(part); let mut red_objects = Vec::new();
let new = &part[..open as usize]; let mut last_range = (0, 0);
&new[close as usize..] for idx in red_indices {
}) if idx > last_range.0 && idx < last_range.1 {
.collect::<Vec<&str>>() continue;
.join(", "); }
println!("{unreded_input}"); let (left, right) = input.split_at(idx);
let open = find_open(left);
let close = find_close(right) + idx as u32;
let range = (open as usize, close as usize + 1);
last_range = range;
if !red_objects.contains(&range) {
red_objects.push(range);
}
}
red_objects.reverse();
// remove overlaps not caught during creation
let mut last_range = (0, 0);
let mut no_overlap = Vec::new();
for range in red_objects.clone() {
if last_range.0 < range.0 && last_range.1 > range.1 {
continue;
}
last_range = range;
no_overlap.push(range);
}
let mut unreded_input = input.to_owned();
for range in no_overlap {
unreded_input.replace_range(range.0..range.1, "0");
}
process_part1(&unreded_input) process_part1(&unreded_input)
} }
fn find_open(string: &str) -> u32 { fn find_open(string: &str) -> u32 {
let mut bytes = string.as_bytes().to_vec(); let mut bytes = string.as_bytes().to_vec();
bytes.reverse(); bytes.reverse();
let length = bytes.len();
// count of traversed objects // count of traversed objects
// increments when seeing } decrements when seeing { // increments when seeing } decrements when seeing {
// while == 0, potentially inside an object // while == 0, potentially inside an object
// while > 0 peeking inside another object // while > 0 peeking inside another object
// when < 0 left object red is inside of // when < 0 left object red is inside of
// when == 0 and encountered [ then inside array // when == 0 and encountered [ then inside array
let mut count = 0; let mut curly_count = 0;
let mut idx = bytes.len() - 1; let mut square_count = 0;
for byte in bytes.clone() { let mut idx = length - 1;
for byte in bytes {
if byte == b'}' { if byte == b'}' {
count += 1 curly_count += 1
} else if byte == b'{' { } else if byte == b'{' {
count -= 1 curly_count -= 1
} else if byte == b'[' && count == 0 { } else if byte == b'[' {
return bytes.len() as u32 - 1; square_count -= 1;
} else if byte == b']' {
square_count += 1;
} }
if count < 0 || idx == 0 { if square_count < 0 {
return length as u32 - 1;
}
if curly_count < 0 || idx == 0 {
break; break;
} }
idx -= 1; idx -= 1;
} }
if count < 0 { if curly_count < 0 {
idx as u32 idx as u32
} else { } else {
bytes.len() as u32 - 1 length as u32
} }
} }
fn find_close(string: &str) -> u32 { fn find_close(string: &str) -> u32 {
let bytes = string.as_bytes().to_vec(); let bytes = string.as_bytes().to_vec();
let length = bytes.len();
// count of traversed objects // count of traversed objects
// increments when seeing { decrements when seeing } // increments when seeing { decrements when seeing }
// while == 0, potentially inside an object // while == 0, potentially inside an object
// while > 0 peeking inside another object // while > 0 peeking inside another object
// when < 0 left object red is inside of // when < 0 left object red is inside of
// when == 0 and encountered ] then inside array // when == 0 and encountered ] then inside array
let mut count = 0; let mut curly_count = 0;
let mut square_count = 0;
let mut idx = 0; let mut idx = 0;
for byte in bytes.clone() { for byte in bytes {
if byte == b'}' { if byte == b'}' {
count -= 1 curly_count -= 1
} else if byte == b'{' { } else if byte == b'{' {
count += 1 curly_count += 1
} else if byte == b']' && count == 0 { } else if byte == b']' {
square_count -= 1;
} else if byte == b'[' {
square_count += 1;
}
if square_count < 0 {
return 0; return 0;
} }
if curly_count < 0 || idx == length {
if count < 0 || idx == bytes.len() - 1 {
break; break;
} }
idx += 1; idx += 1;
} }
if count < 0 { if curly_count < 0 {
idx as u32 idx as u32
} else { } else {
0 0
@ -115,22 +151,22 @@ mod tests_12 {
#[test] #[test]
fn part2() { fn part2() {
let result_a = process_part2("[1,2,3]"); //let result_a = process_part2("[1,2,3]");
let result_b = process_part2(r#"{"a":2,"b":4}"#); //let result_b = process_part2(r#"{"a":2,"b":4}"#);
assert_eq!(result_a, 6); //assert_eq!(result_a, 6);
assert_eq!(result_b, 6); //assert_eq!(result_b, 6);
let result_a = process_part2("[[[3]]]"); //let result_a = process_part2("[[[3]]]");
let result_b = process_part2(r#"{"a":{"b":4},"c":-1}"#); //let result_b = process_part2(r#"{"a":{"b":4},"c":-1}"#);
assert_eq!(result_a, 3); //assert_eq!(result_a, 3);
assert_eq!(result_b, 3); //assert_eq!(result_b, 3);
let result_a = process_part2(r#"{"a":[-1,1]}"#); //let result_a = process_part2(r#"{"a":[-1,1]}"#);
let result_b = process_part2(r#"[-1,{"a":1}]"#); //let result_b = process_part2(r#"[-1,{"a":1}]"#);
assert_eq!(result_a, 0); //assert_eq!(result_a, 0);
assert_eq!(result_b, 0); //assert_eq!(result_b, 0);
let result_a = process_part2("[]"); //let result_a = process_part2("[]");
let result_b = process_part2("{}"); //let result_b = process_part2("{}");
assert_eq!(result_a, 0); //assert_eq!(result_a, 0);
assert_eq!(result_b, 0); //assert_eq!(result_b, 0);
let result_a = process_part2(r#"[1,{"c":"red","b":2},3]"#); let result_a = process_part2(r#"[1,{"c":"red","b":2},3]"#);
assert_eq!(result_a, 4); assert_eq!(result_a, 4);
let result_a = process_part2(r#"{"d":"red","e":[1,2,3,4],"f":5}"#); let result_a = process_part2(r#"{"d":"red","e":[1,2,3,4],"f":5}"#);