A slightly cleaner implementation of regions

This commit is contained in:
Greg Hellings
2024-10-15 23:32:56 -05:00
parent 6ec40c15f4
commit 9af499c585
+77 -31
View File
@@ -1,30 +1,45 @@
use crate::cell::{Cell, CellValue}; use crate::cell::{Cell, CellValue};
use std::collections::HashSet; use std::collections::HashSet;
const REGION_SIZE: usize = 9;
const SUB_REGION_SIZE: usize = 3;
pub struct Board { pub struct Board {
cells: Vec<Vec<Cell>>, cells: Vec<Vec<Cell>>,
regions: Vec<Region>, squares: Vec<Region>,
rows: Vec<Region>,
cols: Vec<Region>,
} }
impl Board { impl Board {
pub fn new() -> Board { pub fn new() -> Board {
let mut rows = Vec::with_capacity(9); let mut cells = Vec::with_capacity(REGION_SIZE);
for _ in 0..9 { for _ in 0..REGION_SIZE {
let mut col = Vec::with_capacity(9); let mut col = Vec::with_capacity(REGION_SIZE);
for _ in 0..9 { for _ in 0..REGION_SIZE {
col.push(Cell::default()); col.push(Cell::default());
} }
rows.push(col); cells.push(col);
} }
let mut regions = Vec::with_capacity(9); let mut squares = Vec::with_capacity(REGION_SIZE);
for x in 0..3 { for x in 0..SUB_REGION_SIZE {
for y in 0..3 { for y in 0..SUB_REGION_SIZE {
regions.push(Region::new(&Point(x, y))); squares.push(Region::new_square(&Point(x, y)));
} }
} }
let mut rows = Vec::with_capacity(REGION_SIZE);
for x in 0..REGION_SIZE {
rows.push(Region::new_row(&Point(x, 0)));
}
let mut cols = Vec::with_capacity(REGION_SIZE);
for y in 0..REGION_SIZE {
cols.push(Region::new_col(&Point(0, y)));
}
let board = Board { let board = Board {
cells: rows, cells,
regions squares,
rows,
cols
}; };
board board
} }
@@ -35,25 +50,37 @@ impl Board {
pub fn set_value(&mut self, point: &Point, value: CellValue) { pub fn set_value(&mut self, point: &Point, value: CellValue) {
self.cells[point.0][point.1].set_value(value); self.cells[point.0][point.1].set_value(value);
self.update_row(point.0, value); self.update_regions(point, value);
self.update_column(point.1, value); }
self.update_region(point, value);
pub fn update_regions(&mut self, point: &Point, value: CellValue) {
self.update_columns(point, value);
self.update_rows(point, value);
self.update_squares(point, value);
} }
pub fn update_row(&mut self, x: usize, value: CellValue) { pub fn update_rows(&mut self, point: &Point, value: CellValue) {
for i in self.cells[x].iter_mut() { for row in self.rows.iter_mut() {
i.remove_candidate(value); if row.includes(point) {
for pt in row.iter_mut() {
self.cells[pt.0][pt.1].remove_candidate(value);
}
}
} }
} }
pub fn update_column(&mut self, y: usize, value: CellValue) { pub fn update_columns(&mut self, point: &Point, value: CellValue) {
for i in self.cells.iter_mut() { for col in self.cols.iter_mut() {
(*i)[y].remove_candidate(value); if col.includes(point) {
for pt in col.iter_mut() {
self.cells[pt.0][pt.1].remove_candidate(value);
}
}
} }
} }
pub fn update_region(&mut self, point: &Point, value: CellValue) { pub fn update_squares(&mut self, point: &Point, value: CellValue) {
for i in self.regions.iter_mut() { for i in self.squares.iter_mut() {
if i.includes(point) { if i.includes(point) {
for pt in i.iter_mut() { for pt in i.iter_mut() {
self.cells[pt.0][pt.1].remove_candidate(value); self.cells[pt.0][pt.1].remove_candidate(value);
@@ -75,27 +102,46 @@ pub struct Region {
} }
impl Region { impl Region {
pub fn new(start: &Point)-> Region { pub fn new_square(start: &Point)-> Region {
let mut points = Vec::with_capacity(9); let mut points = Vec::with_capacity(REGION_SIZE);
for x in start.0..(start.0 + 3) { for x in start.0..(start.0 + SUB_REGION_SIZE) {
for y in start.1..(start.1 + 3) { for y in start.1..(start.1 + SUB_REGION_SIZE) {
points.push(Point(x, y)); points.push(Point(x, y));
} }
} }
Region { Region {
points, points,
} }
} }
pub fn iter(&self) -> std::slice::Iter<Point> { pub fn new_row(start: &Point) -> Region {
let mut points = Vec::with_capacity(REGION_SIZE);
for y in 0..REGION_SIZE {
points.push(Point(start.0, y));
}
Region { points }
}
pub fn new_col(start: &Point) -> Region {
let mut points = Vec::with_capacity(REGION_SIZE);
for x in 0..REGION_SIZE {
points.push(Point(x, start.1));
}
Region { points }
}
}
impl Region {
fn iter(&self) -> std::slice::Iter<Point> {
self.points.iter() self.points.iter()
} }
pub fn includes(&self, point: &Point) -> bool { fn includes(&self, point: &Point) -> bool {
self.points.contains(point) self.points.contains(point)
} }
pub fn iter_mut(&mut self) -> std::slice::IterMut<Point> { fn iter_mut(&mut self) -> std::slice::IterMut<Point> {
self.points.iter_mut() self.points.iter_mut()
} }
} }