|
@@ -461,32 +461,29 @@ pub struct AnyPossible {
|
|
|
pub size: u8,
|
|
|
pub width: u8,
|
|
|
pub max_index: usize,
|
|
|
- pub possible: Vec<GenBits<u32>>,
|
|
|
+ pub possible: Vec<GenBits>,
|
|
|
}
|
|
|
|
|
|
impl AnyPossible {
|
|
|
pub fn new(board_size: u8) -> Self {
|
|
|
- let mut initial = GenBits::<u32>(0);
|
|
|
- let width = board_size * board_size;
|
|
|
- initial.set_bits(0..width);
|
|
|
+ let width = board_size as usize * board_size as usize;
|
|
|
+ let mut initial = GenBits::new(width);
|
|
|
+ // let width = board_size * board_size;
|
|
|
+ initial.set_bits(0..width as usize);
|
|
|
|
|
|
Self {
|
|
|
size: board_size,
|
|
|
- width: width,
|
|
|
- max_index: width as usize * width as usize,
|
|
|
- possible: vec![initial; width as usize * width as usize],
|
|
|
+ width: width as u8,
|
|
|
+ max_index: width * width,
|
|
|
+ possible: vec![initial; width * width],
|
|
|
}
|
|
|
}
|
|
|
|
|
|
pub fn clear(&mut self) {
|
|
|
- let mut initial = GenBits::<u32>(0);
|
|
|
+ let mut initial = GenBits::new(self.width as usize);
|
|
|
// let width = self.size * self.size;
|
|
|
- initial.set_bits(0..self.width);
|
|
|
-
|
|
|
+ initial.set_bits(0..self.width as usize);
|
|
|
self.possible.fill(initial);
|
|
|
-
|
|
|
- // self.possible = vec![initial; self.max_index];
|
|
|
- // width as usize * width as usize];
|
|
|
}
|
|
|
|
|
|
pub fn copy(&mut self, copy_from: &Self) {
|
|
@@ -497,7 +494,7 @@ impl AnyPossible {
|
|
|
self.size
|
|
|
);
|
|
|
for i in 0..self.max_index {
|
|
|
- self.possible[i] = copy_from.possible[i];
|
|
|
+ self.possible[i] = copy_from.possible[i].clone();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -514,7 +511,7 @@ impl AnyPossible {
|
|
|
index,
|
|
|
self.max_index
|
|
|
);
|
|
|
- let changed = self.possible[index].get(value-1) != state;
|
|
|
+ let changed = self.possible[index].get(value - 1) != state;
|
|
|
self.possible[index].set(value - 1, state);
|
|
|
changed
|
|
|
}
|
|
@@ -578,12 +575,12 @@ impl AnyPossible {
|
|
|
}
|
|
|
|
|
|
#[must_use]
|
|
|
- pub fn find_pairs(&mut self, cellgroup: &[usize]) -> (Vec<(Vec<u8>, Vec<u8>)>, bool) {
|
|
|
+ pub fn find_pairs(&mut self, cellgroup: &[usize]) -> (Vec<(Vec<usize>, Vec<u8>)>, bool) {
|
|
|
// result[value] = indexes where it is located?
|
|
|
// Step 1: find values, and their position(s).
|
|
|
|
|
|
- let initial = GenBits::<u32>(0);
|
|
|
- let mut result: Vec<GenBits<u32>> = vec![initial; self.width as usize];
|
|
|
+ let initial = GenBits::new(self.width as usize);
|
|
|
+ let mut result: Vec<GenBits> = vec![initial; self.width as usize];
|
|
|
|
|
|
// let cellgroup = self.group.group(Groups::Cell, cell_index);
|
|
|
|
|
@@ -602,21 +599,21 @@ impl AnyPossible {
|
|
|
|
|
|
// Step 2: pair them up, and if complete, fixup possible (if needed).
|
|
|
|
|
|
- let zero_bits = GenBits::<u32>(0);
|
|
|
+ let zero_bits = GenBits::new(self.width as usize);
|
|
|
let width = self.width;
|
|
|
let mut possibles_updated: bool = false;
|
|
|
- let mut pairs: Vec<(Vec<u8>, Vec<u8>)> = vec![];
|
|
|
+ let mut pairs: Vec<(Vec<usize>, Vec<u8>)> = vec![];
|
|
|
|
|
|
'outer: for idx in 0..width - 1 {
|
|
|
// pos_found contains the positions.
|
|
|
- let pos_found = result[idx as usize];
|
|
|
- if pos_found == zero_bits {
|
|
|
+ let pos_found = &result[idx as usize];
|
|
|
+ if pos_found.count_set() == 0 {
|
|
|
continue;
|
|
|
}
|
|
|
if idx > 0 {
|
|
|
// Check previous for matches - already checked...
|
|
|
for check in 0..idx {
|
|
|
- if pos_found == result[check as usize] {
|
|
|
+ if *pos_found == result[check as usize] {
|
|
|
continue 'outer;
|
|
|
}
|
|
|
}
|
|
@@ -637,7 +634,7 @@ impl AnyPossible {
|
|
|
|
|
|
if count != 1 {
|
|
|
for look in idx + 1..width {
|
|
|
- if result[look as usize] == pos_found {
|
|
|
+ if result[look as usize] == *pos_found {
|
|
|
matches += 1;
|
|
|
pos.push(look);
|
|
|
}
|
|
@@ -647,13 +644,13 @@ impl AnyPossible {
|
|
|
if matches == count {
|
|
|
// Ok! We found a pair (or triple, or quad, or ...)
|
|
|
// Build new possible
|
|
|
- let mut new_possible = zero_bits;
|
|
|
+ let mut new_possible = zero_bits.clone();
|
|
|
for p in &pos {
|
|
|
new_possible.set(*p as usize, true);
|
|
|
}
|
|
|
- let mut index_pos: Vec<u8> = Vec::<u8>::new();
|
|
|
+ let mut index_pos = Vec::<usize>::new();
|
|
|
|
|
|
- for p in pos_found.iter() {
|
|
|
+ for p in pos_found.indexes() {
|
|
|
index_pos.push(p);
|
|
|
if self.possible[cellgroup[p as usize]] != new_possible {
|
|
|
// println!("Update pos {} with {:?}", p, new_possible);
|
|
@@ -665,7 +662,7 @@ impl AnyPossible {
|
|
|
);
|
|
|
*/
|
|
|
possibles_updated = true;
|
|
|
- self.possible[cellgroup[p as usize]] = new_possible;
|
|
|
+ self.possible[cellgroup[p as usize]] = new_possible.clone();
|
|
|
// println!("Updated!");
|
|
|
}
|
|
|
}
|
|
@@ -678,18 +675,20 @@ impl AnyPossible {
|
|
|
|
|
|
#[must_use]
|
|
|
/// Find positions where each value is possible.
|
|
|
- pub fn find_value_pos(&self) -> Vec<GenBits<u32>> {
|
|
|
- let zero = GenBits::<u32>(0);
|
|
|
- let mut result = vec![zero; self.size as usize];
|
|
|
-
|
|
|
- for index in 0..self.size {
|
|
|
+ /// - Vec index is value
|
|
|
+ /// - GenBits are the positions it is found.
|
|
|
+ pub fn find_value_pos(&self) -> Vec<GenBits> {
|
|
|
+ let zero = GenBits::new(self.width as usize);
|
|
|
+ let mut result = vec![zero.clone(); self.width as usize];
|
|
|
+
|
|
|
+ for index in 0..self.width {
|
|
|
if self.possible[index as usize] == zero {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// Ok, there's some value there.
|
|
|
- // Would it be better to use the iterator here?
|
|
|
- for v in self.possible[index as usize].iter() {
|
|
|
+ // Would it be better to use the iterator here? Yes, I think so.
|
|
|
+ for v in self.possible[index as usize].indexes() {
|
|
|
result[v as usize].set(index as usize, true);
|
|
|
}
|
|
|
|
|
@@ -746,15 +745,16 @@ pub struct AnySolver {
|
|
|
pub possible: AnyPossible,
|
|
|
pub group: AnyGroup,
|
|
|
// Is this value set in the given cell?
|
|
|
- pub cell_poss: Vec<GenBits<u32>>,
|
|
|
+ pub cell_poss: Vec<GenBits>,
|
|
|
}
|
|
|
|
|
|
impl AnySolver {
|
|
|
/// Construct new solver from given board size. (3,4,5)
|
|
|
pub fn new(board_size: u8) -> Self {
|
|
|
- let mut default_poss = GenBits::<u32>(0);
|
|
|
let width: u8 = board_size * board_size;
|
|
|
- default_poss.set_bits(0..width);
|
|
|
+ let mut default_poss = GenBits::new(width as usize);
|
|
|
+
|
|
|
+ default_poss.set_bits(0..width as usize);
|
|
|
|
|
|
let mut s = Self {
|
|
|
board: AnyBoard::new(board_size),
|
|
@@ -768,8 +768,8 @@ impl AnySolver {
|
|
|
|
|
|
/// Construct new solver from given board.
|
|
|
pub fn new_from(initial_board: &AnyBoard) -> Self {
|
|
|
- let mut default_poss = GenBits::<u32>(0);
|
|
|
- default_poss.set_bits(0..initial_board.width);
|
|
|
+ let mut default_poss = GenBits::new(initial_board.width as usize);
|
|
|
+ default_poss.set_bits(0..initial_board.width as usize);
|
|
|
|
|
|
let mut s = AnySolver {
|
|
|
board: initial_board.clone(),
|
|
@@ -828,7 +828,7 @@ impl AnySolver {
|
|
|
self.possible.set(*g, val, false);
|
|
|
}
|
|
|
let idx = self.possible.pos(x, y);
|
|
|
- self.possible.possible[idx] = GenBits::<u32>(0);
|
|
|
+ self.possible.possible[idx] = GenBits::new(self.board.width as usize);
|
|
|
self.board.board[idx] = value;
|
|
|
|
|
|
//
|
|
@@ -884,14 +884,12 @@ impl AnySolver {
|
|
|
}
|
|
|
|
|
|
// What values are possible in which rows/columns and cells?
|
|
|
-
|
|
|
+
|
|
|
// Scan rows/columns
|
|
|
for cell in 0..width {
|
|
|
let cell_info = self.group.group(Groups::Cell, cell);
|
|
|
|
|
|
- for row in 0..size {
|
|
|
-
|
|
|
- }
|
|
|
+ for row in 0..size {}
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -899,14 +897,54 @@ impl AnySolver {
|
|
|
/// Finalize move on the board.
|
|
|
/// - This uses the cell index last modified, so we have fewer
|
|
|
/// cells to check here. (2 * size) cells.
|
|
|
- #[deprecated]
|
|
|
pub fn finalize_cell(&mut self, cell_index: u8) {
|
|
|
let width = self.board.width;
|
|
|
let size = self.board.size;
|
|
|
- let mut update: bool = false;
|
|
|
+ // let mut update: bool = false;
|
|
|
+
|
|
|
+ // use width, not size. ;)
|
|
|
+ let mut cell_has_value = vec![false; width as usize];
|
|
|
+
|
|
|
+ let mut cell_update = vec![false; width as usize];
|
|
|
+ cell_update[cell_index as usize] = true;
|
|
|
+
|
|
|
+ let values = self.possible.find_value_pos();
|
|
|
+
|
|
|
+ for (value, positions) in values.iter().enumerate() {
|
|
|
+ if positions.count_set() == 0 {
|
|
|
+ // No positions, skip it.
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // reset
|
|
|
+ cell_has_value.fill(false);
|
|
|
|
|
|
+ for p in positions.iter() {
|
|
|
+ cell_has_value[p as usize] = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ println!("Value {} : Pos {:?}", value, cell_has_value);
|
|
|
+
|
|
|
+ // cell_has_value gives me the indexes that contain value.
|
|
|
+ // I need to process cell rows/columns...
|
|
|
+ // Start with processing one (cell row), and refactor. (like always)
|
|
|
+
|
|
|
+ // cells on left (because cells have the constraints).
|
|
|
+ for cell in (0..size).map(|x| x * size) {
|
|
|
+ // let c = self.group.cell(cell);
|
|
|
+ let mut c = Vec::<&[usize]>::new();
|
|
|
+ for row in 0..size {
|
|
|
+ c.push(self.group.cell(cell + row));
|
|
|
+ }
|
|
|
+
|
|
|
+ // rows go the entire width of the game...
|
|
|
+ for row in 0..width {}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /*
|
|
|
let _pairs = self.possible
|
|
|
.find_pairs(self.group.group(Groups::Cell, cell_index));
|
|
|
+ */
|
|
|
|
|
|
// println!("Finalize Cell Pairs: {:?}", self.possible.find_pairs(self.group.group(Groups::Cell, index)));
|
|
|
|
|
@@ -954,13 +992,13 @@ impl AnySolver {
|
|
|
I probably need some helpers to give me a row/column of a given position... as well.
|
|
|
row/column iterators ?
|
|
|
|
|
|
- 1.)
|
|
|
- In a given cell's column/row, if a number is possible in that cell's column/row, remove it from the other cell's row/column.
|
|
|
+ 1.)
|
|
|
+ In a given cell's column/row, if a number is possible in that cell's column/row, remove it from the other cell's row/column.
|
|
|
(Must be there, so remove it.)
|
|
|
(3,7), (3,8), (3,9) remove 2.
|
|
|
|
|
|
2.)
|
|
|
- In a given cell's column/row, if a number isn't possible in the same column/row in the other cells
|
|
|
+ In a given cell's column/row, if a number isn't possible in the same column/row in the other cells
|
|
|
-- remove that number as possible from that cell's other row/columns.
|
|
|
|
|
|
When updating the possibles - track which cells changed (so we can check/recheck just those).
|
|
@@ -969,7 +1007,7 @@ impl AnySolver {
|
|
|
When allocating the blocks, possibly use the max value (size) -- this should keep the allocated blocks
|
|
|
the same (hopefully keep reusing the same size block of memory over and over)
|
|
|
-- or allocate it once and just reuse/init the same block over and over ? (reduce allocation/deallocations)
|
|
|
-
|
|
|
+
|
|
|
Also the reverse should be possible:
|
|
|
╔═══╦═══╦═══╗
|
|
|
║T ║ ║ ║
|
|
@@ -1002,12 +1040,17 @@ impl AnySolver {
|
|
|
|
|
|
// Ranges are consumed.
|
|
|
|
|
|
+ // This looks like it does what I'm doing somewhere else!
|
|
|
+ // TODO:
|
|
|
+ // TOFIX:
|
|
|
+ // See: AnyPossible's find_value_pos!
|
|
|
+
|
|
|
// Check columns - (of given cell) for logical removes (see logic_test for example)
|
|
|
for value in 0..width {
|
|
|
// Find what columns value is allowed. (in which cells).
|
|
|
// Is this value needed in any of the cells?
|
|
|
- let mut found = GenBits::<u32>(0);
|
|
|
- let mut all_cells = found;
|
|
|
+ let mut found = GenBits::new(width as usize);
|
|
|
+ let mut all_cells = found.clone();
|
|
|
|
|
|
for ci in (top_cell..width).step_by(size as usize) {
|
|
|
all_cells.set(ci as usize, true);
|
|
@@ -1016,12 +1059,12 @@ impl AnySolver {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if found == GenBits::<u32>(0) {
|
|
|
+ if found.count_set() == 0 {
|
|
|
// Not possible anywhere, so skip to next value.
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- println!("Value {} {:?} is needed {:?}", value + 1, all_cells, found);
|
|
|
+ // println!("Value {} {:?} is needed {:?}", value + 1, all_cells, found);
|
|
|
|
|
|
for x in x_range.clone() {
|
|
|
for y in 0..width {
|
|
@@ -1072,11 +1115,11 @@ impl AnySolver {
|
|
|
|
|
|
self.possible.clear();
|
|
|
// reset cell possible
|
|
|
- let mut default_poss = GenBits::<u32>(0);
|
|
|
- default_poss.set_bits(0..self.board.width);
|
|
|
+ let mut default_poss = GenBits::new(self.board.width as usize);
|
|
|
+ default_poss.set_bits(0..self.board.width as usize);
|
|
|
|
|
|
for x in 0..self.board.width {
|
|
|
- self.cell_poss[x as usize] = default_poss;
|
|
|
+ self.cell_poss[x as usize] = default_poss.clone();
|
|
|
}
|
|
|
|
|
|
for y in 0..self.board.width {
|
|
@@ -1130,11 +1173,11 @@ impl AnySolver {
|
|
|
self.possible.clear();
|
|
|
|
|
|
// reset cell possible
|
|
|
- let mut default_poss = GenBits::<u32>(0);
|
|
|
- default_poss.set_bits(0..self.board.width);
|
|
|
+ let mut default_poss = GenBits::new(self.board.width as usize);
|
|
|
+ default_poss.set_bits(0..self.board.width as usize);
|
|
|
|
|
|
for x in 0..self.board.width {
|
|
|
- self.cell_poss[x as usize] = default_poss;
|
|
|
+ self.cell_poss[x as usize] = default_poss.clone();
|
|
|
}
|
|
|
|
|
|
for y in 0..self.board.width {
|
|
@@ -1208,7 +1251,7 @@ impl AnySolver {
|
|
|
available.reserve(width as usize);
|
|
|
|
|
|
for t in self.possible.possible[idx].iter() {
|
|
|
- available.push(t + 1);
|
|
|
+ available.push((t + 1) as u8);
|
|
|
}
|
|
|
if available.len() == 0 {
|
|
|
return false;
|
|
@@ -1235,7 +1278,7 @@ impl AnySolver {
|
|
|
self.possible.copy(&backup.possible);
|
|
|
|
|
|
for i in 0..backup.cell_poss.len() {
|
|
|
- self.cell_poss[i] = backup.cell_poss[i];
|
|
|
+ self.cell_poss[i] = backup.cell_poss[i].clone();
|
|
|
}
|
|
|
// self.cell_poss.copy( backup.cell_poss);
|
|
|
}
|
|
@@ -1316,7 +1359,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, true);
|
|
|
+ self.set(pos.0, pos.1, value as u8, true);
|
|
|
found_something = true;
|
|
|
}
|
|
|
}
|
|
@@ -1345,7 +1388,7 @@ impl AnySolver {
|
|
|
pass2_again = false;
|
|
|
|
|
|
// let mut values = Bits(0); // HashSet<u8> = HashSet::new();
|
|
|
- let mut values = GenBits::<u32>(0);
|
|
|
+ let mut values = GenBits::new(self.board.width as usize);
|
|
|
|
|
|
let mut group_process = |this: &mut Self, grp: &[usize]| {
|
|
|
// Collect all the possible values within the group.
|
|
@@ -1386,7 +1429,7 @@ impl AnySolver {
|
|
|
let xy = this.board.xy(pos);
|
|
|
// this.possible.display();
|
|
|
// this.board.display();
|
|
|
- this.set(xy.0, xy.1, v + 1, true);
|
|
|
+ this.set(xy.0, xy.1, (v + 1) as u8, true);
|
|
|
// println!("SET {} ({},{}) = {}", pos, xy.0 + 1, xy.1 + 1, v+1);
|
|
|
|
|
|
found_something = true;
|
|
@@ -1857,7 +1900,7 @@ mod tests {
|
|
|
println!("--- logic_test ---");
|
|
|
}
|
|
|
|
|
|
- #[ignore]
|
|
|
+ #[ignore = "Possible doesn't process these correctly. No, not yet!"]
|
|
|
#[test]
|
|
|
fn try_this_out() {
|
|
|
let mut board = AnyBoard::new(3);
|