This commit is contained in:
Andrew Glaze 2023-12-22 10:31:00 -05:00
parent 9db0e3f054
commit b802cf1d16
2 changed files with 134 additions and 0 deletions

133
src/day22.rs Normal file
View File

@ -0,0 +1,133 @@
use std::collections::VecDeque;
use aoc_runner_derive::{aoc, aoc_generator};
use regex::Regex;
pub struct Brick {
up: Vec<Vec<usize>>,
down: Vec<Vec<usize>>,
}
#[aoc_generator(day22)]
fn parse(input: &str) -> Brick {
let re: Regex = Regex::new(r"\d+").unwrap();
let mut bricks: Vec<[usize; 6]> = input.lines().map(|line| {
re.captures_iter(line)
.map(|c| c.extract::<0>().0.parse::<usize>().unwrap())
.collect::<Vec<_>>().try_into().unwrap()
}).collect::<Vec<_>>();
let mut heights = [[0; 10]; 10];
let mut indices = [[usize::MAX; 10]; 10];
let mut up = vec![Vec::new(); bricks.len()];
let mut down = vec![Vec::new(); bricks.len()];
bricks.sort_unstable_by_key(|b| b[2]);
for (i, &[x1, y1, z1, x2, y2, z2]) in bricks.iter().enumerate() {
let height = z2 - z1 + 1;
let mut top = 0;
let mut previous = usize::MAX;
for x in x1..=x2 {
for y in y1..=y2 {
top = top.max(heights[x][y]);
}
}
for x in x1..=x2 {
for y in y1..=y2 {
if heights[x][y] == top {
let index = indices[x][y];
if index != previous {
up[index].push(i);
down[i].push(index);
previous = index;
}
}
heights[x][y] = top + height;
indices[x][y] = i;
}
}
}
Brick { up , down }
}
#[aoc(day22, part1)]
fn part1(input: &Brick) -> usize {
let Brick { down, .. } = input;
let mut safe = vec![true; down.len()];
for underneath in down {
if underneath.len() == 1 {
safe[underneath[0]] = false;
}
}
safe.iter().filter(|&&b| b).count()
}
#[aoc(day22, part2)]
fn part2(input: &Brick) -> usize {
let Brick { up, down } = input;
let mut safe = vec![true; down.len()];
for underneath in down {
if underneath.len() == 1 {
safe[underneath[0]] = false;
}
}
let mut result = 0;
let mut todo = VecDeque::new();
let mut removed = vec![usize::MAX; down.len()];
for (start, &safe) in safe.iter().enumerate() {
if safe {
continue;
}
todo.push_back(start);
removed[start] = start;
while let Some(current) = todo.pop_front() {
for &next in &up[current] {
if removed[next] != start && down[next].iter().all(|&i| removed[i] == start) {
result += 1;
removed[next] = start;
todo.push_back(next);
}
}
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
const EX: &str = r"1,0,1~1,2,1
0,0,2~2,0,2
0,2,3~2,2,3
0,0,4~0,2,4
2,0,5~2,2,5
0,1,6~2,1,6
1,1,8~1,1,9";
#[test]
fn part1_example() {
assert_eq!(part1(&parse(EX)), 5);
}
#[test]
fn part2_example() {
assert_eq!(part2(&parse(EX)), 7);
}
}

View File

@ -1,3 +1,4 @@
mod day22;
mod day21; mod day21;
mod day20; mod day20;
mod day19; mod day19;