Kaynağa Gözat

Initial working bit_field version.

Steve Thielemann 9 ay önce
ebeveyn
işleme
5bfda4d711
4 değiştirilmiş dosya ile 466 ekleme ve 326 silme
  1. 1 0
      sudoku/Cargo.toml
  2. 285 289
      sudoku/src/group.rs
  3. 1 1
      sudoku/src/ksudoku.rs
  4. 179 36
      sudoku/src/sudoku.rs

+ 1 - 0
sudoku/Cargo.toml

@@ -9,6 +9,7 @@ edition = "2021"
 serde = "1.0.196"
 serde-xml-rs = "0.6.0"
 serde_derive = "1.0.196"
+bit_field = "0.10.2"
 
 [lib]
 name = "sudoku"

+ 285 - 289
sudoku/src/group.rs

@@ -12,7 +12,7 @@ const WIDTH: u8 = 9;
 /// Define a Group of sudoku positions.
 /// This defines rows, columns, and cells for analysis.
 #[derive(PartialEq)]
-pub struct Group( pub [u8; WIDTH as usize]);
+pub struct Group(pub [u8; WIDTH as usize]);
 
 /*
 pub struct Group {
@@ -20,315 +20,313 @@ pub struct Group {
 }
  */
 
-
 /// Group of positions for rows.
 const GROUP_ROW: [Group; 9] = [
-    Group([      
-            pos1(1, 1),
-            pos1(2, 1),
-            pos1(3, 1),
-            pos1(4, 1),
-            pos1(5, 1),
-            pos1(6, 1),
-            pos1(7, 1),
-            pos1(8, 1),
-            pos1(9, 1),
-]),
-    Group ([
-            pos1(1, 2),
-            pos1(2, 2),
-            pos1(3, 2),
-            pos1(4, 2),
-            pos1(5, 2),
-            pos1(6, 2),
-            pos1(7, 2),
-            pos1(8, 2),
-            pos1(9, 2),
-]),
-   
-    Group ([
-            pos1(1, 3),
-            pos1(2, 3),
-            pos1(3, 3),
-            pos1(4, 3),
-            pos1(5, 3),
-            pos1(6, 3),
-            pos1(7, 3),
-            pos1(8, 3),
-            pos1(9, 3),
-]),
-    Group ([
-            pos1(1, 4),
-            pos1(2, 4),
-            pos1(3, 4),
-            pos1(4, 4),
-            pos1(5, 4),
-            pos1(6, 4),
-            pos1(7, 4),
-            pos1(8, 4),
-            pos1(9, 4),
-]),
     Group([
-            pos1(1, 5),
-            pos1(2, 5),
-            pos1(3, 5),
-            pos1(4, 5),
-            pos1(5, 5),
-            pos1(6, 5),
-            pos1(7, 5),
-            pos1(8, 5),
-            pos1(9, 5),
-]),
+        pos1(1, 1),
+        pos1(2, 1),
+        pos1(3, 1),
+        pos1(4, 1),
+        pos1(5, 1),
+        pos1(6, 1),
+        pos1(7, 1),
+        pos1(8, 1),
+        pos1(9, 1),
+    ]),
+    Group([
+        pos1(1, 2),
+        pos1(2, 2),
+        pos1(3, 2),
+        pos1(4, 2),
+        pos1(5, 2),
+        pos1(6, 2),
+        pos1(7, 2),
+        pos1(8, 2),
+        pos1(9, 2),
+    ]),
+    Group([
+        pos1(1, 3),
+        pos1(2, 3),
+        pos1(3, 3),
+        pos1(4, 3),
+        pos1(5, 3),
+        pos1(6, 3),
+        pos1(7, 3),
+        pos1(8, 3),
+        pos1(9, 3),
+    ]),
     Group([
-            pos1(1, 6),
-            pos1(2, 6),
-            pos1(3, 6),
-            pos1(4, 6),
-            pos1(5, 6),
-            pos1(6, 6),
-            pos1(7, 6),
-            pos1(8, 6),
-            pos1(9, 6),
-]),
+        pos1(1, 4),
+        pos1(2, 4),
+        pos1(3, 4),
+        pos1(4, 4),
+        pos1(5, 4),
+        pos1(6, 4),
+        pos1(7, 4),
+        pos1(8, 4),
+        pos1(9, 4),
+    ]),
+    Group([
+        pos1(1, 5),
+        pos1(2, 5),
+        pos1(3, 5),
+        pos1(4, 5),
+        pos1(5, 5),
+        pos1(6, 5),
+        pos1(7, 5),
+        pos1(8, 5),
+        pos1(9, 5),
+    ]),
+    Group([
+        pos1(1, 6),
+        pos1(2, 6),
+        pos1(3, 6),
+        pos1(4, 6),
+        pos1(5, 6),
+        pos1(6, 6),
+        pos1(7, 6),
+        pos1(8, 6),
+        pos1(9, 6),
+    ]),
     Group([
-            pos1(1, 7),
-            pos1(2, 7),
-            pos1(3, 7),
-            pos1(4, 7),
-            pos1(5, 7),
-            pos1(6, 7),
-            pos1(7, 7),
-            pos1(8, 7),
-            pos1(9, 7),
-]),
-    Group ([
-            pos1(1, 8),
-            pos1(2, 8),
-            pos1(3, 8),
-            pos1(4, 8),
-            pos1(5, 8),
-            pos1(6, 8),
-            pos1(7, 8),
-            pos1(8, 8),
-            pos1(9, 8),
+        pos1(1, 7),
+        pos1(2, 7),
+        pos1(3, 7),
+        pos1(4, 7),
+        pos1(5, 7),
+        pos1(6, 7),
+        pos1(7, 7),
+        pos1(8, 7),
+        pos1(9, 7),
+    ]),
+    Group([
+        pos1(1, 8),
+        pos1(2, 8),
+        pos1(3, 8),
+        pos1(4, 8),
+        pos1(5, 8),
+        pos1(6, 8),
+        pos1(7, 8),
+        pos1(8, 8),
+        pos1(9, 8),
+    ]),
+    Group([
+        pos1(1, 9),
+        pos1(2, 9),
+        pos1(3, 9),
+        pos1(4, 9),
+        pos1(5, 9),
+        pos1(6, 9),
+        pos1(7, 9),
+        pos1(8, 9),
+        pos1(9, 9),
     ]),
-    Group ([
-            pos1(1, 9),
-            pos1(2, 9),
-            pos1(3, 9),
-            pos1(4, 9),
-            pos1(5, 9),
-            pos1(6, 9),
-            pos1(7, 9),
-            pos1(8, 9),
-            pos1(9, 9),
-    ])
 ];
 
 /// Group of positions for columns.
 const GROUP_COLUMN: [Group; 9] = [
     Group([
-            pos1(1, 1),
-            pos1(1, 2),
-            pos1(1, 3),
-            pos1(1, 4),
-            pos1(1, 5),
-            pos1(1, 6),
-            pos1(1, 7),
-            pos1(1, 8),
-            pos1(1, 9),
+        pos1(1, 1),
+        pos1(1, 2),
+        pos1(1, 3),
+        pos1(1, 4),
+        pos1(1, 5),
+        pos1(1, 6),
+        pos1(1, 7),
+        pos1(1, 8),
+        pos1(1, 9),
     ]),
-    Group ([
-            pos1(2, 1),
-            pos1(2, 2),
-            pos1(2, 3),
-            pos1(2, 4),
-            pos1(2, 5),
-            pos1(2, 6),
-            pos1(2, 7),
-            pos1(2, 8),
-            pos1(2, 9),
+    Group([
+        pos1(2, 1),
+        pos1(2, 2),
+        pos1(2, 3),
+        pos1(2, 4),
+        pos1(2, 5),
+        pos1(2, 6),
+        pos1(2, 7),
+        pos1(2, 8),
+        pos1(2, 9),
     ]),
-    Group ([
-            pos1(3, 1),
-            pos1(3, 2),
-            pos1(3, 3),
-            pos1(3, 4),
-            pos1(3, 5),
-            pos1(3, 6),
-            pos1(3, 7),
-            pos1(3, 8),
-            pos1(3, 9),
+    Group([
+        pos1(3, 1),
+        pos1(3, 2),
+        pos1(3, 3),
+        pos1(3, 4),
+        pos1(3, 5),
+        pos1(3, 6),
+        pos1(3, 7),
+        pos1(3, 8),
+        pos1(3, 9),
     ]),
-    Group ([
-            pos1(4, 1),
-            pos1(4, 2),
-            pos1(4, 3),
-            pos1(4, 4),
-            pos1(4, 5),
-            pos1(4, 6),
-            pos1(4, 7),
-            pos1(4, 8),
-            pos1(4, 9),
+    Group([
+        pos1(4, 1),
+        pos1(4, 2),
+        pos1(4, 3),
+        pos1(4, 4),
+        pos1(4, 5),
+        pos1(4, 6),
+        pos1(4, 7),
+        pos1(4, 8),
+        pos1(4, 9),
     ]),
-    Group ([
-            pos1(5, 1),
-            pos1(5, 2),
-            pos1(5, 3),
-            pos1(5, 4),
-            pos1(5, 5),
-            pos1(5, 6),
-            pos1(5, 7),
-            pos1(5, 8),
-            pos1(5, 9),
+    Group([
+        pos1(5, 1),
+        pos1(5, 2),
+        pos1(5, 3),
+        pos1(5, 4),
+        pos1(5, 5),
+        pos1(5, 6),
+        pos1(5, 7),
+        pos1(5, 8),
+        pos1(5, 9),
     ]),
-    Group ([
-            pos1(6, 1),
-            pos1(6, 2),
-            pos1(6, 3),
-            pos1(6, 4),
-            pos1(6, 5),
-            pos1(6, 6),
-            pos1(6, 7),
-            pos1(6, 8),
-            pos1(6, 9),
+    Group([
+        pos1(6, 1),
+        pos1(6, 2),
+        pos1(6, 3),
+        pos1(6, 4),
+        pos1(6, 5),
+        pos1(6, 6),
+        pos1(6, 7),
+        pos1(6, 8),
+        pos1(6, 9),
     ]),
-    Group ([
-            pos1(7, 1),
-            pos1(7, 2),
-            pos1(7, 3),
-            pos1(7, 4),
-            pos1(7, 5),
-            pos1(7, 6),
-            pos1(7, 7),
-            pos1(7, 8),
-            pos1(7, 9),
+    Group([
+        pos1(7, 1),
+        pos1(7, 2),
+        pos1(7, 3),
+        pos1(7, 4),
+        pos1(7, 5),
+        pos1(7, 6),
+        pos1(7, 7),
+        pos1(7, 8),
+        pos1(7, 9),
     ]),
-    Group ([
-            pos1(8, 1),
-            pos1(8, 2),
-            pos1(8, 3),
-            pos1(8, 4),
-            pos1(8, 5),
-            pos1(8, 6),
-            pos1(8, 7),
-            pos1(8, 8),
-            pos1(8, 9),
+    Group([
+        pos1(8, 1),
+        pos1(8, 2),
+        pos1(8, 3),
+        pos1(8, 4),
+        pos1(8, 5),
+        pos1(8, 6),
+        pos1(8, 7),
+        pos1(8, 8),
+        pos1(8, 9),
     ]),
-    Group ([
-            pos1(9, 1),
-            pos1(9, 2),
-            pos1(9, 3),
-            pos1(9, 4),
-            pos1(9, 5),
-            pos1(9, 6),
-            pos1(9, 7),
-            pos1(9, 8),
-            pos1(9, 9),
+    Group([
+        pos1(9, 1),
+        pos1(9, 2),
+        pos1(9, 3),
+        pos1(9, 4),
+        pos1(9, 5),
+        pos1(9, 6),
+        pos1(9, 7),
+        pos1(9, 8),
+        pos1(9, 9),
     ]),
 ];
 
 /// Group of positions for cells (3x3 grid).
 const GROUP_CELL: [Group; 9] = [
-    Group ([
-            pos1(1, 1),
-            pos1(2, 1),
-            pos1(3, 1),
-            pos1(1, 2),
-            pos1(2, 2),
-            pos1(3, 2),
-            pos1(1, 3),
-            pos1(2, 3),
-            pos1(3, 3),
-        ]),
-    Group ([
-            pos1(4, 1),
-            pos1(5, 1),
-            pos1(6, 1),
-            pos1(4, 2),
-            pos1(5, 2),
-            pos1(6, 2),
-            pos1(4, 3),
-            pos1(5, 3),
-            pos1(6, 3),
-        ]),
-    Group ([
-            pos1(7, 1),
-            pos1(8, 1),
-            pos1(9, 1),
-            pos1(7, 2),
-            pos1(8, 2),
-            pos1(9, 2),
-            pos1(7, 3),
-            pos1(8, 3),
-            pos1(9, 3),
-        ]),
-    Group ([
-            pos1(1, 4),
-            pos1(2, 4),
-            pos1(3, 4),
-            pos1(1, 5),
-            pos1(2, 5),
-            pos1(3, 5),
-            pos1(1, 6),
-            pos1(2, 6),
-            pos1(3, 6),
-        ]),
-    Group ([
-            pos1(4, 4),
-            pos1(5, 4),
-            pos1(6, 4),
-            pos1(4, 5),
-            pos1(5, 5),
-            pos1(6, 5),
-            pos1(4, 6),
-            pos1(5, 6),
-            pos1(6, 6),
-        ]),
-    Group ([
-            pos1(7, 4),
-            pos1(8, 4),
-            pos1(9, 4),
-            pos1(7, 5),
-            pos1(8, 5),
-            pos1(9, 5),
-            pos1(7, 6),
-            pos1(8, 6),
-            pos1(9, 6),
-        ]),
-    Group ([
-            pos1(1, 7),
-            pos1(2, 7),
-            pos1(3, 7),
-            pos1(1, 8),
-            pos1(2, 8),
-            pos1(3, 8),
-            pos1(1, 9),
-            pos1(2, 9),
-            pos1(3, 9),
-        ]),
-    Group ([
-            pos1(4, 7),
-            pos1(5, 7),
-            pos1(6, 7),
-            pos1(4, 8),
-            pos1(5, 8),
-            pos1(6, 8),
-            pos1(4, 9),
-            pos1(5, 9),
-            pos1(6, 9),
-        ]),
-    Group ([
-            pos1(7, 7),
-            pos1(8, 7),
-            pos1(9, 7),
-            pos1(7, 8),
-            pos1(8, 8),
-            pos1(9, 8),
-            pos1(7, 9),
-            pos1(8, 9),
-            pos1(9, 9),
-        ]),
+    Group([
+        pos1(1, 1),
+        pos1(2, 1),
+        pos1(3, 1),
+        pos1(1, 2),
+        pos1(2, 2),
+        pos1(3, 2),
+        pos1(1, 3),
+        pos1(2, 3),
+        pos1(3, 3),
+    ]),
+    Group([
+        pos1(4, 1),
+        pos1(5, 1),
+        pos1(6, 1),
+        pos1(4, 2),
+        pos1(5, 2),
+        pos1(6, 2),
+        pos1(4, 3),
+        pos1(5, 3),
+        pos1(6, 3),
+    ]),
+    Group([
+        pos1(7, 1),
+        pos1(8, 1),
+        pos1(9, 1),
+        pos1(7, 2),
+        pos1(8, 2),
+        pos1(9, 2),
+        pos1(7, 3),
+        pos1(8, 3),
+        pos1(9, 3),
+    ]),
+    Group([
+        pos1(1, 4),
+        pos1(2, 4),
+        pos1(3, 4),
+        pos1(1, 5),
+        pos1(2, 5),
+        pos1(3, 5),
+        pos1(1, 6),
+        pos1(2, 6),
+        pos1(3, 6),
+    ]),
+    Group([
+        pos1(4, 4),
+        pos1(5, 4),
+        pos1(6, 4),
+        pos1(4, 5),
+        pos1(5, 5),
+        pos1(6, 5),
+        pos1(4, 6),
+        pos1(5, 6),
+        pos1(6, 6),
+    ]),
+    Group([
+        pos1(7, 4),
+        pos1(8, 4),
+        pos1(9, 4),
+        pos1(7, 5),
+        pos1(8, 5),
+        pos1(9, 5),
+        pos1(7, 6),
+        pos1(8, 6),
+        pos1(9, 6),
+    ]),
+    Group([
+        pos1(1, 7),
+        pos1(2, 7),
+        pos1(3, 7),
+        pos1(1, 8),
+        pos1(2, 8),
+        pos1(3, 8),
+        pos1(1, 9),
+        pos1(2, 9),
+        pos1(3, 9),
+    ]),
+    Group([
+        pos1(4, 7),
+        pos1(5, 7),
+        pos1(6, 7),
+        pos1(4, 8),
+        pos1(5, 8),
+        pos1(6, 8),
+        pos1(4, 9),
+        pos1(5, 9),
+        pos1(6, 9),
+    ]),
+    Group([
+        pos1(7, 7),
+        pos1(8, 7),
+        pos1(9, 7),
+        pos1(7, 8),
+        pos1(8, 8),
+        pos1(9, 8),
+        pos1(7, 9),
+        pos1(8, 9),
+        pos1(9, 9),
+    ]),
 ];
 
 impl fmt::Debug for Group {
@@ -416,9 +414,7 @@ mod tests {
 
 impl Group {
     pub fn new() -> Self {
-        Group (
-             [0; WIDTH as usize],
-            )
+        Group([0; WIDTH as usize])
     }
 
     pub fn for_column(&mut self, x: u8, _y: u8) {

+ 1 - 1
sudoku/src/ksudoku.rs

@@ -1,7 +1,7 @@
 // Read a Ksudoku's XML save file.
 
 use serde_derive::{Deserialize, Serialize};
-use serde_xml_rs::{from_reader}; // , from_str, to_string};
+use serde_xml_rs::from_reader; // , from_str, to_string};
 
 use std::error::Error;
 use std::fs::File;

+ 179 - 36
sudoku/src/sudoku.rs

@@ -9,10 +9,126 @@ const WIDTH: u8 = 9;
 /// Size (width * height) of the board.
 const MAX_SIZE: u8 = 81;
 
+// Use bitfields instead of HashSets.
+use bit_field::BitField;
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub struct Possible(u16);
+
+pub const fn set_bits(bits: u8) -> u16 {
+    (1 << (bits )) - 1
+}
+
+impl Possible {
+    pub fn clear(&mut self) {
+        self.0 = 0;
+    }
+
+    pub fn set(&mut self, bit: u8, value: bool) {
+        // print!("{} set {}={}", self.0, bit, value);
+        self.0.set_bit((bit-1) as usize, value);
+        // println!("{}", self.0);
+    }
+
+    pub fn get(&self, bit: u8) -> bool {
+        self.0.get_bit((bit-1) as usize)
+    }
+
+    pub fn set_bits(&mut self, bits: u8) {
+        self.0 = set_bits(bits);
+    }
+
+    pub fn count_set(&self) -> u8 {
+        let mut count = 0;
+        for i in 1..u16::BIT_LENGTH {
+            if self.get(i as u8) {
+                count += 1;
+            }
+        }
+        count
+    }
+}
+
+struct PossibleIterator<'a> {
+    possible: &'a Possible,
+    index: u8,
+}
+
+impl Possible {
+    fn iter(&self) -> PossibleIterator {
+        PossibleIterator {
+            possible: self,
+            index: 1,
+        }
+    }
+}
+
+impl<'a> Iterator for PossibleIterator<'a> {
+    type Item = u8;
+
+    fn next(&mut self) -> Option<u8> {
+        while (self.index <= u16::BIT_LENGTH as u8) && (!self.possible.get(self.index)) {
+            self.index += 1;
+            // println!("index = {}", self.index);
+        }
+        if self.index >= u16::BIT_LENGTH as u8 {
+            None
+        } else {
+            self.index += 1;
+            Some(self.index - 1)
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::sudoku::*;
+
+    #[test]
+    fn check_possible_bitset() {
+        let mut p = Possible(0);
+
+        p.clear();
+
+        for i in 0..9 {
+            let mut result = p.get(i);
+            assert_eq!(result, false);
+            p.set(i, true);
+            result = p.get(i);
+            assert_eq!(result, true);
+        }
+    }
+
+    #[test]
+    fn check_possible_iter() {
+        let mut p = Possible(0);
+        p.set(3, true);
+        p.set(5, true);
+        p.set(6, true);
+        assert_eq!(3, p.count_set());
+        let values: Vec<u8> = p.iter().collect();
+        assert_eq!(values, vec!(3, 5, 6));
+        assert_eq!(3, p.count_set());
+        p.set(0, true);
+        assert_eq!(4, p.count_set());
+    }
+
+    #[test]
+    fn check_bits() {
+        let mut p = Possible(set_bits(5));
+        for i in 0..6 {
+            let result = p.get(i);
+            assert_eq!(result, true);
+        }
+        assert_eq!(p.get(6), false);
+    }
+}
+
 #[derive(Debug)]
 pub struct Sudoku {
     pub board: [u8; MAX_SIZE as usize],
-    pub possible: [HashSet<u8>; MAX_SIZE as usize],
+    // pub possible: [HashSet<u8>; MAX_SIZE as usize],
+    pub possible: [Possible; MAX_SIZE as usize],
 }
 
 /// Translate x,y to position in board.
@@ -42,10 +158,12 @@ let arr: [Vec<u32>; 10] = [(); 10].map(|_| Vec::with_capacity(100));
 impl Sudoku {
     pub fn new() -> Self {
         // let b : HashSet<u8> = HashSet::from_iter(1..=9);
+        let initial: Possible = Possible(set_bits(9));
 
         let s = Sudoku {
             board: [0; MAX_SIZE as usize],
-            possible: [(); MAX_SIZE as usize].map(|_| HashSet::from_iter(1..=9)),
+            // possible: [(); MAX_SIZE as usize].map(|_| HashSet::from_iter(1..=9)),
+            possible: [initial; MAX_SIZE as usize],
             // possible: [HashSet::from_iter(1..=9); MAX_SIZE as usize],
             // possible: [[0; SIZE as usize]; MAX_SIZE as usize],
             // possible: [(0..MAX_SIZE).map( |_| (1..=9).collect())],
@@ -55,9 +173,12 @@ impl Sudoku {
     }
 
     pub fn clear(&mut self) {
+        let initial = Possible(set_bits(9));
+
         for x in 0..MAX_SIZE {
             self.board[x as usize] = 0;
-            self.possible = [(); MAX_SIZE as usize].map(|_| HashSet::from_iter(1..=9));
+            self.possible[x as usize] = initial;
+            // self.possible = [(); MAX_SIZE as usize].map(|_| HashSet::from_iter(1..=9));
             /*
             self.possible[x as usize].clear();
             for i in 1..=9 {
@@ -143,19 +264,22 @@ impl Sudoku {
         // g.for_row(x, y);
         for g in g.0 {
             // remove value from these sets.
-            self.possible[g as usize].take(&value);
+            self.possible[g as usize].set(value, false);
+            // self.possible[g as usize].take(&value);
         }
         g = for_column(x);
         // g.for_column(x, y);
         for g in g.0 {
             // remove value from these sets.
-            self.possible[g as usize].take(&value);
+            self.possible[g as usize].set(value, false);
+            // self.possible[g as usize].take(&value);
         }
         g = for_cell(which_cell(x, y));
         // g.for_block(x, y);
         for g in g.0 {
             // remove value from these sets.
-            self.possible[g as usize].take(&value);
+            self.possible[g as usize].set(value, false);
+            // self.possible[g as usize].take(&value);
         }
         self.possible[pos(x, y) as usize].clear();
     }
@@ -167,19 +291,19 @@ impl Sudoku {
         g.for_row(x, y);
         for g in g.0 {
             // remove value from these sets.
-            self.possible[g as usize].take(&value);
+            self.possible[g as usize].set(value, false);
         }
 
         g.for_column(x, y);
         for g in g.0 {
             // remove value from these sets.
-            self.possible[g as usize].take(&value);
+            self.possible[g as usize].set(value, false);
         }
 
         g.for_block(x, y);
         for g in g.0 {
             // remove value from these sets.
-            self.possible[g as usize].take(&value);
+            self.possible[g as usize].set(value, false);
         }
         self.possible[pos(x, y) as usize].clear();
     }
@@ -213,10 +337,12 @@ impl Sudoku {
     pub fn display_possible(&self) {
         for y in 0..WIDTH {
             for x in 0..WIDTH {
+                // print!("p={:?}", self.possible[pos(x, y) as usize]);
                 let mut possible = String::new();
 
                 for p in self.possible[pos(x, y) as usize].iter() {
-                    possible += format!("{}", p).as_str();
+                    // print!("{},", p);
+                    possible += format!("{},", p).as_str();
                 }
 
                 // for i in 0..SIZE {
@@ -243,9 +369,9 @@ impl Sudoku {
         let mut found_something = false;
 
         for i in 0..MAX_SIZE {
-            if self.possible[i as usize].len() == 1 {
+            if self.possible[i as usize].count_set() == 1 {
                 // Get the value
-                let value = self.possible[i as usize].iter().next().cloned().unwrap();
+                let value = self.possible[i as usize].iter().next().unwrap();
                 // Found one!
                 println!("Set1 {:?} to {}", xy(i), value);
                 self.set(xy(i).0, xy(i).1, value);
@@ -254,14 +380,17 @@ impl Sudoku {
         }
 
         let mut g = Group::new();
-        let mut values: HashSet<u8> = HashSet::new();
+        let mut values = Possible(0); // HashSet<u8> = HashSet::new();
 
         let mut group_process = |this: &mut Self, grp: &Group| {
             // 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]);
-                values.extend(&this.possible[grp.0[gidx as usize] as usize]);
+                for v in this.possible[grp.0[gidx as usize] as usize].iter() {
+                    values.set(v, true);
+                }
+                // values.extend(this.possible[grp.0[gidx as usize] as usize]);
                 // println!("now     : {:?}", this.possible[grp.items[gidx as usize] as usize]);
             }
 
@@ -272,7 +401,8 @@ impl Sudoku {
                 let mut count = 0;
                 let mut pos = 0;
                 for gidx in 0..WIDTH {
-                    if this.possible[grp.0[gidx as usize] as usize].contains(&v) {
+                    if this.possible[grp.0[gidx as usize] as usize].get(v) {
+                        // if this.possible[grp.0[gidx as usize] as usize].contains(&v) {
                         count += 1;
                         pos = grp.0[gidx as usize];
                         if count > 1 {
@@ -284,7 +414,7 @@ impl Sudoku {
                     // don't need this, it was v!
                     // let value = this.possible[pos as usize].iter().next().cloned().unwrap();
                     println!("Set2 {:?} to {}", xy(pos), v);
-                    this.set(xy(pos).0, xy(pos).1, *v);
+                    this.set(xy(pos).0, xy(pos).1, v);
                     found_something = true;
                 }
             }
@@ -314,40 +444,45 @@ impl Sudoku {
 
             for gidx in 0..WIDTH - 1 {
                 let gpos = g.0[gidx as usize];
-                if self.possible[gpos as usize].len() == 2 {
+                if self.possible[gpos as usize].count_set() == 2 {
                     // Found a pair
                     for fidx in gidx + 1..WIDTH {
                         let fpos = g.0[fidx as usize];
-                        if self.possible[fpos as usize].len() == 2 {
+                        if self.possible[fpos as usize].count_set() == 2 {
                             // Ok, there's another pair
-                            if self.possible[gpos as usize].is_subset(&self.possible[fpos as usize])
-                            {
+                            // if self.possible[gpos as usize].is_subset(&self.possible[fpos as usize])
+                            if self.possible[gpos as usize] == self.possible[fpos as usize] {
                                 // Ok, they have the same values!
                                 // Ok, remove the items in the pair from the cell.
                                 // Don't touch the gpos/fpos records.  Keep those!
                                 let mut values: [u8; 2] = [0, 0];
                                 let mut vpos = 0;
                                 for z in self.possible[gpos as usize].iter() {
-                                    values[vpos] = *z;
+                                    values[vpos] = z;
                                     vpos += 1;
                                 }
 
                                 let mut pair_removed = false;
 
+                                // It isn't currently possible to tell if anything was removed...
+
                                 for remove in 0..WIDTH {
                                     if (gidx == remove) || (fidx == remove) {
                                         continue;
                                     }
                                     // Ok, these aren't the ones to save, so:
                                     let rpos = g.0[remove as usize];
-                                    if self.possible[rpos as usize].take(&values[0]).is_some() {
-                                        found_something = true;
-                                        pair_removed = true;
-                                    };
-                                    if self.possible[rpos as usize].take(&values[1]).is_some() {
+                                    self.possible[rpos as usize].set(values[0], false); /* ).is_some() {
+                                                                                            found_something = true;
+                                                                                            pair_removed = true;
+                                                                                        };
+                                                                                        */
+                                    self.possible[rpos as usize].set(values[1], false);
+                                    /*.is_some() {
                                         found_something = true;
                                         pair_removed = true;
                                     };
+                                    */
                                 }
 
                                 if pair_removed {
@@ -369,25 +504,29 @@ impl Sudoku {
 
                                     vpos = 0;
                                     for z in self.possible[gpos as usize].iter() {
-                                        values[vpos] = *z;
+                                        values[vpos] = z;
                                         vpos += 1;
                                     }
                                     for remove in 0..WIDTH {
                                         if (remove == xy(gpos).1) || (remove == xy(fpos).1) {
                                             continue;
                                         }
-                                        if self.possible[pos(column, remove) as usize]
-                                            .take(&values[0])
+                                        self.possible[pos(column, remove) as usize]
+                                            .set(values[0], false);
+                                        /* v
                                             .is_some()
                                         {
                                             found_something = true;
                                         };
-                                        if self.possible[pos(column, remove) as usize]
-                                            .take(&values[1])
+                                        */
+                                        self.possible[pos(column, remove) as usize]
+                                            .set(values[1], false);
+                                        /*
                                             .is_some()
                                         {
                                             found_something = true;
                                         };
+                                         */
                                     }
                                 }
                                 if xy(gpos).1 == xy(fpos).1 {
@@ -396,25 +535,29 @@ impl Sudoku {
 
                                     vpos = 0;
                                     for z in self.possible[gpos as usize].iter() {
-                                        values[vpos] = *z;
+                                        values[vpos] = z;
                                         vpos += 1;
                                     }
                                     for remove in 0..WIDTH {
                                         if (remove == xy(gpos).0) || (remove == xy(fpos).0) {
                                             continue;
                                         }
-                                        if self.possible[pos(remove, row) as usize]
-                                            .take(&values[0])
+                                        self.possible[pos(remove, row) as usize]
+                                            .set(values[0], false);
+                                        /*
                                             .is_some()
                                         {
                                             found_something = true;
                                         };
-                                        if self.possible[pos(remove, row) as usize]
-                                            .take(&values[1])
+                                         */
+                                        self.possible[pos(remove, row) as usize]
+                                            .set(values[1], false);
+                                        /*
                                             .is_some()
                                         {
                                             found_something = true;
                                         };
+                                         */
                                     }
                                 }
                             }