Browse Source

Working generic GenBits. Size can be specified.

Steve Thielemann 4 months ago
parent
commit
9d7a34fa48
3 changed files with 202 additions and 5 deletions
  1. 1 0
      sudoku/Cargo.toml
  2. 101 1
      sudoku/src/bits.rs
  3. 100 4
      sudoku/src/sudoku.rs

+ 1 - 0
sudoku/Cargo.toml

@@ -7,6 +7,7 @@ edition = "2021"
 
 
 [dependencies]
 [dependencies]
 bit_field = "0.10.2"
 bit_field = "0.10.2"
+num = "0.4.3"
 rand = "0.8.5"
 rand = "0.8.5"
 rand_chacha = "0.3.1"
 rand_chacha = "0.3.1"
 rand_core = { version = "0.6.4", features = ["getrandom"] }
 rand_core = { version = "0.6.4", features = ["getrandom"] }

+ 101 - 1
sudoku/src/bits.rs

@@ -3,6 +3,72 @@ use bit_field::BitField;
 
 
 // If I wanted to do 4x4 or 5x5, I would need more bits. (u32).
 // If I wanted to do 4x4 or 5x5, I would need more bits. (u32).
 
 
+use num::Integer;
+use std::ops::RangeBounds;
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub struct GenBits<T: Integer + BitField>(pub T);
+
+impl<T: Integer + BitField> GenBits<T> {
+    pub fn clear(&mut self) {
+        self.0 = T::zero();
+    }
+
+    pub fn set(&mut self, bit: usize, value: bool) {
+        self.0.set_bit(bit, value);
+    }
+
+    pub fn get(&self, bit: usize) -> bool {
+        self.0.get_bit(bit)
+    }
+
+    pub fn set_bits<R: RangeBounds<u8> + IntoIterator<Item = u8>>(&mut self, bits: R) {
+        for i in bits {
+            self.set(i as usize, true);
+        }
+    }
+
+    pub fn count_set(&self) -> u8 {
+        let mut count: u8 = 0;
+        for i in 0..T::BIT_LENGTH {
+            if self.get(i) {
+                count += 1;
+            }
+        }
+        count
+    }
+}
+
+pub struct GenBitsIterator<'a, T: Integer + BitField> {
+    pub possible: &'a GenBits<T>,
+    pub index: usize,
+}
+
+impl<T: Integer + BitField> GenBits<T> {
+    pub fn iter(&self) -> GenBitsIterator<T> {
+        GenBitsIterator {
+            possible: self,
+            index: 1,
+        }
+    }
+}
+
+impl<'a, T: Integer + BitField> Iterator for GenBitsIterator<'a, T> {
+    type Item = u8;
+
+    fn next(&mut self) -> Option<u8> {
+        while (self.index < T::BIT_LENGTH) && (!self.possible.get(self.index as usize)) {
+            self.index += 1;
+        }
+        if self.index == T::BIT_LENGTH {
+            None
+        } else {
+            self.index += 1;
+            Some((self.index - 1) as u8)
+        }
+    }
+}
+
 #[derive(Debug, Copy, Clone, PartialEq)]
 #[derive(Debug, Copy, Clone, PartialEq)]
 pub struct Bits(pub u16);
 pub struct Bits(pub u16);
 
 
@@ -120,5 +186,39 @@ mod tests {
         }
         }
         assert_eq!(p.get(6), false);
         assert_eq!(p.get(6), false);
     }
     }
-}
 
 
+    #[test]
+    fn check_u16() {
+        let mut p = GenBits::<u16>(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);
+        }
+
+        p = GenBits::<u16>(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());
+
+        p = GenBits::<u16>(0);
+        p.set_bits(0..6);
+
+        for i in 0..6 {
+            let result = p.get(i);
+            assert_eq!(result, true);
+        }
+        assert_eq!(p.get(6), false);
+    }
+}

+ 100 - 4
sudoku/src/sudoku.rs

@@ -28,8 +28,9 @@ pub type SudokuPossible = [Bits; MAX_SIZE as usize];
 
 
 #[derive(Debug, Clone, Copy)]
 #[derive(Debug, Clone, Copy)]
 pub struct Board([u8; MAX_SIZE as usize]);
 pub struct Board([u8; MAX_SIZE as usize]);
-#[derive(Debug, Clone, Copy)]
-pub struct BoardPossible([Bits; MAX_SIZE as usize]);
+
+
+
 
 
 impl Board {
 impl Board {
     pub fn new() -> Self {
     pub fn new() -> Self {
@@ -95,6 +96,27 @@ impl Board {
     }
     }
 
 
 }
 }
+
+// Vec doesn't implement Copy ...
+#[derive(Debug, Clone)]
+pub struct AnyBoard {
+    pub size : u8,
+    pub board : Vec<u8>,
+}
+
+impl AnyBoard {
+    pub fn new(board_size: u8) -> Self {
+        if (board_size < 3) || (board_size > 5) {
+            panic!("Board size must be 3-5.");
+        }
+
+        let s = AnyBoard{
+            size: board_size,
+            board: vec![0, board_size*board_size*2],
+        };
+        s
+    }
+}
 /*
 /*
 I probably should keep board and possible separate from one another.
 I probably should keep board and possible separate from one another.
 Possible is only used when solving the puzzles, and only used by the
 Possible is only used when solving the puzzles, and only used by the
@@ -102,6 +124,15 @@ logic solver.  Not needed by brute-force.
 
 
 Ok, the problem is that the possible doesn't make any sense to be
 Ok, the problem is that the possible doesn't make any sense to be
 unlinked in any way from the board.  I think they have to be together.
 unlinked in any way from the board.  I think they have to be together.
+
+Right now, I have &mut of board, it might be better to just copy it.
+Then, I could derive Clone and Copy again for BoardPossible...
+
+(And simplify things immensely, getting rid of lifetimes...)
+
+Still thinking of having Possible as a structure, so I could implement
+funcs on just that, rather then having them in BoardPossible (wrong
+place for Possible's implementation).
  */
  */
 
 
  /*
  /*
@@ -109,9 +140,74 @@ unlinked in any way from the board.  I think they have to be together.
 pub struct SudokuPossible {
 pub struct SudokuPossible {
     pub possible: [Possible; MAX_SIZE as usize];
     pub possible: [Possible; MAX_SIZE as usize];
 }
 }
+
+        // 10 = WIDTH + 1
+        // This would need to be changed in order to handle 4x4 or 5x5.
+        // NOTE: We ignore bit 0, we use bits 1-9 (for 3x3).
+        let mut initial: Bits = Bits(set_bits(10));
+        initial.set(0, false);
+
+        let s = Sudoku {
+            board: [0; MAX_SIZE as usize],
+            possible: [initial; MAX_SIZE as usize],
+
 */
 */
 
 
-impl BoardPossible {
+#[derive(Debug)]
+pub struct BoardPossible<'a> {
+    board: &'a mut Board, 
+    possible: [Bits; MAX_SIZE as usize],
+}
+
+impl <'a>BoardPossible<'a> {
+    pub fn new(board : &'a mut Board) -> Self {
+        // 10 = WIDTH + 1
+        // This would need to be changed in order to handle 4x4 or 5x5.
+        // NOTE: We ignore bit 0, we use bits 1-9 (for 3x3).
+        let mut initial: Bits = Bits(set_bits(10));
+        initial.set(0, false);
+
+        let mut s = Self {
+            board: board,
+            possible: [initial; MAX_SIZE as usize],
+        };
+        s.reset_possible();
+        s
+    }
+
+    pub fn clear_possible(&mut self) {
+        let mut initial: Bits = Bits(set_bits(10));
+        initial.set(0, false);
+        self.possible = [initial; MAX_SIZE as usize];
+    }
+
+    /// set (x,y) with value.
+    /// - This updates the board.
+    /// - this updates all the possible (row,column,cell).
+    /// - Clears the possible for the (x,y).
+    pub fn set(&mut self, x:u8, y:u8, value:u8) {
+        self.board.0[pos(x,y)] = value;
+
+        // update the possible
+        let mut g: &Group = for_row(y);
+        for g in g.0 {
+            self.possible[g].set(value, false);
+        }
+        g = for_column(x);
+        for g in g.0 {
+            self.possible[g].set(value, false);
+        }
+        g = for_cell(which_cell(x,y));
+        for g in g.0 {
+            self.possible[g].set(value, false);
+        }
+        self.possible[pos(x,y)].clear();
+    }
+
+    pub fn reset_possible(&mut self) {
+
+    }
+
     /// Display the possibles.
     /// Display the possibles.
     /// This should be in the Possible struct, not here.
     /// This should be in the Possible struct, not here.
     pub fn display(&self) {
     pub fn display(&self) {
@@ -120,7 +216,7 @@ impl BoardPossible {
                 // print!("p={:?}", self.possible[pos(x, y) as usize]);
                 // print!("p={:?}", self.possible[pos(x, y) as usize]);
                 let mut possible = String::new();
                 let mut possible = String::new();
 
 
-                for p in self.0[pos(x, y) as usize].iter() {
+                for p in self.possible[pos(x, y) as usize].iter() {
                     // print!("{},", p);
                     // print!("{},", p);
                     possible += format!("{},", p).as_str();
                     possible += format!("{},", p).as_str();
                 }
                 }