|
@@ -37,7 +37,9 @@ struct Ksudoku {
|
|
|
game: Game,
|
|
|
}
|
|
|
|
|
|
-const SIZE: u8 = 9;
|
|
|
+/// Width of the sudoku board.
|
|
|
+const WIDTH: u8 = 9;
|
|
|
+/// Size (width * height) of the board.
|
|
|
const MAX_SIZE: u8 = 81;
|
|
|
|
|
|
#[derive(Debug)]
|
|
@@ -46,18 +48,19 @@ struct Sudoku {
|
|
|
possible: [HashSet<u8>; MAX_SIZE as usize],
|
|
|
}
|
|
|
|
|
|
-// Translate x,y to position in board.
|
|
|
+/// Translate x,y to position in board.
|
|
|
const fn pos(x: u8, y: u8) -> u8 {
|
|
|
- x + (y * SIZE as u8)
|
|
|
+ x + (y * WIDTH as u8)
|
|
|
}
|
|
|
|
|
|
+/// Translate x,y (with starting index of 1) to position in board.
|
|
|
const fn pos1(x: u8, y: u8) -> u8 {
|
|
|
- (x - 1) + ((y - 1) * SIZE as u8)
|
|
|
+ (x - 1) + ((y - 1) * WIDTH as u8)
|
|
|
}
|
|
|
|
|
|
-// Translate post to x,y in board.
|
|
|
+/// Translate post to x,y in board.
|
|
|
const fn xy(pos: u8) -> (u8, u8) {
|
|
|
- ((pos % SIZE), (pos / SIZE))
|
|
|
+ ((pos % WIDTH), (pos / WIDTH))
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -108,7 +111,7 @@ impl Sudoku {
|
|
|
// self.board[pos(x, y) as usize] = ch as u8 - 'a' as u8;
|
|
|
};
|
|
|
y += 1;
|
|
|
- if y >= SIZE {
|
|
|
+ if y >= WIDTH {
|
|
|
y = 0;
|
|
|
x += 1;
|
|
|
}
|
|
@@ -116,6 +119,30 @@ 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 = for_row(y);
|
|
|
+ // 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);
|
|
|
+ // g.for_column(x, y);
|
|
|
+ for g in g.items {
|
|
|
+ // remove value from these sets.
|
|
|
+ self.possible[g as usize].take(&value);
|
|
|
+ }
|
|
|
+ g = for_cell(which_cell(x,y));
|
|
|
+ // 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 set2(&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();
|
|
@@ -124,11 +151,13 @@ impl Sudoku {
|
|
|
// 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.
|
|
@@ -137,11 +166,12 @@ impl Sudoku {
|
|
|
self.possible[pos(x, y) as usize].clear();
|
|
|
}
|
|
|
|
|
|
+
|
|
|
fn display(&self) {
|
|
|
println!("╔═══╦═══╦═══╗");
|
|
|
- for y in 0..SIZE {
|
|
|
+ for y in 0..WIDTH {
|
|
|
print!("║");
|
|
|
- for x in 0..SIZE {
|
|
|
+ for x in 0..WIDTH {
|
|
|
let item = self.board[pos(x as u8, y as u8) as usize];
|
|
|
if item == 0 {
|
|
|
print!(" ");
|
|
@@ -154,7 +184,7 @@ impl Sudoku {
|
|
|
}
|
|
|
println!("");
|
|
|
if y % 3 == 2 {
|
|
|
- if y + 1 == SIZE {
|
|
|
+ if y + 1 == WIDTH {
|
|
|
println!("╚═══╩═══╩═══╝");
|
|
|
} else {
|
|
|
println!("╠═══╬═══╬═══╣");
|
|
@@ -164,8 +194,8 @@ impl Sudoku {
|
|
|
}
|
|
|
|
|
|
fn display_possible(&self) {
|
|
|
- for y in 0..SIZE {
|
|
|
- for x in 0..SIZE {
|
|
|
+ for y in 0..WIDTH {
|
|
|
+ for x in 0..WIDTH {
|
|
|
let mut possible = String::new();
|
|
|
|
|
|
for p in self.possible[pos(x, y) as usize].iter() {
|
|
@@ -212,7 +242,7 @@ impl Sudoku {
|
|
|
let mut group_process = |this: &mut Self, grp: &Group| {
|
|
|
// Collect all the possible values within the group.
|
|
|
values.clear();
|
|
|
- for gidx in 0..SIZE {
|
|
|
+ for gidx in 0..WIDTH {
|
|
|
// println!("possible: {:?}", this.possible[grp.items[gidx as usize] as usize]);
|
|
|
values.extend(&this.possible[grp.items[gidx as usize] as usize]);
|
|
|
// println!("now : {:?}", this.possible[grp.items[gidx as usize] as usize]);
|
|
@@ -224,7 +254,7 @@ impl Sudoku {
|
|
|
for v in values.iter() {
|
|
|
let mut count = 0;
|
|
|
let mut pos = 0;
|
|
|
- for gidx in 0..SIZE {
|
|
|
+ for gidx in 0..WIDTH {
|
|
|
if this.possible[grp.items[gidx as usize] as usize].contains(&v) {
|
|
|
count += 1;
|
|
|
pos = grp.items[gidx as usize];
|
|
@@ -244,25 +274,28 @@ impl Sudoku {
|
|
|
};
|
|
|
|
|
|
// Change to 0..SIZE ... Keep it simple.
|
|
|
- for i in 0..SIZE {
|
|
|
- g.for_column(i, 1);
|
|
|
+ for i in 0..WIDTH {
|
|
|
+ let mut g = for_column(i);
|
|
|
+ // g.for_column(i, 1);
|
|
|
group_process(self, &g);
|
|
|
- g.for_row(1, i);
|
|
|
+ g = for_row(i);
|
|
|
+ // g.for_row(1, i);
|
|
|
group_process(self, &g);
|
|
|
- g.for_iter(i);
|
|
|
+ g = for_cell(i);
|
|
|
+ // g.for_iter(i);
|
|
|
group_process(self, &g);
|
|
|
}
|
|
|
|
|
|
println!("Looking for pairs...");
|
|
|
// PAIR processing.
|
|
|
- for i in 0..SIZE {
|
|
|
+ for i in 0..WIDTH {
|
|
|
g.for_iter(i);
|
|
|
|
|
|
- for gidx in 0..SIZE - 1 {
|
|
|
+ for gidx in 0..WIDTH - 1 {
|
|
|
let gpos = g.items[gidx as usize];
|
|
|
if self.possible[gpos as usize].len() == 2 {
|
|
|
// Found a pair
|
|
|
- for fidx in gidx + 1..SIZE {
|
|
|
+ for fidx in gidx + 1..WIDTH {
|
|
|
let fpos = g.items[fidx as usize];
|
|
|
if self.possible[fpos as usize].len() == 2 {
|
|
|
// Ok, there's another pair
|
|
@@ -280,7 +313,7 @@ impl Sudoku {
|
|
|
|
|
|
let mut pair_removed = false;
|
|
|
|
|
|
- for remove in 0..SIZE {
|
|
|
+ for remove in 0..WIDTH {
|
|
|
if (gidx == remove) || (fidx == remove) {
|
|
|
continue;
|
|
|
}
|
|
@@ -318,7 +351,7 @@ impl Sudoku {
|
|
|
values[vpos] = *z;
|
|
|
vpos += 1;
|
|
|
}
|
|
|
- for remove in 0..SIZE {
|
|
|
+ for remove in 0..WIDTH {
|
|
|
if (remove == xy(gpos).1) || (remove == xy(fpos).1) {
|
|
|
continue;
|
|
|
}
|
|
@@ -345,7 +378,7 @@ impl Sudoku {
|
|
|
values[vpos] = *z;
|
|
|
vpos += 1;
|
|
|
}
|
|
|
- for remove in 0..SIZE {
|
|
|
+ for remove in 0..WIDTH {
|
|
|
if (remove == xy(gpos).0) || (remove == xy(fpos).0) {
|
|
|
continue;
|
|
|
}
|
|
@@ -375,12 +408,15 @@ impl Sudoku {
|
|
|
}
|
|
|
|
|
|
// #[derive(Debug)]
|
|
|
+/// Define a Group of sudoku positions.
|
|
|
+/// This defines rows, columns, and cells for analysis.
|
|
|
#[derive(PartialEq)]
|
|
|
struct Group {
|
|
|
- items: [u8; SIZE as usize],
|
|
|
+ items: [u8; WIDTH as usize],
|
|
|
}
|
|
|
|
|
|
-const ROW: [Group; 9] = [
|
|
|
+/// Group of positions for rows.
|
|
|
+const GROUP_ROW: [Group; 9] = [
|
|
|
Group {
|
|
|
items: [
|
|
|
pos1(1, 1),
|
|
@@ -500,7 +536,8 @@ const ROW: [Group; 9] = [
|
|
|
},
|
|
|
];
|
|
|
|
|
|
-const COLUMN: [Group; 9] = [
|
|
|
+/// Group of positions for columns.
|
|
|
+const GROUP_COLUMN: [Group; 9] = [
|
|
|
Group {
|
|
|
items: [
|
|
|
pos1(1, 1),
|
|
@@ -620,7 +657,8 @@ const COLUMN: [Group; 9] = [
|
|
|
},
|
|
|
];
|
|
|
|
|
|
-const CELL: [Group; 9] = [
|
|
|
+/// Group of positions for cells (3x3 grid).
|
|
|
+const GROUP_CELL: [Group; 9] = [
|
|
|
Group {
|
|
|
items: [
|
|
|
pos1(1, 1),
|
|
@@ -761,15 +799,20 @@ impl fmt::Debug for Group {
|
|
|
}
|
|
|
|
|
|
fn for_column(i: u8) -> &'static Group {
|
|
|
- &COLUMN[i as usize]
|
|
|
+ &GROUP_COLUMN[i as usize]
|
|
|
}
|
|
|
|
|
|
fn for_row(i: u8) -> &'static Group {
|
|
|
- &ROW[i as usize]
|
|
|
+ &GROUP_ROW[i as usize]
|
|
|
}
|
|
|
|
|
|
fn for_cell(i: u8) -> &'static Group {
|
|
|
- &CELL[i as usize]
|
|
|
+ &GROUP_CELL[i as usize]
|
|
|
+}
|
|
|
+
|
|
|
+/// Which cell contains this x,y?
|
|
|
+fn which_cell(x:u8, y:u8) -> u8 {
|
|
|
+ (x/3)+(y/3)*3
|
|
|
}
|
|
|
|
|
|
#[cfg(test)]
|
|
@@ -816,17 +859,17 @@ mod tests {
|
|
|
impl Group {
|
|
|
fn new() -> Self {
|
|
|
Group {
|
|
|
- items: [0; SIZE as usize],
|
|
|
+ items: [0; WIDTH as usize],
|
|
|
}
|
|
|
}
|
|
|
|
|
|
fn for_column(&mut self, x: u8, _y: u8) {
|
|
|
- for y in 0..SIZE {
|
|
|
+ for y in 0..WIDTH {
|
|
|
self.items[y as usize] = pos(x, y);
|
|
|
}
|
|
|
}
|
|
|
fn for_row(&mut self, _x: u8, y: u8) {
|
|
|
- for x in 0..SIZE {
|
|
|
+ for x in 0..WIDTH {
|
|
|
self.items[x as usize] = pos(x, y);
|
|
|
}
|
|
|
}
|
|
@@ -834,7 +877,7 @@ impl Group {
|
|
|
// Find starting block positions
|
|
|
let sb_x = x - (x % 3);
|
|
|
let sb_y = y - (y % 3);
|
|
|
- for i in 0..SIZE {
|
|
|
+ for i in 0..WIDTH {
|
|
|
let ix = i % 3;
|
|
|
let iy = i / 3;
|
|
|
// println!("i = {}, sb.x = {} sb.y = {}, ix = {} iy = {}", i, sb_x, sb_y, ix, iy);
|
|
@@ -849,7 +892,7 @@ impl Group {
|
|
|
}
|
|
|
|
|
|
fn display(&self) {
|
|
|
- for i in 0..SIZE {
|
|
|
+ for i in 0..WIDTH {
|
|
|
let v = self.items[i as usize];
|
|
|
print!("{} [{},{}] ", v, xy(v).0, xy(v).1);
|
|
|
}
|