From 6ad197871f3bb042e9f9d74ba56d2d503bf346af Mon Sep 17 00:00:00 2001 From: Matthias Blankertz Date: Mon, 29 Jan 2024 15:55:53 +0100 Subject: [PATCH] clippy and fmt --- rustfmt.toml | 1 + src/main.rs | 495 ++++++++++++++++++++++++++++----------------------- 2 files changed, 273 insertions(+), 223 deletions(-) create mode 100644 rustfmt.toml diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..866c756 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +max_width = 120 \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 242faaf..e69a7e9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,53 +1,60 @@ -use std::fmt; use arr_macro::arr; +use std::fmt; const GRID_SIZE: usize = 9; -#[derive(Debug, PartialEq)] -#[derive(Clone, Copy)] +#[derive(Debug, PartialEq, Clone, Copy)] pub struct PossibleValues([bool; GRID_SIZE]); impl PossibleValues { fn get_value(&self) -> Option { - let mut val = 0u8; - for x in 0..GRID_SIZE { - if self.0[x] { - if val != 0 { panic!("get_value called on PossibleValue with more than one possiblitiy {}", self) } - val = (x+1) as u8; - } - } - if val == 0 { None } else { Some(val) } + let mut val = 0u8; + for x in 0..GRID_SIZE { + if self.0[x] { + if val != 0 { + panic!( + "get_value called on PossibleValue with more than one possiblitiy {}", + self + ) + } + val = (x + 1) as u8; + } + } + if val == 0 { + None + } else { + Some(val) + } } fn get_values(&self) -> Vec { - let mut v = Vec::::new(); - for x in 0..GRID_SIZE { - if self.0[x] { - v.push((x+1) as u8) - } - } - v + let mut v = Vec::::new(); + for x in 0..GRID_SIZE { + if self.0[x] { + v.push((x + 1) as u8) + } + } + v } fn get_count(&self) -> u8 { - let mut count = 0u8; - for x in 0..GRID_SIZE { - if self.0[x] { - count += 1; - } - } - count + let mut count = 0u8; + for x in 0..GRID_SIZE { + if self.0[x] { + count += 1; + } + } + count } } impl fmt::Display for PossibleValues { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad(format!("{:?}", self.get_values()).as_str()) + f.pad(format!("{:?}", self.get_values()).as_str()) } } -#[derive(Debug, PartialEq)] -#[derive(Clone, Copy)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum CellValue { None, Fixed(u8), @@ -56,27 +63,26 @@ pub enum CellValue { impl CellValue { fn from_possible(possible: PossibleValues) -> CellValue { - let cnt = possible.get_count(); - match cnt { - 0 => CellValue::None, - 1 => CellValue::Fixed(possible.get_value().unwrap()), - _ => CellValue::Possible(possible), - } + let cnt = possible.get_count(); + match cnt { + 0 => CellValue::None, + 1 => CellValue::Fixed(possible.get_value().unwrap()), + _ => CellValue::Possible(possible), + } } } impl fmt::Display for CellValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self { - CellValue::Possible(x) => write!(f, "{:27}", x), - CellValue::None => write!(f, "{:27}", "X"), - CellValue::Fixed(x) => write!(f, "{:<27}", x), - } + match &self { + CellValue::Possible(x) => write!(f, "{:27}", x), + CellValue::None => write!(f, "{:27}", "X"), + CellValue::Fixed(x) => write!(f, "{:<27}", x), + } } } -#[derive(Debug, PartialEq)] -#[derive(Clone, Copy)] +#[derive(Debug, PartialEq, Clone, Copy)] pub struct Grid { data: [CellValue; GRID_SIZE * GRID_SIZE], } @@ -91,10 +97,12 @@ impl<'a> Iterator for GridRowIterator<'a> { type Item = CellValue; fn next(&mut self) -> Option { - if self.pos >= GRID_SIZE { return None; } - let curr = self.parent.at(self.row, self.pos); - self.pos += 1; - Some(*curr) + if self.pos >= GRID_SIZE { + return None; + } + let curr = self.parent.at(self.row, self.pos); + self.pos += 1; + Some(*curr) } } @@ -108,10 +116,12 @@ impl<'a> Iterator for GridColIterator<'a> { type Item = CellValue; fn next(&mut self) -> Option { - if self.pos >= GRID_SIZE { return None; } - let curr = self.parent.at(self.pos, self.col); - self.pos += 1; - Some(*curr) + if self.pos >= GRID_SIZE { + return None; + } + let curr = self.parent.at(self.pos, self.col); + self.pos += 1; + Some(*curr) } } @@ -119,261 +129,289 @@ pub struct GridBlockIterator<'a> { parent: &'a Grid, pos: usize, row: usize, - col: usize + col: usize, } impl<'a> Iterator for GridBlockIterator<'a> { type Item = CellValue; fn next(&mut self) -> Option { - if self.pos >= GRID_SIZE { return None; } - let curr = self.parent.at(self.row + self.pos % 3, self.col + self.pos / 3); - self.pos += 1; - Some(*curr) + if self.pos >= GRID_SIZE { + return None; + } + let curr = self.parent.at(self.row + self.pos % 3, self.col + self.pos / 3); + self.pos += 1; + Some(*curr) + } +} + +impl Default for Grid { + fn default() -> Self { + Self::new() } } impl Grid { pub fn new() -> Grid { - Grid{data: arr![CellValue::None; 81]} + Grid { + data: arr![CellValue::None; 81], + } } pub fn from_array(input: [u8; 81]) -> Grid { - let mut g = Grid::new(); - for row in 0..GRID_SIZE { - for col in 0..GRID_SIZE { - match input[row * GRID_SIZE + col] { - 0 => *g.at_mut(row, col) = CellValue::None, - other => *g.at_mut(row, col) = CellValue::Fixed(other) - } - } - } - g.update(); - g + let mut g = Grid::new(); + for row in 0..GRID_SIZE { + for col in 0..GRID_SIZE { + match input[row * GRID_SIZE + col] { + 0 => *g.at_mut(row, col) = CellValue::None, + other => *g.at_mut(row, col) = CellValue::Fixed(other), + } + } + } + g.update(); + g } - + pub fn row_iter(&self, row: usize) -> GridRowIterator { - GridRowIterator{parent: self, pos: 0, row} + GridRowIterator { + parent: self, + pos: 0, + row, + } } pub fn col_iter(&self, col: usize) -> GridColIterator { - GridColIterator{parent: self, pos: 0, col} + GridColIterator { + parent: self, + pos: 0, + col, + } } pub fn block_iter(&self, row: usize, col: usize) -> GridBlockIterator { - let row = (row / 3) * 3; - let col = (col / 3) * 3; - GridBlockIterator{parent: self, pos: 0, row, col} + let row = (row / 3) * 3; + let col = (col / 3) * 3; + GridBlockIterator { + parent: self, + pos: 0, + row, + col, + } } // For all cells that are not fixed, compute possible values pub fn update(&mut self) { - for row in 0..GRID_SIZE { - for col in 0..GRID_SIZE { - if let CellValue::Fixed(_) = &self.at(row, col) { continue; } - *self.at_mut(row, col) = self.compute_possible(row, col); - } - } + for row in 0..GRID_SIZE { + for col in 0..GRID_SIZE { + if let CellValue::Fixed(_) = &self.at(row, col) { + continue; + } + *self.at_mut(row, col) = self.compute_possible(row, col); + } + } } // Find the shortest list of possible values pub fn find_shortest_possibles(&self) -> Option<(usize, usize, PossibleValues)> { - let mut len = 9; - let mut shortest_row : Option = None; - let mut shortest_col : Option = None; - for row in 0..GRID_SIZE { - for col in 0..GRID_SIZE { - if let CellValue::Possible(x) = &self.at(row, col) { - if x.get_count() <= len { - len = x.get_count(); - shortest_row = Some(row); - shortest_col = Some(col); - } - } - } - } - if let Some(row) = shortest_row { - let col = shortest_col.unwrap(); - let CellValue::Possible(val) = &self.at(row, col) else { panic!(); }; - Some((row, col, *val)) - } else { - None - } + let mut len = 9; + let mut shortest_row: Option = None; + let mut shortest_col: Option = None; + for row in 0..GRID_SIZE { + for col in 0..GRID_SIZE { + if let CellValue::Possible(x) = &self.at(row, col) { + if x.get_count() <= len { + len = x.get_count(); + shortest_row = Some(row); + shortest_col = Some(col); + } + } + } + } + if let Some(row) = shortest_row { + let col = shortest_col.unwrap(); + let CellValue::Possible(val) = &self.at(row, col) else { + panic!(); + }; + Some((row, col, *val)) + } else { + None + } } pub fn done(&self) -> bool { - for row in 0..GRID_SIZE { - for col in 0..GRID_SIZE { - match &self.at(row, col) { - CellValue::Possible(_) => return false, - CellValue::None => return false, - CellValue::Fixed(_) => continue, - } - } - } - return true; + for row in 0..GRID_SIZE { + for col in 0..GRID_SIZE { + match &self.at(row, col) { + CellValue::Possible(_) => return false, + CellValue::None => return false, + CellValue::Fixed(_) => continue, + } + } + } + true } pub fn possible(&self) -> bool { - for row in 0..GRID_SIZE { - for col in 0..GRID_SIZE { - match &self.at(row, col) { - CellValue::None => return false, - _ => continue, - } - } - } - return true; + for row in 0..GRID_SIZE { + for col in 0..GRID_SIZE { + match &self.at(row, col) { + CellValue::None => return false, + _ => continue, + } + } + } + true } - + pub fn at(&self, row: usize, col: usize) -> &CellValue { - if row >= GRID_SIZE || col >= GRID_SIZE { panic!("out of bounds access"); } - &self.data[row*GRID_SIZE + col] + if row >= GRID_SIZE || col >= GRID_SIZE { + panic!("out of bounds access"); + } + &self.data[row * GRID_SIZE + col] } pub fn at_mut(&mut self, row: usize, col: usize) -> &mut CellValue { - if row >= GRID_SIZE || col >= GRID_SIZE { panic!("out of bounds access"); } - &mut self.data[row*GRID_SIZE + col] - } - - fn get_value(&self, row: usize, col: usize) -> Option { - match &self.at(row, col) { - CellValue::Possible(x) => x.get_value(), - CellValue::None => None, - CellValue::Fixed(x) => Some(*x) - } - } - - fn get_values(&self, row: usize, col: usize) -> Vec { - match &self.at(row, col) { - CellValue::Possible(x) => x.get_values(), - CellValue::None => Vec::::new(), - CellValue::Fixed(x) => vec![*x], - } + if row >= GRID_SIZE || col >= GRID_SIZE { + panic!("out of bounds access"); + } + &mut self.data[row * GRID_SIZE + col] } fn compute_possible(&self, row: usize, col: usize) -> CellValue { - if let CellValue::Fixed(x) = &self.at(row, col) { return CellValue::Fixed(*x); } - let mut result = PossibleValues([true; 9]); - for other in self.row_iter(row) { - if let CellValue::Fixed(x) = other { result.0[(x-1) as usize] = false } - } - for other in self.col_iter(col) { - if let CellValue::Fixed(x) = other { result.0[(x-1) as usize] = false } - } - for other in self.block_iter(row, col) { - if let CellValue::Fixed(x) = other { result.0[(x-1) as usize] = false } - } - CellValue::from_possible(result) + if let CellValue::Fixed(x) = &self.at(row, col) { + return CellValue::Fixed(*x); + } + let mut result = PossibleValues([true; 9]); + for other in self.row_iter(row) { + if let CellValue::Fixed(x) = other { + result.0[(x - 1) as usize] = false + } + } + for other in self.col_iter(col) { + if let CellValue::Fixed(x) = other { + result.0[(x - 1) as usize] = false + } + } + for other in self.block_iter(row, col) { + if let CellValue::Fixed(x) = other { + result.0[(x - 1) as usize] = false + } + } + CellValue::from_possible(result) } } impl fmt::Display for Grid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for row in 0..GRID_SIZE { - for col in 0..GRID_SIZE { - write!(f, "{}", &self.at(row, col))?; - if col < GRID_SIZE-1 { - if (col + 1) % 3 == 0 { - write!(f, " || ")?; - } else { - write!(f, " | ")?; - } - } - } - if row < GRID_SIZE-1 { - if (row + 1) % 3 == 0 { - write!(f, "\n{}", "-".repeat(29*9+2))?; - } - writeln!(f)?; - } - } - Ok(()) + for row in 0..GRID_SIZE { + for col in 0..GRID_SIZE { + write!(f, "{}", &self.at(row, col))?; + if col < GRID_SIZE - 1 { + if (col + 1) % 3 == 0 { + write!(f, " || ")?; + } else { + write!(f, " | ")?; + } + } + } + if row < GRID_SIZE - 1 { + if (row + 1) % 3 == 0 { + write!(f, "\n{}", "-".repeat(29 * 9 + 2))?; + } + writeln!(f)?; + } + } + Ok(()) } } #[cfg(test)] mod tests { use super::*; - + #[test] fn possible_values() { - let none = PossibleValues([false; 9]); - let three = PossibleValues([false, false, true, false, false, false, false, false, false]); - let some = PossibleValues([false, true, false, true, false, false, false, false, false]); - let all = PossibleValues([true; 9]); + let none = PossibleValues([false; 9]); + let three = PossibleValues([false, false, true, false, false, false, false, false, false]); + let some = PossibleValues([false, true, false, true, false, false, false, false, false]); + let all = PossibleValues([true; 9]); - assert_eq!(None, none.get_value()); - assert_eq!(Some(3), three.get_value()); + assert_eq!(None, none.get_value()); + assert_eq!(Some(3), three.get_value()); - assert_eq!(0, none.get_count()); - assert_eq!(1, three.get_count()); - assert_eq!(2, some.get_count()); - assert_eq!(9, all.get_count()); + assert_eq!(0, none.get_count()); + assert_eq!(1, three.get_count()); + assert_eq!(2, some.get_count()); + assert_eq!(9, all.get_count()); - assert_eq!(Vec::::new(), none.get_values()); - assert_eq!(vec![3u8], three.get_values()); - assert_eq!(vec![2u8, 4u8], some.get_values()); - assert_eq!(vec![1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8], all.get_values()); + assert_eq!(Vec::::new(), none.get_values()); + assert_eq!(vec![3u8], three.get_values()); + assert_eq!(vec![2u8, 4u8], some.get_values()); + assert_eq!(vec![1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8], all.get_values()); } #[test] #[should_panic] fn possible_values_get_value() { - let some = PossibleValues([false, true, false, true, false, false, false, false, false]); - some.get_value(); + let some = PossibleValues([false, true, false, true, false, false, false, false, false]); + some.get_value(); } #[test] fn cellvalue_from_possible() { - let none = PossibleValues([false; 9]); - let three = PossibleValues([false, false, true, false, false, false, false, false, false]); - let some = PossibleValues([false, true, false, true, false, false, false, false, false]); - let all = PossibleValues([true; 9]); + let none = PossibleValues([false; 9]); + let three = PossibleValues([false, false, true, false, false, false, false, false, false]); + let some = PossibleValues([false, true, false, true, false, false, false, false, false]); + let all = PossibleValues([true; 9]); - assert_eq!(CellValue::None, CellValue::from_possible(none)); - assert_eq!(CellValue::Fixed(3), CellValue::from_possible(three)); - assert_eq!(CellValue::Possible(some), CellValue::from_possible(some)); - assert_eq!(CellValue::Possible(all), CellValue::from_possible(all)); + assert_eq!(CellValue::None, CellValue::from_possible(none)); + assert_eq!(CellValue::Fixed(3), CellValue::from_possible(three)); + assert_eq!(CellValue::Possible(some), CellValue::from_possible(some)); + assert_eq!(CellValue::Possible(all), CellValue::from_possible(all)); } #[test] fn new_grid_is_empty() { - let g = Grid::new(); - for row in 0..9 { - for col in 0..9 { - assert_eq!(None, g.get_value(row, col)); - } - } + let g = Grid::new(); + for row in 0..9 { + for col in 0..9 { + assert_eq!(None, g.get_value(row, col)); + } + } } } fn solve(g: Grid) -> Option { let mut queue = vec![g]; while let Some(mut work) = queue.pop() { - if !work.possible() { continue; } - let prev = work; - println!("{work}"); - println!(); - work.update(); - if work.done() { - return Some(work); - } else if prev == work { - let Some((row, col, possibles)) = work.find_shortest_possibles() else { continue; }; - for possible in possibles.get_values() { - let mut copy = work; - *copy.at_mut(row, col) = CellValue::Fixed(possible); - copy.update(); - queue.push(copy); - } - } else { - queue.push(work); - } + if !work.possible() { + continue; + } + let prev = work; + println!("{work}"); + println!(); + work.update(); + if work.done() { + return Some(work); + } else if prev == work { + let Some((row, col, possibles)) = work.find_shortest_possibles() else { + continue; + }; + for possible in possibles.get_values() { + let mut copy = work; + *copy.at_mut(row, col) = CellValue::Fixed(possible); + copy.update(); + queue.push(copy); + } + } else { + queue.push(work); + } } None } fn main() { + #[rustfmt::skip] let g = Grid::from_array([5, 3, 0, 0, 7, 0, 0, 0, 0, 6, 0, 0, 1, 9, 5, 0, 0, 0, 0, 9, 8, 0, 0, 0, 0, 6, 0, @@ -382,9 +420,14 @@ fn main() { 7, 0, 0, 0, 2, 0, 0, 0, 6, 0, 6, 0, 0, 0, 0, 2, 8, 0, 0, 0, 0, 4, 1, 9, 0, 0, 5, - 0, 0, 0, 0, 8, 0, 0, 7, 9]); - println!("{}\n", solve(g).map(|g| format!("{}", g)).unwrap_or("No solution".to_string())); + 0, 0, 0, 0, 8, 0, 0, 7, 9, + ]); + println!( + "{}\n", + solve(g).map(|g| format!("{}", g)).unwrap_or("No solution".to_string()) + ); + #[rustfmt::skip] let evil = Grid::from_array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 8, 5, 0, 0, 1, 0, 2, 0, 0, 0, 0, @@ -393,6 +436,12 @@ fn main() { 0, 9, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 7, 3, 0, 0, 2, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 4, 0, 0, 0, 9]); - println!("{}\n", solve(evil).map(|g| format!("{}", g)).unwrap_or("No solution".to_string())); + 0, 0, 0, 0, 4, 0, 0, 0, 9, + ]); + println!( + "{}\n", + solve(evil) + .map(|g| format!("{}", g)) + .unwrap_or("No solution".to_string()) + ); }