|
| 1 | +use std::sync::atomic::{AtomicI32, Ordering}; |
| 2 | +use utils::multithreading::worker_pool; |
1 | 3 | use utils::point::Point2D; |
2 | 4 | use utils::prelude::*; |
3 | 5 |
|
@@ -62,21 +64,26 @@ impl Day14 { |
62 | 64 |
|
63 | 65 | #[must_use] |
64 | 66 | pub fn part2(&self) -> u32 { |
65 | | - let mut robots = self.robots.clone(); |
66 | | - for i in 1..=u32::MAX { |
67 | | - let mut grid = [0u128; HEIGHT as usize]; |
68 | | - for r in robots.iter_mut() { |
69 | | - r.position += r.velocity; |
70 | | - r.position.x = r.position.x.rem_euclid(WIDTH); |
71 | | - r.position.y = r.position.y.rem_euclid(HEIGHT); |
72 | | - grid[r.position.y as usize] |= 1 << r.position.x; |
73 | | - } |
| 67 | + let counter = AtomicI32::new(0); |
| 68 | + let result = AtomicI32::new(i32::MAX); |
| 69 | + |
| 70 | + worker_pool(|| { |
| 71 | + while result.load(Ordering::Acquire) == i32::MAX { |
| 72 | + let i = counter.fetch_add(1, Ordering::AcqRel); |
| 73 | + let mut grid = [0u128; HEIGHT as usize]; |
| 74 | + for r in &self.robots { |
| 75 | + let pos = r.position + (r.velocity * i); |
| 76 | + grid[pos.y.rem_euclid(HEIGHT) as usize] |= 1 << pos.x.rem_euclid(WIDTH); |
| 77 | + } |
74 | 78 |
|
75 | | - if grid.iter().any(|&b| Self::has_ten_consecutive_bits(b)) { |
76 | | - return i; |
| 79 | + if grid.iter().any(|&b| Self::has_ten_consecutive_bits(b)) { |
| 80 | + result.fetch_min(i, Ordering::AcqRel); |
| 81 | + return; |
| 82 | + } |
77 | 83 | } |
78 | | - } |
79 | | - unreachable!("no solution found") |
| 84 | + }); |
| 85 | + |
| 86 | + result.into_inner() as u32 |
80 | 87 | } |
81 | 88 |
|
82 | 89 | fn has_ten_consecutive_bits(b: u128) -> bool { |
|
0 commit comments