|
@@ -4,6 +4,8 @@ use serde_xml_rs::{from_reader, from_str, to_string};
|
|
|
use std::fmt;
|
|
|
use std::fs::File;
|
|
|
|
|
|
+use std::collections::HashSet;
|
|
|
+
|
|
|
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
|
|
struct Graph {
|
|
|
order: i32,
|
|
@@ -39,7 +41,7 @@ const MAX_SIZE: u8 = 81;
|
|
|
#[derive(Debug)]
|
|
|
struct Sudoku {
|
|
|
board: [u8; MAX_SIZE as usize],
|
|
|
- possible: [[u8; SIZE as usize]; MAX_SIZE as usize],
|
|
|
+ possible: [HashSet<u8>; MAX_SIZE as usize],
|
|
|
}
|
|
|
|
|
|
// Translate x,y to position in board.
|
|
@@ -52,12 +54,26 @@ const fn xy(pos: u8) -> (u8, u8) {
|
|
|
((pos % SIZE), (pos / SIZE))
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+(0 .. 10)
|
|
|
+ .map(|_| HashSet::<usize>::new())
|
|
|
+ .collect();
|
|
|
+
|
|
|
+let arr: [Vec<u32>; 10] = [(); 10].map(|_| Vec::with_capacity(100));
|
|
|
+
|
|
|
+*/
|
|
|
+
|
|
|
impl Sudoku {
|
|
|
fn new() -> Self {
|
|
|
+ // let b : HashSet<u8> = HashSet::from_iter(1..=9);
|
|
|
+
|
|
|
let s = Sudoku {
|
|
|
board: [0; MAX_SIZE as usize],
|
|
|
+ possible: [(); MAX_SIZE as usize].map(|_| HashSet::from_iter(1..=9)),
|
|
|
+ // possible: [HashSet::from_iter(1..=9); MAX_SIZE as usize],
|
|
|
// possible: [[0; SIZE as usize]; MAX_SIZE as usize],
|
|
|
- possible: [[1, 2, 3, 4, 5, 6, 7, 8, 9]; MAX_SIZE as usize],
|
|
|
+ // possible: [(0..MAX_SIZE).map( |_| (1..=9).collect())],
|
|
|
+ // possible: [(1..=9).map(|_| HashSet::new()).collect(); MAX_SIZE as usize],
|
|
|
};
|
|
|
s
|
|
|
}
|
|
@@ -65,7 +81,14 @@ impl Sudoku {
|
|
|
fn clear(&mut self) {
|
|
|
for x in 0..MAX_SIZE {
|
|
|
self.board[x as usize] = 0;
|
|
|
- self.possible[x as usize] = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
|
+ self.possible = [(); MAX_SIZE as usize].map(|_| HashSet::from_iter(1..=9));
|
|
|
+ /*
|
|
|
+ self.possible[x as usize].clear();
|
|
|
+ for i in 1..=9 {
|
|
|
+ self.possible[x as usize].insert(i);
|
|
|
+ }
|
|
|
+ */
|
|
|
+ // self.possible[x as usize] = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -75,7 +98,8 @@ impl Sudoku {
|
|
|
let mut y: u8 = 0;
|
|
|
for ch in s.chars() {
|
|
|
if ch >= 'b' {
|
|
|
- self.board[pos(x, y) as usize] = ch as u8 - 'a' as u8;
|
|
|
+ self.set(x, y, ch as u8 - 'a' as u8);
|
|
|
+ // self.board[pos(x, y) as usize] = ch as u8 - 'a' as u8;
|
|
|
};
|
|
|
y += 1;
|
|
|
if y >= SIZE {
|
|
@@ -85,6 +109,28 @@ impl Sudoku {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ fn set(&mut self, x: u8, y: u8, value: u8) {
|
|
|
+ self.board[pos(x, y) as usize] = value;
|
|
|
+ // Ok, update the possible
|
|
|
+ let mut g = Group::new();
|
|
|
+ g.for_row(x, y);
|
|
|
+ for g in g.items {
|
|
|
+ // remove value from these sets.
|
|
|
+ self.possible[g as usize].take(&value);
|
|
|
+ }
|
|
|
+ g.for_column(x, y);
|
|
|
+ for g in g.items {
|
|
|
+ // remove value from these sets.
|
|
|
+ self.possible[g as usize].take(&value);
|
|
|
+ }
|
|
|
+ g.for_block(x, y);
|
|
|
+ for g in g.items {
|
|
|
+ // remove value from these sets.
|
|
|
+ self.possible[g as usize].take(&value);
|
|
|
+ }
|
|
|
+ self.possible[pos(x, y) as usize].clear();
|
|
|
+ }
|
|
|
+
|
|
|
fn display(&self) {
|
|
|
println!("╔═══╦═══╦═══╗");
|
|
|
for y in 0..SIZE {
|
|
@@ -114,20 +160,47 @@ impl Sudoku {
|
|
|
fn display_possible(&self) {
|
|
|
for y in 0..SIZE {
|
|
|
for x in 0..SIZE {
|
|
|
+ let mut possible = String::new();
|
|
|
+
|
|
|
+ for p in self.possible[pos(x, y) as usize].iter() {
|
|
|
+ possible += format!("{}", p).as_str();
|
|
|
+ }
|
|
|
+
|
|
|
+ // for i in 0..SIZE {
|
|
|
+ // let &pos = self.possible[pos(x, y) as usize];
|
|
|
print!("({},{}):", x, y);
|
|
|
- for i in 0..SIZE {
|
|
|
- let pos = self.possible[pos(x, y) as usize][i as usize];
|
|
|
- if pos == 0 {
|
|
|
- print!(" ");
|
|
|
- } else {
|
|
|
- print!("{}", pos);
|
|
|
- }
|
|
|
+ // print!("{:20}", format!("{:?}", self.possible[pos(x, y) as usize]));
|
|
|
+ print!("{:9}", possible);
|
|
|
+ /*
|
|
|
+ if pos == 0 {
|
|
|
+ print!(" ");
|
|
|
+ } else {
|
|
|
+ print!("{}", pos);
|
|
|
}
|
|
|
- print!(" ");
|
|
|
+ */
|
|
|
+ // }
|
|
|
+ // print!(" ");
|
|
|
}
|
|
|
println!("");
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ fn solve(&mut self) -> bool {
|
|
|
+ // Pass 1: Look for singles in the possible sets.
|
|
|
+ let mut found_something = false;
|
|
|
+
|
|
|
+ for i in 0..MAX_SIZE {
|
|
|
+ if self.possible[i as usize].len() == 1 {
|
|
|
+ // Get the value
|
|
|
+ let value = self.possible[i as usize].iter().next().cloned().unwrap();
|
|
|
+ // Found one!
|
|
|
+ println!("Set {:?} to {}", xy(i), value);
|
|
|
+ self.set(xy(i).0, xy(i).1, value);
|
|
|
+ found_something = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ found_something
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// #[derive(Debug)]
|
|
@@ -204,6 +277,13 @@ fn main() {
|
|
|
s.display();
|
|
|
s.display_possible();
|
|
|
|
|
|
+ while s.solve() {
|
|
|
+ println!("Try it again...");
|
|
|
+ }
|
|
|
+ s.display();
|
|
|
+ s.display_possible();
|
|
|
+
|
|
|
+ /*
|
|
|
let mut g = Group::new();
|
|
|
g.for_row(1, 1);
|
|
|
print!("Row: ");
|
|
@@ -221,4 +301,5 @@ fn main() {
|
|
|
println!("({},{} {:#?})", i, i, g);
|
|
|
// g.display();
|
|
|
}
|
|
|
+ */
|
|
|
}
|