From 9af499c58596e01244bc23d9b317b08e804cd79c Mon Sep 17 00:00:00 2001 From: Greg Hellings Date: Tue, 15 Oct 2024 23:32:56 -0500 Subject: [PATCH] A slightly cleaner implementation of regions --- src/board.rs | 108 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 31 deletions(-) diff --git a/src/board.rs b/src/board.rs index 9f9b542..cef7401 100644 --- a/src/board.rs +++ b/src/board.rs @@ -1,30 +1,45 @@ use crate::cell::{Cell, CellValue}; use std::collections::HashSet; +const REGION_SIZE: usize = 9; +const SUB_REGION_SIZE: usize = 3; + pub struct Board { cells: Vec>, - regions: Vec, + squares: Vec, + rows: Vec, + cols: Vec, } impl Board { pub fn new() -> Board { - let mut rows = Vec::with_capacity(9); - for _ in 0..9 { - let mut col = Vec::with_capacity(9); - for _ in 0..9 { + let mut cells = Vec::with_capacity(REGION_SIZE); + for _ in 0..REGION_SIZE { + let mut col = Vec::with_capacity(REGION_SIZE); + for _ in 0..REGION_SIZE { col.push(Cell::default()); } - rows.push(col); + cells.push(col); } - let mut regions = Vec::with_capacity(9); - for x in 0..3 { - for y in 0..3 { - regions.push(Region::new(&Point(x, y))); + let mut squares = Vec::with_capacity(REGION_SIZE); + for x in 0..SUB_REGION_SIZE { + for y in 0..SUB_REGION_SIZE { + 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 { - cells: rows, - regions + cells, + squares, + rows, + cols }; board } @@ -35,25 +50,37 @@ impl Board { pub fn set_value(&mut self, point: &Point, value: CellValue) { self.cells[point.0][point.1].set_value(value); - self.update_row(point.0, value); - self.update_column(point.1, value); - self.update_region(point, value); + self.update_regions(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) { - for i in self.cells[x].iter_mut() { - i.remove_candidate(value); + pub fn update_rows(&mut self, point: &Point, value: CellValue) { + for row in self.rows.iter_mut() { + 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) { - for i in self.cells.iter_mut() { - (*i)[y].remove_candidate(value); + pub fn update_columns(&mut self, point: &Point, value: CellValue) { + for col in self.cols.iter_mut() { + 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) { - for i in self.regions.iter_mut() { + pub fn update_squares(&mut self, point: &Point, value: CellValue) { + for i in self.squares.iter_mut() { if i.includes(point) { for pt in i.iter_mut() { self.cells[pt.0][pt.1].remove_candidate(value); @@ -75,27 +102,46 @@ pub struct Region { } impl Region { - pub fn new(start: &Point)-> Region { - let mut points = Vec::with_capacity(9); - for x in start.0..(start.0 + 3) { - for y in start.1..(start.1 + 3) { + pub fn new_square(start: &Point)-> Region { + let mut points = Vec::with_capacity(REGION_SIZE); + for x in start.0..(start.0 + SUB_REGION_SIZE) { + for y in start.1..(start.1 + SUB_REGION_SIZE) { points.push(Point(x, y)); } } Region { - points, + points, } } - pub fn iter(&self) -> std::slice::Iter { + 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 { self.points.iter() } - pub fn includes(&self, point: &Point) -> bool { + fn includes(&self, point: &Point) -> bool { self.points.contains(point) } - pub fn iter_mut(&mut self) -> std::slice::IterMut { + fn iter_mut(&mut self) -> std::slice::IterMut { self.points.iter_mut() } }