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}