clippy and fmt

This commit is contained in:
2024-01-29 15:55:53 +01:00
parent 3b523257f0
commit 6ad197871f
2 changed files with 273 additions and 223 deletions

1
rustfmt.toml Normal file
View File

@@ -0,0 +1 @@
max_width = 120

View File

@@ -1,10 +1,9 @@
use std::fmt;
use arr_macro::arr; use arr_macro::arr;
use std::fmt;
const GRID_SIZE: usize = 9; const GRID_SIZE: usize = 9;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Clone, Copy)]
#[derive(Clone, Copy)]
pub struct PossibleValues([bool; GRID_SIZE]); pub struct PossibleValues([bool; GRID_SIZE]);
impl PossibleValues { impl PossibleValues {
@@ -12,11 +11,20 @@ impl PossibleValues {
let mut val = 0u8; let mut val = 0u8;
for x in 0..GRID_SIZE { for x in 0..GRID_SIZE {
if self.0[x] { if self.0[x] {
if val != 0 { panic!("get_value called on PossibleValue with more than one possiblitiy {}", self) } if val != 0 {
panic!(
"get_value called on PossibleValue with more than one possiblitiy {}",
self
)
}
val = (x + 1) as u8; val = (x + 1) as u8;
} }
} }
if val == 0 { None } else { Some(val) } if val == 0 {
None
} else {
Some(val)
}
} }
fn get_values(&self) -> Vec<u8> { fn get_values(&self) -> Vec<u8> {
@@ -46,8 +54,7 @@ impl fmt::Display for PossibleValues {
} }
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Clone, Copy)]
#[derive(Clone, Copy)]
pub enum CellValue { pub enum CellValue {
None, None,
Fixed(u8), Fixed(u8),
@@ -75,8 +82,7 @@ impl fmt::Display for CellValue {
} }
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq, Clone, Copy)]
#[derive(Clone, Copy)]
pub struct Grid { pub struct Grid {
data: [CellValue; GRID_SIZE * GRID_SIZE], data: [CellValue; GRID_SIZE * GRID_SIZE],
} }
@@ -91,7 +97,9 @@ impl<'a> Iterator for GridRowIterator<'a> {
type Item = CellValue; type Item = CellValue;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.pos >= GRID_SIZE { return None; } if self.pos >= GRID_SIZE {
return None;
}
let curr = self.parent.at(self.row, self.pos); let curr = self.parent.at(self.row, self.pos);
self.pos += 1; self.pos += 1;
Some(*curr) Some(*curr)
@@ -108,7 +116,9 @@ impl<'a> Iterator for GridColIterator<'a> {
type Item = CellValue; type Item = CellValue;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.pos >= GRID_SIZE { return None; } if self.pos >= GRID_SIZE {
return None;
}
let curr = self.parent.at(self.pos, self.col); let curr = self.parent.at(self.pos, self.col);
self.pos += 1; self.pos += 1;
Some(*curr) Some(*curr)
@@ -119,23 +129,33 @@ pub struct GridBlockIterator<'a> {
parent: &'a Grid, parent: &'a Grid,
pos: usize, pos: usize,
row: usize, row: usize,
col: usize col: usize,
} }
impl<'a> Iterator for GridBlockIterator<'a> { impl<'a> Iterator for GridBlockIterator<'a> {
type Item = CellValue; type Item = CellValue;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.pos >= GRID_SIZE { return None; } if self.pos >= GRID_SIZE {
return None;
}
let curr = self.parent.at(self.row + self.pos % 3, self.col + self.pos / 3); let curr = self.parent.at(self.row + self.pos % 3, self.col + self.pos / 3);
self.pos += 1; self.pos += 1;
Some(*curr) Some(*curr)
} }
} }
impl Default for Grid {
fn default() -> Self {
Self::new()
}
}
impl Grid { impl Grid {
pub fn new() -> 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 { pub fn from_array(input: [u8; 81]) -> Grid {
@@ -144,7 +164,7 @@ impl Grid {
for col in 0..GRID_SIZE { for col in 0..GRID_SIZE {
match input[row * GRID_SIZE + col] { match input[row * GRID_SIZE + col] {
0 => *g.at_mut(row, col) = CellValue::None, 0 => *g.at_mut(row, col) = CellValue::None,
other => *g.at_mut(row, col) = CellValue::Fixed(other) other => *g.at_mut(row, col) = CellValue::Fixed(other),
} }
} }
} }
@@ -153,24 +173,39 @@ impl Grid {
} }
pub fn row_iter(&self, row: usize) -> GridRowIterator { 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 { 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 { pub fn block_iter(&self, row: usize, col: usize) -> GridBlockIterator {
let row = (row / 3) * 3; let row = (row / 3) * 3;
let col = (col / 3) * 3; let col = (col / 3) * 3;
GridBlockIterator{parent: self, pos: 0, row, col} GridBlockIterator {
parent: self,
pos: 0,
row,
col,
}
} }
// For all cells that are not fixed, compute possible values // For all cells that are not fixed, compute possible values
pub fn update(&mut self) { pub fn update(&mut self) {
for row in 0..GRID_SIZE { for row in 0..GRID_SIZE {
for col in 0..GRID_SIZE { for col in 0..GRID_SIZE {
if let CellValue::Fixed(_) = &self.at(row, col) { continue; } if let CellValue::Fixed(_) = &self.at(row, col) {
continue;
}
*self.at_mut(row, col) = self.compute_possible(row, col); *self.at_mut(row, col) = self.compute_possible(row, col);
} }
} }
@@ -194,7 +229,9 @@ impl Grid {
} }
if let Some(row) = shortest_row { if let Some(row) = shortest_row {
let col = shortest_col.unwrap(); let col = shortest_col.unwrap();
let CellValue::Possible(val) = &self.at(row, col) else { panic!(); }; let CellValue::Possible(val) = &self.at(row, col) else {
panic!();
};
Some((row, col, *val)) Some((row, col, *val))
} else { } else {
None None
@@ -211,7 +248,7 @@ impl Grid {
} }
} }
} }
return true; true
} }
pub fn possible(&self) -> bool { pub fn possible(&self) -> bool {
@@ -223,46 +260,42 @@ impl Grid {
} }
} }
} }
return true; true
} }
pub fn at(&self, row: usize, col: usize) -> &CellValue { pub fn at(&self, row: usize, col: usize) -> &CellValue {
if row >= GRID_SIZE || col >= GRID_SIZE { panic!("out of bounds access"); } if row >= GRID_SIZE || col >= GRID_SIZE {
panic!("out of bounds access");
}
&self.data[row * GRID_SIZE + col] &self.data[row * GRID_SIZE + col]
} }
pub fn at_mut(&mut self, row: usize, col: usize) -> &mut CellValue { pub fn at_mut(&mut self, row: usize, col: usize) -> &mut CellValue {
if row >= GRID_SIZE || col >= GRID_SIZE { panic!("out of bounds access"); } if row >= GRID_SIZE || col >= GRID_SIZE {
panic!("out of bounds access");
}
&mut self.data[row * GRID_SIZE + col] &mut self.data[row * GRID_SIZE + col]
} }
fn get_value(&self, row: usize, col: usize) -> Option<u8> {
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<u8> {
match &self.at(row, col) {
CellValue::Possible(x) => x.get_values(),
CellValue::None => Vec::<u8>::new(),
CellValue::Fixed(x) => vec![*x],
}
}
fn compute_possible(&self, row: usize, col: usize) -> CellValue { fn compute_possible(&self, row: usize, col: usize) -> CellValue {
if let CellValue::Fixed(x) = &self.at(row, col) { return CellValue::Fixed(*x); } if let CellValue::Fixed(x) = &self.at(row, col) {
return CellValue::Fixed(*x);
}
let mut result = PossibleValues([true; 9]); let mut result = PossibleValues([true; 9]);
for other in self.row_iter(row) { for other in self.row_iter(row) {
if let CellValue::Fixed(x) = other { result.0[(x-1) as usize] = false } if let CellValue::Fixed(x) = other {
result.0[(x - 1) as usize] = false
}
} }
for other in self.col_iter(col) { for other in self.col_iter(col) {
if let CellValue::Fixed(x) = other { result.0[(x-1) as usize] = false } if let CellValue::Fixed(x) = other {
result.0[(x - 1) as usize] = false
}
} }
for other in self.block_iter(row, col) { for other in self.block_iter(row, col) {
if let CellValue::Fixed(x) = other { result.0[(x-1) as usize] = false } if let CellValue::Fixed(x) = other {
result.0[(x - 1) as usize] = false
}
} }
CellValue::from_possible(result) CellValue::from_possible(result)
} }
@@ -351,7 +384,9 @@ mod tests {
fn solve(g: Grid) -> Option<Grid> { fn solve(g: Grid) -> Option<Grid> {
let mut queue = vec![g]; let mut queue = vec![g];
while let Some(mut work) = queue.pop() { while let Some(mut work) = queue.pop() {
if !work.possible() { continue; } if !work.possible() {
continue;
}
let prev = work; let prev = work;
println!("{work}"); println!("{work}");
println!(); println!();
@@ -359,7 +394,9 @@ fn solve(g: Grid) -> Option<Grid> {
if work.done() { if work.done() {
return Some(work); return Some(work);
} else if prev == work { } else if prev == work {
let Some((row, col, possibles)) = work.find_shortest_possibles() else { continue; }; let Some((row, col, possibles)) = work.find_shortest_possibles() else {
continue;
};
for possible in possibles.get_values() { for possible in possibles.get_values() {
let mut copy = work; let mut copy = work;
*copy.at_mut(row, col) = CellValue::Fixed(possible); *copy.at_mut(row, col) = CellValue::Fixed(possible);
@@ -374,6 +411,7 @@ fn solve(g: Grid) -> Option<Grid> {
} }
fn main() { fn main() {
#[rustfmt::skip]
let g = Grid::from_array([5, 3, 0, 0, 7, 0, 0, 0, 0, let g = Grid::from_array([5, 3, 0, 0, 7, 0, 0, 0, 0,
6, 0, 0, 1, 9, 5, 0, 0, 0, 6, 0, 0, 1, 9, 5, 0, 0, 0,
0, 9, 8, 0, 0, 0, 0, 6, 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, 7, 0, 0, 0, 2, 0, 0, 0, 6,
0, 6, 0, 0, 0, 0, 2, 8, 0, 0, 6, 0, 0, 0, 0, 2, 8, 0,
0, 0, 0, 4, 1, 9, 0, 0, 5, 0, 0, 0, 4, 1, 9, 0, 0, 5,
0, 0, 0, 0, 8, 0, 0, 7, 9]); 0, 0, 0, 0, 8, 0, 0, 7, 9,
println!("{}\n", solve(g).map(|g| format!("{}", g)).unwrap_or("No solution".to_string())); ]);
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, 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, 0, 0, 0, 3, 0, 8, 5,
0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0,
@@ -393,6 +436,12 @@ fn main() {
0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
5, 0, 0, 0, 0, 0, 0, 7, 3, 5, 0, 0, 0, 0, 0, 0, 7, 3,
0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 4, 0, 0, 0, 9]); 0, 0, 0, 0, 4, 0, 0, 0, 9,
println!("{}\n", solve(evil).map(|g| format!("{}", g)).unwrap_or("No solution".to_string())); ]);
println!(
"{}\n",
solve(evil)
.map(|g| format!("{}", g))
.unwrap_or("No solution".to_string())
);
} }