From cf1f4cfdcdc2f1706d48054e55b2a7fb91f44a06 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Thu, 9 Feb 2023 21:59:25 +0000 Subject: [PATCH] add code --- src/main.rs | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 src/main.rs diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e633504 --- /dev/null +++ b/src/main.rs @@ -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 { + let mut collapsed = self + .0 + .iter() + .enumerate() + .filter(|(_, &x)| x != 0) + .map(|(i, _)| i) + .collect::>(); + 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::>(); + + 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); +}