ternary_spreadsheet/
grid.rs1use crate::cell::{Cell, TernaryValue};
2
3#[derive(Debug, Clone)]
5pub struct Grid {
6 cells: Vec<Vec<Cell>>,
7 rows: usize,
8 cols: usize,
9}
10
11impl Grid {
12 pub fn new(rows: usize, cols: usize) -> Self {
14 let cells = (0..rows)
15 .map(|_| (0..cols).map(|_| Cell::neutral()).collect())
16 .collect();
17 Grid { cells, rows, cols }
18 }
19
20 pub fn dimensions(&self) -> (usize, usize) {
22 (self.rows, self.cols)
23 }
24
25 pub fn rows(&self) -> usize {
27 self.rows
28 }
29
30 pub fn cols(&self) -> usize {
32 self.cols
33 }
34
35 pub fn get(&self, row: usize, col: usize) -> Option<&Cell> {
37 self.cells.get(row).and_then(|r| r.get(col))
38 }
39
40 pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut Cell> {
42 self.cells.get_mut(row).and_then(|r| r.get_mut(col))
43 }
44
45 pub fn set(&mut self, row: usize, col: usize, value: TernaryValue) {
47 if let Some(cell) = self.get_mut(row, col) {
48 cell.set_value(value);
49 }
50 }
51
52 pub fn row(&self, row: usize) -> Option<&[Cell]> {
54 self.cells.get(row).map(|r| r.as_slice())
55 }
56
57 pub fn col(&self, col: usize) -> Option<Vec<Cell>> {
59 if col >= self.cols {
60 return None;
61 }
62 Some(self.cells.iter().map(|r| r[col].clone()).collect())
63 }
64
65 pub fn cells(&self) -> Vec<&Cell> {
67 self.cells.iter().flat_map(|r| r.iter()).collect()
68 }
69
70 pub fn range(&self, r1: usize, c1: usize, r2: usize, c2: usize) -> Vec<&Cell> {
72 let (r_min, r_max) = (r1.min(r2), r1.max(r2));
73 let (c_min, c_max) = (c1.min(c2), c1.max(c2));
74 self.cells.iter()
75 .enumerate()
76 .filter(|(r, _)| *r >= r_min && *r <= r_max)
77 .flat_map(|(_, row)| {
78 row.iter()
79 .enumerate()
80 .filter(|(c, _)| *c >= c_min && *c <= c_max)
81 .map(|(_, cell)| cell)
82 })
83 .collect()
84 }
85
86 pub fn range_mut(&mut self, r1: usize, c1: usize, r2: usize, c2: usize) -> Vec<&mut Cell> {
88 let (r_min, r_max) = (r1.min(r2), r1.max(r2));
89 let (c_min, c_max) = (c1.min(c2), c1.max(c2));
90 self.cells.iter_mut()
91 .enumerate()
92 .filter(move |(r, _)| *r >= r_min && *r <= r_max)
93 .flat_map(move |(_, row)| {
94 row.iter_mut()
95 .enumerate()
96 .filter(move |(c, _)| *c >= c_min && *c <= c_max)
97 .map(|(_, cell)| cell)
98 })
99 .collect()
100 }
101
102 pub fn for_each<F: FnMut(&mut Cell)>(&mut self, mut f: F) {
104 for row in &mut self.cells {
105 for cell in row.iter_mut() {
106 f(cell);
107 }
108 }
109 }
110
111 pub fn len(&self) -> usize {
113 self.rows * self.cols
114 }
115
116 pub fn is_empty(&self) -> bool {
118 self.rows == 0 || self.cols == 0
119 }
120
121 pub fn compute_all_fitness(&mut self) {
123 for row in &mut self.cells {
124 for cell in row.iter_mut() {
125 cell.set_fitness(cell.compute_default_fitness());
126 }
127 }
128 }
129
130 pub fn rows_mut(&mut self) -> &mut Vec<Vec<Cell>> {
132 &mut self.cells
133 }
134
135 pub fn parse_cell_ref(s: &str) -> Option<(usize, usize)> {
137 let s = s.trim();
138 let col_end = s.chars().position(|c| c.is_ascii_digit())?;
139 let col_str = &s[..col_end];
140 let row_str = &s[col_end..];
141
142 let mut col: usize = 0;
143 for ch in col_str.chars() {
144 if !ch.is_ascii_alphabetic() {
145 return None;
146 }
147 col = col * 26 + (ch.to_ascii_uppercase() as usize - 'A' as usize + 1);
148 }
149 if col == 0 { return None; }
150 col -= 1;
151
152 let row: usize = row_str.parse().ok()?;
153 if row == 0 { return None; }
154 Some((row - 1, col))
155 }
156}