day 22
This commit is contained in:
parent
fc5e45dcbf
commit
9324bc2ccc
7
day22/Cargo.lock
generated
Normal file
7
day22/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "day22"
|
||||
version = "0.1.0"
|
8
day22/Cargo.toml
Normal file
8
day22/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "day22"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
1485
day22/input.txt
Normal file
1485
day22/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
119
day22/src/main.rs
Normal file
119
day22/src/main.rs
Normal file
@ -0,0 +1,119 @@
|
||||
use std::cmp;
|
||||
use std::fs::read_to_string;
|
||||
use std::time::Instant;
|
||||
|
||||
struct Brick {
|
||||
supports: Vec<u16>,
|
||||
supported_by: Vec<u16>,
|
||||
pos1: (u16, u16, u16),
|
||||
pos2: (u16, u16, u16),
|
||||
}
|
||||
|
||||
impl Brick {
|
||||
fn new(pos1: (u16, u16, u16), pos2: (u16, u16, u16)) -> Brick {
|
||||
Brick { supports: vec![], supported_by: vec![], pos1, pos2 }
|
||||
}
|
||||
}
|
||||
|
||||
// Part 1
|
||||
fn can_be_taken_out(bricks: &Vec<Brick>, brick: &Brick) -> bool {
|
||||
for &other_brick_id in &brick.supports {
|
||||
let other_brick = &bricks[other_brick_id as usize];
|
||||
if other_brick.supported_by.len() < 2 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
// Part 2
|
||||
fn count_fallen(bricks: &Vec<Brick>, index: usize) -> u16 {
|
||||
// Counting how many supports have been already removed from each brick
|
||||
let mut taken_supports: Vec<u16> = vec![0; bricks.len()];
|
||||
// Result counter
|
||||
let mut taken_bricks = 0;
|
||||
// Bricks that are going to disappear
|
||||
let mut to_take: Vec<u16> = vec![index as u16];
|
||||
loop {
|
||||
if let Some(id) = to_take.pop() {
|
||||
// Increase taken counter for each brick that is supported by current
|
||||
// If taken supports is equal to amount of supports, that brick will fall too
|
||||
let brick = &bricks[id as usize];
|
||||
for &supported_id in &brick.supports {
|
||||
let supported_brick = &bricks[supported_id as usize];
|
||||
taken_supports[supported_id as usize] += 1;
|
||||
if taken_supports[supported_id as usize] == supported_brick.supported_by.len() as u16 {
|
||||
to_take.push(supported_id);
|
||||
taken_bricks += 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
taken_bricks
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let time_start = Instant::now();
|
||||
let input_str = read_to_string("input.txt").unwrap();
|
||||
let time_start_no_io = Instant::now();
|
||||
let mut bricks: Vec<Brick> = vec![];
|
||||
for line in input_str.lines() {
|
||||
let mut split = line.split([',', '~']).map(|s| s.parse::<u16>().unwrap());
|
||||
bricks.push(Brick::new((split.next().unwrap(), split.next().unwrap(), split.next().unwrap()),
|
||||
(split.next().unwrap(), split.next().unwrap(), split.next().unwrap())));
|
||||
}
|
||||
// Sort by their vertical position so we can easily process them retaining falling precedence
|
||||
bricks.sort_by(|a, b| a.pos1.2.cmp(&b.pos1.2));
|
||||
// View from above containing id of the topmost brick on each x, y
|
||||
let max_x = bricks.iter().fold(0, |acc, brick| cmp::max(acc, brick.pos2.0));
|
||||
let max_y = bricks.iter().fold(0, |acc, brick| cmp::max(acc, brick.pos2.1));
|
||||
let mut from_above = vec![vec![u16::MAX; (max_x + 1) as usize]; (max_y + 1) as usize];
|
||||
// Make the bricks fall and create a support graph
|
||||
for i in 0..bricks.len() {
|
||||
let (below, rest) = bricks.split_at_mut(i);
|
||||
let brick = &mut rest[0];
|
||||
// Check how low the brick can go
|
||||
let mut target_z = 0;
|
||||
for y in brick.pos1.1..=brick.pos2.1 {
|
||||
for x in brick.pos1.0..=brick.pos2.0 {
|
||||
let &other_brick_id = &from_above[y as usize][x as usize];
|
||||
if other_brick_id != u16::MAX {
|
||||
let other_brick = &below[other_brick_id as usize];
|
||||
target_z = cmp::max(target_z, other_brick.pos2.2 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Shift it below
|
||||
let z_drop = brick.pos1.2 - target_z;
|
||||
brick.pos1.2 -= z_drop;
|
||||
brick.pos2.2 -= z_drop;
|
||||
// Create support graph connections in bricks, update view from above
|
||||
for y in brick.pos1.1..=brick.pos2.1 {
|
||||
for x in brick.pos1.0..=brick.pos2.0 {
|
||||
let &other_brick_id = &from_above[y as usize][x as usize];
|
||||
if other_brick_id != u16::MAX {
|
||||
let other_brick = &mut below[other_brick_id as usize];
|
||||
if other_brick.pos2.2 + 1 == target_z {
|
||||
if !brick.supported_by.contains(&other_brick_id) {
|
||||
brick.supported_by.push(other_brick_id);
|
||||
other_brick.supports.push(i as u16);
|
||||
}
|
||||
}
|
||||
}
|
||||
from_above[y as usize][x as usize] = i as u16;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Part 1
|
||||
let sum1 = bricks.iter().filter(|&brick| can_be_taken_out(&bricks, brick)).count();
|
||||
// Part 2
|
||||
let sum2 = (0..bricks.len()).map(|i| count_fallen(&bricks, i) as u32).sum::<u32>();
|
||||
let elapsed = time_start.elapsed().as_micros();
|
||||
let elapsed_no_io = time_start_no_io.elapsed().as_micros();
|
||||
println!("Time: {}us", elapsed);
|
||||
println!("Time without file i/o: {}us", elapsed_no_io);
|
||||
println!("Sum1: {}", sum1);
|
||||
println!("Sum2: {}", sum2);
|
||||
}
|
Loading…
Reference in New Issue
Block a user