use crate::cell::{Cell, TernaryValue};
#[derive(Debug, Clone)]
pub struct Grid {
cells: Vec<Vec<Cell>>,
rows: usize,
cols: usize,
}
impl Grid {
pub fn new(rows: usize, cols: usize) -> Self {
let cells = (0..rows)
.map(|_| (0..cols).map(|_| Cell::neutral()).collect())
.collect();
Grid { cells, rows, cols }
}
pub fn dimensions(&self) -> (usize, usize) {
(self.rows, self.cols)
}
pub fn rows(&self) -> usize {
self.rows
}
pub fn cols(&self) -> usize {
self.cols
}
pub fn get(&self, row: usize, col: usize) -> Option<&Cell> {
self.cells.get(row).and_then(|r| r.get(col))
}
pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut Cell> {
self.cells.get_mut(row).and_then(|r| r.get_mut(col))
}
pub fn set(&mut self, row: usize, col: usize, value: TernaryValue) {
if let Some(cell) = self.get_mut(row, col) {
cell.set_value(value);
}
}
pub fn row(&self, row: usize) -> Option<&[Cell]> {
self.cells.get(row).map(|r| r.as_slice())
}
pub fn col(&self, col: usize) -> Option<Vec<Cell>> {
if col >= self.cols {
return None;
}
Some(self.cells.iter().map(|r| r[col].clone()).collect())
}
pub fn cells(&self) -> Vec<&Cell> {
self.cells.iter().flat_map(|r| r.iter()).collect()
}
pub fn range(&self, r1: usize, c1: usize, r2: usize, c2: usize) -> Vec<&Cell> {
let (r_min, r_max) = (r1.min(r2), r1.max(r2));
let (c_min, c_max) = (c1.min(c2), c1.max(c2));
self.cells.iter()
.enumerate()
.filter(|(r, _)| *r >= r_min && *r <= r_max)
.flat_map(|(_, row)| {
row.iter()
.enumerate()
.filter(|(c, _)| *c >= c_min && *c <= c_max)
.map(|(_, cell)| cell)
})
.collect()
}
pub fn range_mut(&mut self, r1: usize, c1: usize, r2: usize, c2: usize) -> Vec<&mut Cell> {
let (r_min, r_max) = (r1.min(r2), r1.max(r2));
let (c_min, c_max) = (c1.min(c2), c1.max(c2));
self.cells.iter_mut()
.enumerate()
.filter(move |(r, _)| *r >= r_min && *r <= r_max)
.flat_map(move |(_, row)| {
row.iter_mut()
.enumerate()
.filter(move |(c, _)| *c >= c_min && *c <= c_max)
.map(|(_, cell)| cell)
})
.collect()
}
pub fn for_each<F: FnMut(&mut Cell)>(&mut self, mut f: F) {
for row in &mut self.cells {
for cell in row.iter_mut() {
f(cell);
}
}
}
pub fn len(&self) -> usize {
self.rows * self.cols
}
pub fn is_empty(&self) -> bool {
self.rows == 0 || self.cols == 0
}
pub fn compute_all_fitness(&mut self) {
for row in &mut self.cells {
for cell in row.iter_mut() {
cell.set_fitness(cell.compute_default_fitness());
}
}
}
pub fn rows_mut(&mut self) -> &mut Vec<Vec<Cell>> {
&mut self.cells
}
pub fn parse_cell_ref(s: &str) -> Option<(usize, usize)> {
let s = s.trim();
let col_end = s.chars().position(|c| c.is_ascii_digit())?;
let col_str = &s[..col_end];
let row_str = &s[col_end..];
let mut col: usize = 0;
for ch in col_str.chars() {
if !ch.is_ascii_alphabetic() {
return None;
}
col = col * 26 + (ch.to_ascii_uppercase() as usize - 'A' as usize + 1);
}
if col == 0 { return None; }
col -= 1;
let row: usize = row_str.parse().ok()?;
if row == 0 { return None; }
Some((row - 1, col))
}
}