瀏覽代碼

Using const groups doesn't speed things up much.

Steve Thielemann 9 月之前
父節點
當前提交
6f675cfe4f
共有 1 個文件被更改,包括 79 次插入36 次删除
  1. 79 36
      src/main.rs

+ 79 - 36
src/main.rs

@@ -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);
         }