|  | @@ -7,7 +7,6 @@ use strum::IntoEnumIterator;
 | 
	
		
			
				|  |  |  extern crate rand_chacha;
 | 
	
		
			
				|  |  |  use rand::distributions::{Distribution, Uniform};
 | 
	
		
			
				|  |  |  use rand::seq::SliceRandom;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  use rand_chacha::rand_core::SeedableRng;
 | 
	
		
			
				|  |  |  use rand_chacha::ChaCha20Rng;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -583,6 +582,11 @@ yet another.  I think that's how I mentally judge the puzzles.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +pub struct Pairs {
 | 
	
		
			
				|  |  | +    pub values: [u8; 2],
 | 
	
		
			
				|  |  | +    pub pos: [u8; 2],
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #[derive(Debug, Clone)]
 | 
	
		
			
				|  |  |  pub struct AnySolver {
 | 
	
		
			
				|  |  |      pub board: AnyBoard,
 | 
	
	
		
			
				|  | @@ -638,9 +642,10 @@ impl AnySolver {
 | 
	
		
			
				|  |  |      /// Process a move
 | 
	
		
			
				|  |  |      /// - Remove value from rows, columns, and cells.
 | 
	
		
			
				|  |  |      /// - Clear possibles from (x,y) position, it's filled.
 | 
	
		
			
				|  |  | -    /// - **THIS PANICS** debug_assert!, panics in test validated_board
 | 
	
		
			
				|  |  | -    /// TO FIX: This needs to return an error. (someway, somehow)
 | 
	
		
			
				|  |  | -    pub fn process_move(&mut self, x: u8, y: u8, value: u8) {
 | 
	
		
			
				|  |  | +    /// - Added finalize parameter
 | 
	
		
			
				|  |  | +    ///   - Use it when doing a single move.
 | 
	
		
			
				|  |  | +    ///   - Don't do it when setting up the board.  Call finalize_move then.
 | 
	
		
			
				|  |  | +    pub fn process_move(&mut self, x: u8, y: u8, value: u8, finalize: bool) {
 | 
	
		
			
				|  |  |          debug_assert!(
 | 
	
		
			
				|  |  |              x <= self.board.width && y <= self.board.width,
 | 
	
		
			
				|  |  |              "Expected ({}, {}) <= {}",
 | 
	
	
		
			
				|  | @@ -703,8 +708,9 @@ impl AnySolver {
 | 
	
		
			
				|  |  |          */
 | 
	
		
			
				|  |  |          self.cell_poss[cell_index as usize].set(value as usize - 1, false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        self.finalize_cell(cell_index);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        if finalize {
 | 
	
		
			
				|  |  | +            self.finalize_cell(cell_index);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |          // Should I do the checks here for the logic possible fix?
 | 
	
		
			
				|  |  |          // Or, should I make it a different function?
 | 
	
		
			
				|  |  |          // Put somewhere else, since it has to re-check the entire board!
 | 
	
	
		
			
				|  | @@ -712,16 +718,200 @@ impl AnySolver {
 | 
	
		
			
				|  |  |          // OR, just check row and columns?
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /// find_pairs:  Finds the pairs (and triples, and quads, and ...)
 | 
	
		
			
				|  |  | +    /// Must be a vector, because size is self.board.width (dynamic)
 | 
	
		
			
				|  |  | +    /// Returns vector[values 0..width], of positions values are seen.
 | 
	
		
			
				|  |  | +    /// [0] = "1" = vec![list of positions containing a possible 1]
 | 
	
		
			
				|  |  | +    pub fn find_pairs(&mut self, cell_index: u8) -> Vec<GenBits<u32>> {
 | 
	
		
			
				|  |  | +        // result[value] = indexes where it is located?
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let initial = GenBits::<u32>(0);
 | 
	
		
			
				|  |  | +        let mut result: Vec<GenBits<u32>> = vec![initial; self.board.width as usize];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Find starting row and column for given cell.
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +        // let (col, row) = self.group.cell_start(cell_index);
 | 
	
		
			
				|  |  | +        // let size = self.board.size;
 | 
	
		
			
				|  |  | +        /* 
 | 
	
		
			
				|  |  | +        let size = self.board.size;
 | 
	
		
			
				|  |  | +        let col = (cell_index % size) * size;
 | 
	
		
			
				|  |  | +        let row = (cell_index / size) * size;
 | 
	
		
			
				|  |  | +        */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // println!("Cell {} Starts at {},{}", cell_index, col, row);
 | 
	
		
			
				|  |  | +        let cellgroup = self.group.group(Groups::Cell, cell_index);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for value in 0..self.board.width {
 | 
	
		
			
				|  |  | +            // Locate every position with a 1
 | 
	
		
			
				|  |  | +            for pos in 0..self.board.width {
 | 
	
		
			
				|  |  | +                let cellindex = cellgroup[pos as usize];
 | 
	
		
			
				|  |  | +                /* 
 | 
	
		
			
				|  |  | +                let x = col + (pos % size);
 | 
	
		
			
				|  |  | +                let y = row + (pos / size);
 | 
	
		
			
				|  |  | +                */
 | 
	
		
			
				|  |  | +                // println!("Pos {} ({},{}) Value {}", pos, x, y, value);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if self
 | 
	
		
			
				|  |  | +                    .possible
 | 
	
		
			
				|  |  | +                    .get(cellindex, value as usize + 1)
 | 
	
		
			
				|  |  | +                    // .get(self.possible.pos(x, y), value as usize + 1)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    // println!("Found {} ({},{}) = {}", cell_index, x, y, value);
 | 
	
		
			
				|  |  | +                    result[value as usize].set(pos as usize, true);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Ok, this is good, but not useful.  ;)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let zero_bits = GenBits::<u32>(0);
 | 
	
		
			
				|  |  | +        let width = self.board.width;
 | 
	
		
			
				|  |  | +        let mut possibles_updated : bool = false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        'outer: for idx in 0..width-1 {
 | 
	
		
			
				|  |  | +            // pos_found contains the positions.
 | 
	
		
			
				|  |  | +            let pos_found = result[idx as usize]; 
 | 
	
		
			
				|  |  | +            if pos_found == zero_bits {
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if idx > 0 {
 | 
	
		
			
				|  |  | +                // Check previous for matches - already checked...
 | 
	
		
			
				|  |  | +                for check in 0..idx {
 | 
	
		
			
				|  |  | +                    if pos_found == result[check as usize] {
 | 
	
		
			
				|  |  | +                        continue 'outer;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            let count = pos_found.count_set();
 | 
	
		
			
				|  |  | +            if count == 1 {
 | 
	
		
			
				|  |  | +                // Single possible item here ... skip this for now.
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            let mut matches = 1;
 | 
	
		
			
				|  |  | +            // Pos contains the numbers in the cell.
 | 
	
		
			
				|  |  | +            let mut pos = Vec::<u8>::new();
 | 
	
		
			
				|  |  | +            pos.push(idx);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for look in idx+1..width {
 | 
	
		
			
				|  |  | +                if result[look as usize] == pos_found {
 | 
	
		
			
				|  |  | +                    matches += 1;
 | 
	
		
			
				|  |  | +                    pos.push(look);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if matches == count {
 | 
	
		
			
				|  |  | +                // Ok! We found a pair (or triple, or quad, or ...)
 | 
	
		
			
				|  |  | +                // Build new possible
 | 
	
		
			
				|  |  | +                let mut new_possible = zero_bits;
 | 
	
		
			
				|  |  | +                for p in &pos {
 | 
	
		
			
				|  |  | +                    new_possible.set(*p as usize, true);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                for p in pos_found.iter() {
 | 
	
		
			
				|  |  | +                    if self.possible.possible[cellgroup[p as usize]] != new_possible {
 | 
	
		
			
				|  |  | +                        println!("Update pos {} with {:?}", p, new_possible);
 | 
	
		
			
				|  |  | +                        println!("Index is {} => {:?}", cellgroup[p as usize], self.group.xy(cellgroup[p as usize]));
 | 
	
		
			
				|  |  | +                        possibles_updated = true;
 | 
	
		
			
				|  |  | +                        self.possible.possible[cellgroup[p as usize]] = new_possible;
 | 
	
		
			
				|  |  | +                        println!("Updated!");
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        result
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      /// Finalize move on the board.
 | 
	
		
			
				|  |  |      /// - This uses the cell index last modified, so we have fewer
 | 
	
		
			
				|  |  |      ///   cells to check here. (2 * size) cells.
 | 
	
		
			
				|  |  | -    pub fn finalize_cell(&mut self, index:u8) {
 | 
	
		
			
				|  |  | -        let size = self.board.size;
 | 
	
		
			
				|  |  | +    pub fn finalize_cell(&mut self, index: u8) {
 | 
	
		
			
				|  |  | +        let size = self.board.width;
 | 
	
		
			
				|  |  | +        let mut update: bool = false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /* 
 | 
	
		
			
				|  |  | +        let values = self.find_pairs(index);
 | 
	
		
			
				|  |  | +        // ok! Scan, and find pairs, triples, etc.
 | 
	
		
			
				|  |  | +        println!("Finalize Cell {}: {:?}", index, values);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        'outer: for idx in 0..size-1 {
 | 
	
		
			
				|  |  | +            // Positions found
 | 
	
		
			
				|  |  | +            let pos_found = values[idx as usize];
 | 
	
		
			
				|  |  | +            if pos_found == (GenBits::<u32>(0)) {
 | 
	
		
			
				|  |  | +                println!("Idx {}: (empty)", idx);
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if idx > 0 {
 | 
	
		
			
				|  |  | +                // check if previous done
 | 
	
		
			
				|  |  | +                for check in 0..idx {
 | 
	
		
			
				|  |  | +                    if pos_found == values[check as usize] {
 | 
	
		
			
				|  |  | +                        println!("Previously done {}  prev index {} {:?}", idx, check, pos_found);
 | 
	
		
			
				|  |  | +                        continue 'outer;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            /*
 | 
	
		
			
				|  |  | +            if idx == size-2 {
 | 
	
		
			
				|  |  | +                break 'outer;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // Check to see:
 | 
	
		
			
				|  |  | +            // - How many items are in it.
 | 
	
		
			
				|  |  | +            // - Can we find that many matches.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /*
 | 
	
		
			
				|  |  | +            let count = pos_found.count_set();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if count == 1 {
 | 
	
		
			
				|  |  | +                // Or - should we process this single possible value here?
 | 
	
		
			
				|  |  | +                println!("Idx {}: has one item.", idx);
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            let mut matches = 1;
 | 
	
		
			
				|  |  | +            let mut pos = Vec::<u8>::new();
 | 
	
		
			
				|  |  | +            pos.push(idx);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            println!("Starting at {}, we're looking for {:?} [{} times]", idx, pos_found, count);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for look in idx+1..size {
 | 
	
		
			
				|  |  | +                if values[look as usize] == pos_found {
 | 
	
		
			
				|  |  | +                    matches += 1;
 | 
	
		
			
				|  |  | +                    pos.push(look);
 | 
	
		
			
				|  |  | +                    println!("Match found at {} ({} total)", look, matches);
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    println!("{:?} did not match {:?} at {}", pos_found, values[look as usize], look);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            println!("Final {} matches found, looking for {}", matches, count);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if matches == count {
 | 
	
		
			
				|  |  | +                // Pair (or something) found!
 | 
	
		
			
				|  |  | +                println!("Pairs: {:?} [value {}]", values, idx);
 | 
	
		
			
				|  |  | +                println!("FOUND: Index {} Count {} Value {:?} {:?}", index, count, pos_found, pos);
 | 
	
		
			
				|  |  | +                // Ok! In this position, remove any other possible!
 | 
	
		
			
				|  |  | +                // What position am I talking about here?
 | 
	
		
			
				|  |  | +                // let index_pos = self.possible.which_cell_index(index, )
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                println!("missed: Index {} Count {} Value {:?} {:?}", index, count, pos_found, pos);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // println!("Pairs: {:?}", self.find_pairs(index));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // Check columns
 | 
	
		
			
				|  |  |          for c in 0..size {
 | 
	
		
			
				|  |  |              // Calculate the row and column for the given cell.
 | 
	
		
			
				|  |  | -            let _col = (index % size)*size + c;
 | 
	
		
			
				|  |  | +            let _col = (index % size) * size + c;
 | 
	
		
			
				|  |  |              // println!("Index {} COL {}", index, col);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -731,22 +921,19 @@ impl AnySolver {
 | 
	
		
			
				|  |  |              let _row = (index / size) * size + r;
 | 
	
		
			
				|  |  |              // println!("Index {} ROW {}", index, row);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        println!("finalize_cell ends...");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /// Finalize move(s) on the board.
 | 
	
		
			
				|  |  |      /// - This checks the board for logic fixes. (when column is full/has 1+pair/triple)
 | 
	
		
			
				|  |  |      pub fn finalize_move(&mut self) {
 | 
	
		
			
				|  |  | -        for idx in 0..3 {
 | 
	
		
			
				|  |  | -            let mut _ix: u8 = idx * 3;
 | 
	
		
			
				|  |  | -            let mut _iy: u8 = idx * 3;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            println!("Index {} x {} y {}", idx, _ix, _iy);
 | 
	
		
			
				|  |  | -            // Check cell rows
 | 
	
		
			
				|  |  | -            
 | 
	
		
			
				|  |  | -            // Check cell columns
 | 
	
		
			
				|  |  | +        // Process the cells diagonally.
 | 
	
		
			
				|  |  | +        println!("TODO");
 | 
	
		
			
				|  |  | +        /* 
 | 
	
		
			
				|  |  | +        for idx in 0..self.board.size {
 | 
	
		
			
				|  |  | +            self.finalize_cell(idx + idx * self.board.size);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        assert!(false, "Boing!");
 | 
	
		
			
				|  |  | +        */
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /// Validate the board
 | 
	
	
		
			
				|  | @@ -779,13 +966,14 @@ impl AnySolver {
 | 
	
		
			
				|  |  |                          // self.board.display();
 | 
	
		
			
				|  |  |                          return false;
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | -                    self.process_move(x, y, value);
 | 
	
		
			
				|  |  | +                    self.process_move(x, y, value, false);
 | 
	
		
			
				|  |  |                  } else {
 | 
	
		
			
				|  |  |                      has_blanks = true;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          // Ok, the pieces given fit correctly with the sudoku constraints.
 | 
	
		
			
				|  |  | +        self.finalize_move();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if has_blanks {
 | 
	
		
			
				|  |  |              // Verify that the remaining value == 0 positions have possibles.
 | 
	
	
		
			
				|  | @@ -826,17 +1014,19 @@ impl AnySolver {
 | 
	
		
			
				|  |  |              for x in 0..self.board.width {
 | 
	
		
			
				|  |  |                  let value = self.board.get(x, y);
 | 
	
		
			
				|  |  |                  if value != 0 {
 | 
	
		
			
				|  |  | -                    self.process_move(x, y, value);
 | 
	
		
			
				|  |  | +                    self.process_move(x, y, value, false);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        self.finalize_move();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /// set (x,y) to value.
 | 
	
		
			
				|  |  |      /// - This updates the board.
 | 
	
		
			
				|  |  |      /// - This updates all the possibles (row,column,cell).
 | 
	
		
			
				|  |  |      /// - Clears the possible for (x,y) [See process_move].
 | 
	
		
			
				|  |  | -    pub fn set(&mut self, x: u8, y: u8, value: u8) {
 | 
	
		
			
				|  |  | +    /// TO FIX:  I think set also needs finalize ... to pass to process_move.
 | 
	
		
			
				|  |  | +    pub fn set(&mut self, x: u8, y: u8, value: u8, finalize: bool) {
 | 
	
		
			
				|  |  |          debug_assert!(
 | 
	
		
			
				|  |  |              x < self.board.width && y < self.board.width,
 | 
	
		
			
				|  |  |              "Expected ({}, {}) < {}",
 | 
	
	
		
			
				|  | @@ -853,7 +1043,7 @@ impl AnySolver {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          self.board.set(x, y, value);
 | 
	
		
			
				|  |  |          if value != 0 {
 | 
	
		
			
				|  |  | -            self.process_move(x, y, value);
 | 
	
		
			
				|  |  | +            self.process_move(x, y, value, finalize);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -905,7 +1095,7 @@ impl AnySolver {
 | 
	
		
			
				|  |  |                  for value in available.into_iter() {
 | 
	
		
			
				|  |  |                      assert!(value != 0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    self.set(x, y, value);
 | 
	
		
			
				|  |  | +                    self.set(x, y, value, true);
 | 
	
		
			
				|  |  |                      // self.board.display();
 | 
	
		
			
				|  |  |                      // self.possible.display();
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -958,7 +1148,7 @@ impl AnySolver {
 | 
	
		
			
				|  |  |              value = self.get(x, y);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        self.set(x, y, 0);
 | 
	
		
			
				|  |  | +        self.set(x, y, 0, true);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // clone, and solve by logic.
 | 
	
		
			
				|  |  |          let mut puzcopy = self.clone();
 | 
	
	
		
			
				|  | @@ -970,7 +1160,8 @@ impl AnySolver {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // Not solvable, restore and return false.
 | 
	
		
			
				|  |  | -        self.set(x, y, value);
 | 
	
		
			
				|  |  | +        // Since this failed, don't bother to finalize.
 | 
	
		
			
				|  |  | +        self.set(x, y, value, false);
 | 
	
		
			
				|  |  |          return false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -997,7 +1188,7 @@ impl AnySolver {
 | 
	
		
			
				|  |  |                      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);
 | 
	
		
			
				|  |  | +                    self.set(pos.0, pos.1, value, true);
 | 
	
		
			
				|  |  |                      found_something = true;
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
	
		
			
				|  | @@ -1067,7 +1258,7 @@ impl AnySolver {
 | 
	
		
			
				|  |  |                          let xy = this.board.xy(pos);
 | 
	
		
			
				|  |  |                          // this.possible.display();
 | 
	
		
			
				|  |  |                          // this.board.display();
 | 
	
		
			
				|  |  | -                        this.set(xy.0, xy.1, v + 1);
 | 
	
		
			
				|  |  | +                        this.set(xy.0, xy.1, v + 1, true);
 | 
	
		
			
				|  |  |                          // println!("SET {} ({},{}) = {}", pos, xy.0 + 1, xy.1 + 1, v+1);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                          found_something = true;
 | 
	
	
		
			
				|  | @@ -1531,13 +1722,13 @@ mod tests {
 | 
	
		
			
				|  |  |          println!("--- logic_test ---");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    #[ignore]    
 | 
	
		
			
				|  |  | +    #[ignore]
 | 
	
		
			
				|  |  |      #[test]
 | 
	
		
			
				|  |  |      fn logic_test_pairs() {
 | 
	
		
			
				|  |  |          let mut board = AnyBoard::new(3);
 | 
	
		
			
				|  |  |          board.set(1, 0, 2);
 | 
	
		
			
				|  |  |          board.set(2, 1, 3);
 | 
	
		
			
				|  |  | -        board.set(2,2, 5);
 | 
	
		
			
				|  |  | +        board.set(2, 2, 5);
 | 
	
		
			
				|  |  |          board.set(1, 6, 3);
 | 
	
		
			
				|  |  |          board.set(0, 4, 4);
 | 
	
		
			
				|  |  |          board.set(1, 7, 5);
 | 
	
	
		
			
				|  | @@ -1559,23 +1750,33 @@ mod tests {
 | 
	
		
			
				|  |  |             ╚═══╩═══╩═══╝
 | 
	
		
			
				|  |  |             P = Possible pair (3,5)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -           (1,1):1,6,7,8,9         (2,1):                  (3,1):1,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | -           (1,2):1,6,7,8,9         (2,2):1,3,4,5,6,7,8,9   (3,2):1,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | -           (1,3):1,6,7,8,9         (2,3):1,3,4,5,6,7,8,9   (3,3):1,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | -           (1,4):                  (2,4):1,6,7,8,9         (3,4):1,2,6,7,8,9
 | 
	
		
			
				|  |  | -           (1,5):                  (2,5):1,6,7,8,9         (3,5):1,2,6,7,8,9
 | 
	
		
			
				|  |  | -           (1,6):                  (2,6):1,6,7,8,9         (3,6):1,2,6,7,8,9
 | 
	
		
			
				|  |  | -           (1,7):1,2,6,7,8,9       (2,7):1,3,4,5,6,7,8,9   (3,7):1,2,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | -           (1,8):1,2,6,7,8,9       (2,8):1,3,4,5,6,7,8,9   (3,8):1,2,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | -           (1,9):1,2,6,7,8,9       (2,9):1,3,4,5,6,7,8,9   (3,9):1,2,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | -           ^ This shows the logic bug.
 | 
	
		
			
				|  |  | -           (3,7), (3,8) and (3,9) should not contain 2!
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +        (1,1):1,6,7,8,9         (2,1):                  (3,1):1,4,6,7,8,9       (4,1):1,3,4,5,6,7,8,9   (5,1):1,3,4,5,6,7,8,9   (6,1):1,3,4,5,6,7,8,9   (7,1):1,3,4,5,6,7,8,9   (8,1):1,3,4,5,6,7,8,9   (9,1):1,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | +        (1,2):1,6,7,8,9         (2,2):1,4,6,7,8,9       (3,2):                  (4,2):1,2,4,5,6,7,8,9   (5,2):1,2,4,5,6,7,8,9   (6,2):1,2,4,5,6,7,8,9   (7,2):1,2,4,5,6,7,8,9   (8,2):1,2,4,5,6,7,8,9   (9,2):1,2,4,5,6,7,8,9
 | 
	
		
			
				|  |  | +        (1,3):1,6,7,8,9         (2,3):1,4,6,7,8,9       (3,3):                  (4,3):1,2,3,4,6,7,8,9   (5,3):1,2,3,4,6,7,8,9   (6,3):1,2,3,4,6,7,8,9   (7,3):1,2,3,4,6,7,8,9   (8,3):1,2,3,4,6,7,8,9   (9,3):1,2,3,4,6,7,8,9
 | 
	
		
			
				|  |  | +        (1,4):1,2,3,5,6,7,8,9   (2,4):1,6,7,8,9         (3,4):1,2,6,7,8,9       (4,4):1,2,3,4,5,6,7,8,9 (5,4):1,2,3,4,5,6,7,8,9 (6,4):1,2,3,4,5,6,7,8,9 (7,4):1,2,3,4,5,6,7,8,9 (8,4):1,2,3,4,5,6,7,8,9 (9,4):1,2,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | +        (1,5):                  (2,5):1,6,7,8,9         (3,5):1,2,6,7,8,9       (4,5):1,2,3,5,6,7,8,9   (5,5):1,2,3,5,6,7,8,9   (6,5):1,2,3,5,6,7,8,9   (7,5):1,2,3,5,6,7,8,9   (8,5):1,2,3,5,6,7,8,9   (9,5):1,2,3,5,6,7,8,9
 | 
	
		
			
				|  |  | +        (1,6):1,2,3,5,6,7,8,9   (2,6):1,6,7,8,9         (3,6):1,2,6,7,8,9       (4,6):1,2,3,4,5,6,7,8,9 (5,6):1,2,3,4,5,6,7,8,9 (6,6):1,2,3,4,5,6,7,8,9 (7,6):1,2,3,4,5,6,7,8,9 (8,6):1,2,3,4,5,6,7,8,9 (9,6):1,2,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | +        (1,7):1,2,6,7,8,9       (2,7):                  (3,7):1,2,4,6,7,8,9     (4,7):1,2,4,5,6,7,8,9   (5,7):1,2,4,5,6,7,8,9   (6,7):1,2,4,5,6,7,8,9   (7,7):1,2,4,5,6,7,8,9   (8,7):1,2,4,5,6,7,8,9   (9,7):1,2,4,5,6,7,8,9
 | 
	
		
			
				|  |  | +        (1,8):1,2,6,7,8,9       (2,8):                  (3,8):1,2,4,6,7,8,9     (4,8):1,2,3,4,6,7,8,9   (5,8):1,2,3,4,6,7,8,9   (6,8):1,2,3,4,6,7,8,9   (7,8):1,2,3,4,6,7,8,9   (8,8):1,2,3,4,6,7,8,9   (9,8):1,2,3,4,6,7,8,9
 | 
	
		
			
				|  |  | +        (1,9):1,2,6,7,8,9       (2,9):1,4,6,7,8,9       (3,9):1,2,4,6,7,8,9     (4,9):1,2,3,4,5,6,7,8,9 (5,9):1,2,3,4,5,6,7,8,9 (6,9):1,2,3,4,5,6,7,8,9 (7,9):1,2,3,4,5,6,7,8,9 (8,9):1,2,3,4,5,6,7,8,9 (9,9):1,2,3,4,5,6,7,8,9
 | 
	
		
			
				|  |  | +        ^ This shows the logic bug.
 | 
	
		
			
				|  |  | +          (1,4) and (1,6) should only be 3,5.
 | 
	
		
			
				|  |  | +          (3,7), (3,8), and (3,9) should not contain 2.
 | 
	
		
			
				|  |  |          */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        assert!(solver.validate_board());
 | 
	
		
			
				|  |  | +        println!("RIGHT HERE:");
 | 
	
		
			
				|  |  | +        println!("Pairs [cell index 3]: {:?}", solver.find_pairs(3));
 | 
	
		
			
				|  |  | +        solver.finalize_cell(3);
 | 
	
		
			
				|  |  |          solver.possible.display();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        /*
 | 
	
		
			
				|  |  | +        Pairs: [{1, 4, 8, 6, 7, 0, 5, 2}, {6, 0, 8, 5, 2}, {0, 6}, {}, {0, 6}, {1, 4, 8, 6, 7, 0, 5, 2}, {1, 4, 8, 6, 7, 0, 5, 2}, {1, 4, 8, 6, 7, 0, 5, 2}, {1, 4, 8, 6, 7, 0, 5, 2}]
 | 
	
		
			
				|  |  | +        3 and 5 are {0,6} !
 | 
	
		
			
				|  |  | +         */
 | 
	
		
			
				|  |  | +        // Is validate_board destroying our work?!?
 | 
	
		
			
				|  |  | +        // YES IT IS!
 | 
	
		
			
				|  |  | +        assert!(solver.validate_board());
 | 
	
		
			
				|  |  | +        solver.possible.display();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      #[test]
 |