use crate::swarm::Swarm;
use crate::traits::Topology;
#[derive(Debug, Clone)]
pub struct VonNeumann {
rows: usize,
cols: usize,
}
impl VonNeumann {
pub fn new(rows: usize, cols: usize) -> Self {
assert!(rows >= 1 && cols >= 1, "the grid needs rows, cols >= 1");
Self { rows, cols }
}
pub fn square_for(n: usize) -> Self {
let mut rows = (n as f64).sqrt() as usize;
if rows == 0 {
rows = 1;
}
let cols = n.div_ceil(rows);
Self::new(rows, cols)
}
}
impl Topology for VonNeumann {
fn neighbors(&self, i: usize, swarm: &Swarm) -> Vec<usize> {
let n = swarm.len();
let (r, c) = (i / self.cols, i % self.cols);
let up = ((r + self.rows - 1) % self.rows) * self.cols + c;
let down = ((r + 1) % self.rows) * self.cols + c;
let left = r * self.cols + (c + self.cols - 1) % self.cols;
let right = r * self.cols + (c + 1) % self.cols;
let mut idx = Vec::with_capacity(5);
idx.push(i);
for j in [up, down, left, right] {
if j < n && !idx.contains(&j) {
idx.push(j);
}
}
idx
}
}