Pārlūkot izejas kodu

Logic pass1 & pass2 cleaner.

Pass3 seems broken, doesn't seem to find pairs and solve anything.
Steve Thielemann 4 mēneši atpakaļ
vecāks
revīzija
c7539d53c2
1 mainītis faili ar 149 papildinājumiem un 13 dzēšanām
  1. 149 13
      sudoku/src/sudoku.rs

+ 149 - 13
sudoku/src/sudoku.rs

@@ -613,6 +613,8 @@ impl AnyPossible {
      */
 
     /// Format all possible, finding max length.
+    /// - Return vec<string> of each item formatted.
+    /// - Return max length.
     pub fn pos_max(&self) -> (Vec<String>, usize) {
         let mut pos = Vec::<String>::new();
         pos.reserve(self.max_index);
@@ -628,6 +630,9 @@ impl AnyPossible {
         (pos, max)
     }
 
+    /// Display Possible
+    /// - Collect all of the possibles, with max length.
+    /// - Display formatted (using max length).
     pub fn display(&self) {
         let pos_info = self.pos_max();
 
@@ -635,18 +640,6 @@ impl AnyPossible {
             for x in 0..self.width {
                 let idx = self.pos(x, y);
 
-                /* 
-                let possible = self.possible[idx];
-                let values: Vec<u8> = possible.iter().collect();
-                // let stuff: String = values.into_iter().map(|i| i.to_string().push_str(",")).collect::<String>();
-                // let output = values.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
-
-                let stuff: String = values
-                    .into_iter()
-                    .map(|i| (i + 1).to_string())
-                    // .collect::<String>();
-                    .collect::<Vec<_>>().join(",");
-                */
                 print!("({},{}):{:3$} ", x + 1, y + 1, pos_info.0[idx], pos_info.1);
             }
             println!("");
@@ -889,6 +882,132 @@ impl AnySolver {
         true
     }
 
+    fn logic_pass1(&mut self) -> bool {
+        // Pass 1: Look for singles in the possible sets.
+        let mut pass1 = false;
+
+        // Repeat pass 1 until all have been found.
+        let mut pass1_again = true;
+
+        while pass1_again {
+            // Pass 1 - look for singles.
+            pass1_again = false;
+            let mut found_something = false;
+
+            for i in 0..self.possible.max_index {
+                if self.board.board[i] != 0 {
+                    // Skip, if position already filled.
+                    continue;
+                }
+
+                if self.possible.possible[i].count_set() == 1 {
+                    // Get value
+                    let value = self.possible.possible[i].iter().next().unwrap() + 1;
+                    let pos = self.board.xy(i);
+                    // println!("SET {}({},{})={}", i, pos.0 + 1, pos.1 + 1, value);
+                    self.set(pos.0, pos.1, value);
+                    found_something = true;
+                }
+            }
+
+            if found_something {
+                // We found something on this pass, so:
+                // - Try it again.
+                // - Record that we did something.
+                pass1 = true;
+                pass1_again = true;
+                found_something = false;
+            }
+        }
+        pass1
+    }
+
+    fn logic_pass2(&mut self) -> bool {
+        let mut found_something = false;
+
+        let mut pass2 = false;
+        let mut pass2_again = true;
+
+        let width = self.group.width;
+        let grp = self.group.clone();
+
+        while pass2_again {
+            pass2_again = false;
+
+            // let mut values = Bits(0); // HashSet<u8> = HashSet::new();
+            let mut values = GenBits::<u32>(0);
+
+            let mut group_process = |this: &mut Self, grp: &[usize]| {
+                // Collect all the possible values within the group.
+                values.clear();
+                for gidx in 0..width {
+                    // println!("possible: {:?}", this.possible[grp.items[gidx as usize] as usize]);
+                    for v in this.possible.possible[grp[gidx as usize]].iter() {
+                        values.set(v as usize, true);
+                    }
+                    // values.extend(this.possible[grp.0[gidx as usize] as usize]);
+                    // println!("now     : {:?}", this.possible[grp.items[gidx as usize] as usize]);
+                }
+
+                // println!("values {:?}", values);
+
+                // Now, check for singles.
+                for v in values.iter() {
+                    // println!("Check Value: {}", v);
+
+                    let mut count = 0;
+                    let mut pos = 0;
+
+                    for gidx in 0..width {
+                        if this.possible.possible[grp[gidx as usize]].get(v as usize) {
+                            // if this.possible[grp.0[gidx as usize] as usize].contains(&v) {
+                            count += 1;
+                            pos = grp[gidx as usize];
+                            if count > 1 {
+                                break;
+                            } else {
+                                // print!(" IDX {} POS {} ", gidx, pos);
+                            }
+                        }
+                    }
+                    if count == 1 {
+                        // don't need this, it was v!
+                        // let value = this.possible[pos as usize].iter().next().cloned().unwrap();
+                        let xy = this.board.xy(pos);
+                        // this.possible.display();
+                        // this.board.display();
+                        this.set(xy.0, xy.1, v + 1);
+                        // println!("SET {} ({},{}) = {}", pos, xy.0 + 1, xy.1 + 1, v+1);
+
+                        found_something = true;
+                    }
+                }
+            };
+
+            // Change to 0..WIDTH ...  Keep it simple.
+            for i in 0..width {
+                // println!("Column {i}:");
+                let mut g = grp.column(i);
+                group_process(self, g);
+                // println!("Row {i}:");
+                g = grp.row(i);
+                group_process(self, g);
+                // println!("Cell {i}:");
+                g = grp.cell(i);
+                group_process(self, g);
+            }
+
+            if found_something == true {
+                // Ok, pass 2 found something.
+                pass2 = true;                
+                found_something = false;
+                pass2_again = true;
+                // continue;
+            }
+        }
+        pass2
+    }
+
     /// Solve by logic alone.
     /// - Returns true when something was added to board.
     /// - Call solve until it returns false.
@@ -898,8 +1017,24 @@ impl AnySolver {
 
         // self.board.display();
         // self.possible.display();
-
+        let mut result = true;
         // Pass 1: Look for singles in the possible sets.
+        while result {
+            result = self.logic_pass1();
+            println!("Pass1");
+        }
+
+        let mut result2 = true;
+        while result2 {
+            result2 = self.logic_pass2();
+            println!("Pass2");
+        }
+
+        result || result2
+        /*
+        // Pass 2: Is the same as Pass 1!
+        // We just look in groups, instead of all the indexes.
+
         let mut found_something = false;
         let mut pass1 = false;
 
@@ -1222,6 +1357,7 @@ impl AnySolver {
         }
         println!("Pass 3 - Ending...");
         found_something
+        */
     }
 }