diff --git a/day22/src/bin/day22a.rs b/day22/src/bin/day22a.rs index f7bb694..2196012 100644 --- a/day22/src/bin/day22a.rs +++ b/day22/src/bin/day22a.rs @@ -17,18 +17,7 @@ fn can_disintegrate(bricks: &[Brick], b: &Brick) -> bool { fn process(bufin: impl BufRead) -> Result { let mut bricks = parser::parse(bufin)?; - let mut changed = true; - while changed { - let old = bricks.clone(); - changed = false; - for b in &mut bricks { - if let Some(z) = falls_to(&old, b) { - let height = b.2.max() - b.2.min(); - b.2 = Range::new(z, z + height); - changed = true; - } - } - } + settle_bricks(&mut bricks); Ok(bricks .par_iter() .filter(|b| can_disintegrate(&bricks, b)) diff --git a/day22/src/bin/day22b.rs b/day22/src/bin/day22b.rs new file mode 100644 index 0000000..330b5dd --- /dev/null +++ b/day22/src/bin/day22b.rs @@ -0,0 +1,32 @@ +// Copyright (C) 2023 Leandro Lisboa Penz +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. + +use day22::*; + +use rayon::prelude::*; + +fn would_fall(bricks: &[Brick], b: &Brick) -> usize { + let mut bricks = bricks + .iter() + .filter(|o| o != &b) + .copied() + .collect::>(); + settle_bricks(&mut bricks) +} + +fn process(bufin: impl BufRead) -> Result { + let mut bricks = parser::parse(bufin)?; + settle_bricks(&mut bricks); + Ok(bricks.par_iter().map(|b| would_fall(&bricks, b)).sum()) +} + +#[test] +fn test() -> Result<()> { + assert_eq!(process(EXAMPLE.as_bytes())?, 7); + Ok(()) +} + +fn main() -> Result<()> { + do_main(|| process(stdin().lock())) +} diff --git a/day22/src/lib.rs b/day22/src/lib.rs index 2b68c5d..61f9996 100644 --- a/day22/src/lib.rs +++ b/day22/src/lib.rs @@ -5,6 +5,7 @@ pub use aoc::*; use std::cmp::min; +use std::collections::HashSet; pub const EXAMPLE: &str = "1,0,1~1,2,1 0,0,2~2,0,2 @@ -114,3 +115,21 @@ pub fn falls_to(bricks: &[Brick], b: &Brick) -> Option { (b.2.min() != 1).then_some(1) } } + +pub fn settle_bricks(bricks: &mut [Brick]) -> usize { + let mut changed = true; + let mut fell = HashSet::::new(); + while changed { + let old = bricks.to_vec(); + changed = false; + for (i, b) in bricks.iter_mut().enumerate() { + if let Some(z) = falls_to(&old, b) { + let height = b.2.max() - b.2.min(); + b.2 = Range::new(z, z + height); + fell.insert(i); + changed = true; + } + } + } + fell.len() +}