Skip to content

Commit 40e0554

Browse files
committed
🧻
1 parent 5c67471 commit 40e0554

File tree

4 files changed

+119
-1
lines changed

4 files changed

+119
-1
lines changed

‎aoc2025_wasm/inputs‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use anyhow::{Context, Result};
2+
use ndarray::Array2;
3+
4+
pub fn make_byte_grid(raw_inp: &str) -> Result<Array2<u8>> {
5+
let columns = raw_inp
6+
.trim()
7+
.bytes()
8+
.position(|c| c == b'\n')
9+
.context("can't get column count")?;
10+
11+
Array2::from_shape_vec(
12+
((raw_inp.trim().len() + 1) / (columns + 1), columns),
13+
raw_inp.bytes().filter(|&x| x != b'\n').collect(),
14+
)
15+
.context("can't make array")
16+
}
17+
18+
pub fn make_bool_grid<const TRUE_CHAR: u8>(raw_inp: &str) -> Result<Array2<bool>> {
19+
let columns = raw_inp
20+
.trim()
21+
.bytes()
22+
.position(|c| c == b'\n')
23+
.context("can't get column count")?;
24+
25+
Array2::from_shape_vec(
26+
((raw_inp.trim().len() + 1) / (columns + 1), columns),
27+
raw_inp
28+
.bytes()
29+
.filter(|&x| x != b'\n')
30+
.map(|b| b == TRUE_CHAR)
31+
.collect(),
32+
)
33+
.context("can't make array")
34+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use anyhow::Result;
2+
use ndarray::Array2;
3+
4+
fn neighbour_coords(y: usize, x: usize) -> [(usize, usize); 8] {
5+
[
6+
(y.wrapping_sub(1), x.wrapping_sub(1)),
7+
(y.wrapping_sub(1), x),
8+
(y.wrapping_sub(1), x.wrapping_add(1)),
9+
(y, x.wrapping_sub(1)),
10+
(y, x.wrapping_add(1)),
11+
(y.wrapping_add(1), x.wrapping_sub(1)),
12+
(y.wrapping_add(1), x),
13+
(y.wrapping_add(1), x.wrapping_add(1)),
14+
]
15+
}
16+
17+
fn neighbours(grid: &Array2<bool>, y: usize, x: usize) -> usize {
18+
neighbour_coords(y, x)
19+
.into_iter()
20+
.filter(|&(y, x)| *grid.get((y, x)).unwrap_or(&false))
21+
.count()
22+
}
23+
24+
fn calculate(mut grid: Array2<bool>) -> (u32, u32) {
25+
let mut p1 = 0;
26+
let mut p2 = 0;
27+
let mut changed_q = Vec::with_capacity(2048);
28+
29+
for y in 0..grid.dim().0 {
30+
for x in 0..grid.dim().1 {
31+
if *grid.get((y, x)).expect("indexes are valid") && neighbours(&grid, y, x) < 4 {
32+
p1 += 1;
33+
changed_q.push((y, x));
34+
}
35+
}
36+
}
37+
38+
while let Some((y, x)) = changed_q.pop() {
39+
{
40+
let itm = grid.get_mut((y, x)).expect("indexes are valid");
41+
if !*itm {
42+
continue;
43+
}
44+
*itm = false
45+
}
46+
p2 += 1;
47+
48+
neighbour_coords(y, x)
49+
.into_iter()
50+
.filter(|(y, x)| *grid.get((*y, *x)).unwrap_or(&false) && neighbours(&grid, *y, *x) < 4)
51+
.for_each(|(y, x)| changed_q.push((y, x)));
52+
}
53+
54+
(p1, p2)
55+
}
56+
57+
pub fn run_2025_04(inp: &str) -> Result<String> {
58+
let grid = crate::grid_util::make_bool_grid::<b'@'>(inp)?;
59+
let (p1, p2) = calculate(grid);
60+
Ok(format!("{p1}\n{p2}"))
61+
}
62+
63+
#[cfg(test)]
64+
mod tests {
65+
use super::*;
66+
67+
const EXAMPLE_DATA: &str = include_str!("../inputs/examples/2025_04");
68+
const REAL_DATA: &str = include_str!("../inputs/real/2025_04");
69+
70+
#[test]
71+
fn test_example() {
72+
let grid = crate::grid_util::make_bool_grid::<b'@'>(EXAMPLE_DATA).unwrap();
73+
assert_eq!(calculate(grid), (13, 43));
74+
}
75+
76+
#[test]
77+
fn test_real() {
78+
let grid = crate::grid_util::make_bool_grid::<b'@'>(REAL_DATA).unwrap();
79+
assert_eq!(calculate(grid), (1349, 8277));
80+
}
81+
}

‎aoc2025_wasm/src/lib.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
pub mod grid_util;
12
mod impl_2025_01;
23
mod impl_2025_02;
34
mod impl_2025_03;
5+
mod impl_2025_04;
46

57
pub use wasm_bindgen_rayon::init_thread_pool;
68

@@ -13,6 +15,7 @@ pub fn run_day(day: u32, input: &str) -> String {
1315
1 => impl_2025_01::run_2025_01(input),
1416
2 => impl_2025_02::run_2025_02(input),
1517
3 => impl_2025_03::run_2025_03(input),
18+
4 => impl_2025_04::run_2025_04(input),
1619
_ => Err(anyhow!("No solution for that day yet")),
1720
};
1821

0 commit comments

Comments
 (0)