|
@@ -14,9 +14,9 @@ use bit_field::BitField;
|
|
|
|
|
|
extern crate rand_chacha;
|
|
extern crate rand_chacha;
|
|
use rand::prelude::*;
|
|
use rand::prelude::*;
|
|
|
|
+use rand::seq::SliceRandom;
|
|
use rand_chacha::rand_core::SeedableRng;
|
|
use rand_chacha::rand_core::SeedableRng;
|
|
use rand_chacha::ChaCha20Rng;
|
|
use rand_chacha::ChaCha20Rng;
|
|
-use rand::seq::SliceRandom;
|
|
|
|
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
|
pub struct Possible(u16);
|
|
pub struct Possible(u16);
|
|
@@ -340,20 +340,86 @@ impl Sudoku {
|
|
true
|
|
true
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ fn calculate_possible(&mut self, solutions: &mut u16) -> bool {
|
|
|
|
+ let backup = Sudoku {
|
|
|
|
+ board: self.board,
|
|
|
|
+ possible: self.possible,
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ for idx in 0..MAX_SIZE {
|
|
|
|
+ if self.board[idx as usize] == 0 {
|
|
|
|
+ // Ok, there's a blank here
|
|
|
|
+ let (x,y) = xy(idx);
|
|
|
|
+ 'outer:
|
|
|
|
+ for possible in 1..=9 {
|
|
|
|
+ let mut g = for_row(x);
|
|
|
|
+ for p in g.0 {
|
|
|
|
+ if self.board[p as usize] == possible {
|
|
|
|
+ continue 'outer;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ g = for_column(y);
|
|
|
|
+ for p in g.0 {
|
|
|
|
+ if self.board[p as usize] == possible {
|
|
|
|
+ continue 'outer;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // check cell
|
|
|
|
+ let cell = which_cell(x,y);
|
|
|
|
+ g = for_cell(cell);
|
|
|
|
+ for p in g.0 {
|
|
|
|
+ if self.board[p as usize] == possible {
|
|
|
|
+ continue 'outer;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Ok, it could go here!
|
|
|
|
+ self.board[idx as usize] = possible;
|
|
|
|
+ if self.puzzle_complete() {
|
|
|
|
+ *solutions += 1;
|
|
|
|
+ break;
|
|
|
|
+ } else {
|
|
|
|
+ if self.calculate_possible(solutions) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ self.board[idx as usize] = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ false
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn bruteforce_solver(&self) -> u16 {
|
|
|
|
+ let mut workset = Sudoku {
|
|
|
|
+ board: self.board,
|
|
|
|
+ possible: [Possible(0); MAX_SIZE as usize],
|
|
|
|
+ }; // self.possible };
|
|
|
|
+
|
|
|
|
+ let mut solutions :u16 = 0;
|
|
|
|
+ workset.calculate_possible(&mut solutions);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // find number of solutions.
|
|
|
|
+ solutions
|
|
|
|
+ }
|
|
|
|
+
|
|
pub fn make(&mut self) {
|
|
pub fn make(&mut self) {
|
|
let mut rng = ChaCha20Rng::from_entropy();
|
|
let mut rng = ChaCha20Rng::from_entropy();
|
|
|
|
|
|
self.fill_board(&mut rng);
|
|
self.fill_board(&mut rng);
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn fill_board(&mut self, rng : &mut ChaCha20Rng ) -> bool {
|
|
|
|
- let backup = Sudoku{ board: self.board,
|
|
|
|
- possible: self.possible
|
|
|
|
|
|
+ fn fill_board(&mut self, rng: &mut ChaCha20Rng) -> bool {
|
|
|
|
+ let backup = Sudoku {
|
|
|
|
+ board: self.board,
|
|
|
|
+ possible: self.possible,
|
|
};
|
|
};
|
|
|
|
|
|
for idx in 0..MAX_SIZE {
|
|
for idx in 0..MAX_SIZE {
|
|
if self.board[idx as usize] == 0 {
|
|
if self.board[idx as usize] == 0 {
|
|
- let (x,y) = xy(idx);
|
|
|
|
|
|
+ let (x, y) = xy(idx);
|
|
let mut available: [u8; WIDTH as usize] = [0; WIDTH as usize];
|
|
let mut available: [u8; WIDTH as usize] = [0; WIDTH as usize];
|
|
let mut total_available: u8 = 0;
|
|
let mut total_available: u8 = 0;
|
|
|
|
|
|
@@ -375,7 +441,7 @@ impl Sudoku {
|
|
available[0..total_available as usize].shuffle(rng);
|
|
available[0..total_available as usize].shuffle(rng);
|
|
for v_idx in 0..total_available {
|
|
for v_idx in 0..total_available {
|
|
let value = available[v_idx as usize];
|
|
let value = available[v_idx as usize];
|
|
- self.set(x,y, value);
|
|
|
|
|
|
+ self.set(x, y, value);
|
|
if self.fill_board(rng) {
|
|
if self.fill_board(rng) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -422,8 +488,8 @@ impl Sudoku {
|
|
let value = pick_one(self, &mut rng, i);
|
|
let value = pick_one(self, &mut rng, i);
|
|
if value.is_some() {
|
|
if value.is_some() {
|
|
let value = value.unwrap();
|
|
let value = value.unwrap();
|
|
- println!("Set({},{})={}", x, y, value);
|
|
|
|
- self.set(x, y, value);
|
|
|
|
|
|
+ println!("Set({},{})={}", x, y, value);
|
|
|
|
+ self.set(x, y, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|