day22
This commit is contained in:
parent
9db0e3f054
commit
b802cf1d16
133
src/day22.rs
Normal file
133
src/day22.rs
Normal 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);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
mod day22;
|
||||
mod day21;
|
||||
mod day20;
|
||||
mod day19;
|
||||
|
Loading…
Reference in New Issue
Block a user