1
0
Fork 0
This commit is contained in:
Johann150 2023-02-09 21:59:25 +00:00
parent db3bb87e9e
commit cf1f4cfdcd
1 changed files with 169 additions and 0 deletions

169
src/main.rs Normal file
View File

@ -0,0 +1,169 @@
struct Board([u8; 9 * 9]);
struct SuperBoard([bool; 9 * 9 * 9]);
impl std::fmt::Display for Board {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for i in 0..9 * 9 {
if i % 9 > 0 {
if i % 3 == 0 {
write!(f, "|")?;
} else {
write!(f, " ")?;
}
} else if i > 0 && i % (9 * 3) == 0 {
writeln!(f, "-----+-----+-----")?;
}
match self.0[i] {
0 => {
write!(f, " ")?;
}
n => {
write!(f, "{n}")?;
}
}
if i % 9 == 8 {
writeln!(f)?;
}
}
Ok(())
}
}
impl std::fmt::Display for SuperBoard {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for j in 0..9 * 9 * 9 {
let col = j / 3 % 9;
let row = j / (9 * 9);
let n = j / 9 / 3 % 3 * 3 + j % 3;
if j == 0 {
// start of grid
} else if j % 243 == 0 {
writeln!(f, "-----------+-----------+-----------")?;
} else if j % 81 == 0 {
writeln!(f, "...........|...........|...........")?;
} else if j % 27 == 0 {
// start of line
} else if j % 9 == 0 {
write!(f, "|")?;
} else if j % 3 == 0 {
write!(f, ".")?;
}
let offset = n + (col * 9) + (row * 9 * 9);
if self.0[offset] {
write!(f, "{}", n + 1)?;
} else {
write!(f, " ")?;
}
if j % 27 == 26 {
// end of line
writeln!(f)?;
}
}
Ok(())
}
}
impl From<&Board> for SuperBoard {
fn from(board: &Board) -> SuperBoard {
let mut super_board = [false; 9 * 9 * 9];
for (i, &cell) in board.0.iter().enumerate() {
let super_i = i * 9;
match cell {
0 => {
for i in 0..9 {
super_board[super_i + i] = true;
}
}
n => {
super_board[super_i + n as usize - 1] = true;
}
}
}
SuperBoard(super_board)
}
}
impl Board {
fn constrain(&mut self) -> Result<SuperBoard, ()> {
let mut collapsed = self
.0
.iter()
.enumerate()
.filter(|(_, &x)| x != 0)
.map(|(i, _)| i)
.collect::<Vec<_>>();
let mut super_board = SuperBoard::from(&*self);
while let Some(i) = collapsed.pop() {
let value = self.0[i];
assert!(value > 0);
let offset = (value - 1) as usize;
// column
let col_start = i % 9;
let row_start = i - col_start;
let box_start = i / 27 * 27 + i % 9 / 3 * 3;
let to_constrain = (col_start..81)
.step_by(9)
.chain((row_start..81).take(9))
.chain((box_start..81).step_by(9).take(3).flat_map(|x| x..x + 3))
.collect::<std::collections::HashSet<_>>();
for j in to_constrain.into_iter() {
if i == j {
continue;
}
// safe to unwrap because none of the above can ever go outside the predefined bounds
let x = &mut super_board.0[j * 9 + offset];
if *x {
*x = false;
let cell = &super_board.0[(j * 9)..(j * 9 + 9)];
match cell.iter().filter(|&&x| x).count() {
0 => return Err(()),
1 => {
self.0[j] = cell
.iter()
.enumerate()
.find(|(_, &x)| x)
.map(|(i, _)| i + 1)
.unwrap() as u8;
if !collapsed.contains(&j) {
collapsed.push(j);
}
}
_ => (),
}
}
}
}
Ok(super_board)
}
}
fn main() {
let mut board = Board([
0, 6, 0, /**/ 0, 0, 1, /**/ 0, 0, 3,
8, 0, 0, /**/ 0, 0, 0, /**/ 0, 1, 9,
5, 0, 2, /**/ 0, 7, 0, /**/ 8, 4, 0,
/**********************************/
4, 0, 6, /**/ 9, 0, 2, /**/ 3, 0, 5,
0, 0, 0, /**/ 8, 0, 7, /**/ 0, 0, 0,
1, 0, 7, /**/ 5, 0, 3, /**/ 4, 0, 8,
/**********************************/
0, 4, 1, /**/ 0, 9, 0, /**/ 5, 0, 2,
9, 2, 0, /**/ 0, 0, 0, /**/ 0, 0, 7,
6, 0, 0, /**/ 2, 0, 0, /**/ 0, 9, 0,
]);
board.constrain().unwrap();
println!("{}", board);
}