Selaa lähdekoodia

Working generic GenBits. Size can be specified.

Steve Thielemann 4 kuukautta sitten
vanhempi
commit
9d7a34fa48
3 muutettua tiedostoa jossa 202 lisäystä ja 5 poistoa
  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]
 bit_field = "0.10.2"
+num = "0.4.3"
 rand = "0.8.5"
 rand_chacha = "0.3.1"
 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).
 
+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)]
 pub struct Bits(pub u16);
 
@@ -120,5 +186,39 @@ mod tests {
         }
         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)]
 pub struct Board([u8; MAX_SIZE as usize]);
-#[derive(Debug, Clone, Copy)]
-pub struct BoardPossible([Bits; MAX_SIZE as usize]);
+
+
+
 
 impl Board {
     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.
 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
 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 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.
     /// This should be in the Possible struct, not here.
     pub fn display(&self) {
@@ -120,7 +216,7 @@ impl BoardPossible {
                 // print!("p={:?}", self.possible[pos(x, y) as usize]);
                 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);
                     possible += format!("{},", p).as_str();
                 }