census.rs
1.8 kB · rust · 65 lines
1use mrlycore::tensor::Tensor;23/// Counts the cells of a grid holding one value.4pub fn count(grid: &Tensor, value: u8) -> usize {5 grid.bytes().iter().filter(|&&v| v == value).count()6}78/// Counts the faces where filled cells meet empty cells or the boundary: perimeter in 2d, surface in 3d.9pub fn exposed(grid: &Tensor) -> u128 {10 let dims = grid.shape.clone();11 let rank = dims.len();12 let mut total: u128 = 0;13 for flat in 0..grid.size() {14 if grid.bytes()[flat] == 0 {15 continue;16 }17 let mut rem = flat;18 let mut coord = Vec::with_capacity(rank);19 for axis in 0..rank {20 let stride: usize = dims[(axis + 1)..].iter().product();21 coord.push(rem / stride);22 rem %= stride;23 }24 for axis in 0..rank {25 if coord[axis] == 0 || {26 let mut lo = coord.clone();27 lo[axis] -= 1;28 grid.get(&lo) == 029 } {30 total += 1;31 }32 if coord[axis] + 1 == dims[axis] || {33 let mut hi = coord.clone();34 hi[axis] += 1;35 grid.get(&hi) == 036 } {37 total += 1;38 }39 }40 }41 total42}4344#[cfg(test)]45mod tests {46 use super::*;47 use mrlycore::atoms;48 #[test]49 fn exposed_is_perimeter_in_2d() {50 assert_eq!(exposed(&atoms::ones_2d(1)), 4);51 assert_eq!(exposed(&atoms::ones_2d(3)), 12);52 assert_eq!(exposed(&atoms::carpet_2d(3)), 16);53 }54 #[test]55 fn exposed_is_surface_in_3d() {56 assert_eq!(exposed(&atoms::ones_3d(1)), 6);57 assert_eq!(exposed(&atoms::ones_3d(2)), 24);58 }59 #[test]60 fn counts() {61 let c = atoms::carpet_2d(3);62 assert_eq!(count(&c, 1), 8);63 assert_eq!(count(&c, 0), 1);64 }65}