|
@@ -606,22 +606,48 @@ impl AnyPossible {
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ How can I find the max size of each display possible item?
|
|
|
|
+ I'd like to cache the info so I don't re-calc it, and I'd like a pony! :P
|
|
|
|
+
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ /// Format all possible, finding max length.
|
|
|
|
+ pub fn pos_max(&self) -> (Vec<String>, usize) {
|
|
|
|
+ let mut pos = Vec::<String>::new();
|
|
|
|
+ pos.reserve(self.max_index);
|
|
|
|
+ let mut max: usize = 0;
|
|
|
|
+
|
|
|
|
+ for idx in 0..self.max_index {
|
|
|
|
+ let s = self.possible[idx].display();
|
|
|
|
+ if max < s.len() {
|
|
|
|
+ max = s.len();
|
|
|
|
+ }
|
|
|
|
+ pos.push(s);
|
|
|
|
+ }
|
|
|
|
+ (pos, max)
|
|
|
|
+ }
|
|
|
|
+
|
|
pub fn display(&self) {
|
|
pub fn display(&self) {
|
|
|
|
+ let pos_info = self.pos_max();
|
|
|
|
+
|
|
for y in 0..self.width {
|
|
for y in 0..self.width {
|
|
for x in 0..self.width {
|
|
for x in 0..self.width {
|
|
let idx = self.pos(x, y);
|
|
let idx = self.pos(x, y);
|
|
|
|
+
|
|
|
|
+ /*
|
|
let possible = self.possible[idx];
|
|
let possible = self.possible[idx];
|
|
let values: Vec<u8> = possible.iter().collect();
|
|
let values: Vec<u8> = possible.iter().collect();
|
|
// let stuff: String = values.into_iter().map(|i| i.to_string().push_str(",")).collect::<String>();
|
|
// let stuff: String = values.into_iter().map(|i| i.to_string().push_str(",")).collect::<String>();
|
|
|
|
+ // let output = values.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
|
|
|
|
+
|
|
let stuff: String = values
|
|
let stuff: String = values
|
|
.into_iter()
|
|
.into_iter()
|
|
.map(|i| (i + 1).to_string())
|
|
.map(|i| (i + 1).to_string())
|
|
- .collect::<String>();
|
|
|
|
- /*
|
|
|
|
- if stuff.len() > 1 {
|
|
|
|
- stuff.pop();
|
|
|
|
- }*/
|
|
|
|
- print!("({},{}):{:9} ", x + 1, y + 1, stuff);
|
|
|
|
|
|
+ // .collect::<String>();
|
|
|
|
+ .collect::<Vec<_>>().join(",");
|
|
|
|
+ */
|
|
|
|
+ print!("({},{}):{:3$} ", x + 1, y + 1, pos_info.0[idx], pos_info.1);
|
|
}
|
|
}
|
|
println!("");
|
|
println!("");
|
|
}
|
|
}
|
|
@@ -868,7 +894,8 @@ impl AnySolver {
|
|
/// - Call solve until it returns false.
|
|
/// - Call solve until it returns false.
|
|
/// - It might not be solved (if guessing is required).
|
|
/// - It might not be solved (if guessing is required).
|
|
pub fn solve_logic(&mut self) -> bool {
|
|
pub fn solve_logic(&mut self) -> bool {
|
|
- self.reset_possible();
|
|
|
|
|
|
+ // self.reset_possible(); // destroys anything pass3 accomplishes ...
|
|
|
|
+
|
|
// self.board.display();
|
|
// self.board.display();
|
|
// self.possible.display();
|
|
// self.possible.display();
|
|
|
|
|
|
@@ -913,7 +940,19 @@ impl AnySolver {
|
|
// Nothing found with this run of pass 1.
|
|
// Nothing found with this run of pass 1.
|
|
|
|
|
|
// Pass 2 - Look for singles within the groups.
|
|
// Pass 2 - Look for singles within the groups.
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ // Are we done?
|
|
|
|
+ /*
|
|
|
|
+ if self.board.complete() {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // We're getting stuck in pass 2 ...
|
|
|
|
+ // not anymore. ;)
|
|
|
|
+ println!("Pass 2:");
|
|
|
|
+ self.board.display();
|
|
|
|
+
|
|
|
|
+ */
|
|
|
|
+
|
|
found_something = false;
|
|
found_something = false;
|
|
|
|
|
|
let mut values = Bits(0); // HashSet<u8> = HashSet::new();
|
|
let mut values = Bits(0); // HashSet<u8> = HashSet::new();
|
|
@@ -929,16 +968,16 @@ impl AnySolver {
|
|
// values.extend(this.possible[grp.0[gidx as usize] as usize]);
|
|
// values.extend(this.possible[grp.0[gidx as usize] as usize]);
|
|
// println!("now : {:?}", this.possible[grp.items[gidx as usize] as usize]);
|
|
// println!("now : {:?}", this.possible[grp.items[gidx as usize] as usize]);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// println!("values {:?}", values);
|
|
// println!("values {:?}", values);
|
|
-
|
|
|
|
|
|
+
|
|
// Now, check for singles.
|
|
// Now, check for singles.
|
|
for v in values.iter() {
|
|
for v in values.iter() {
|
|
// println!("Check Value: {}", v);
|
|
// println!("Check Value: {}", v);
|
|
-
|
|
|
|
|
|
+
|
|
let mut count = 0;
|
|
let mut count = 0;
|
|
let mut pos = 0;
|
|
let mut pos = 0;
|
|
-
|
|
|
|
|
|
+
|
|
for gidx in 0..width {
|
|
for gidx in 0..width {
|
|
if this.possible.possible[grp[gidx as usize]].get(v as usize) {
|
|
if this.possible.possible[grp[gidx as usize]].get(v as usize) {
|
|
// if this.possible[grp.0[gidx as usize] as usize].contains(&v) {
|
|
// if this.possible[grp.0[gidx as usize] as usize].contains(&v) {
|
|
@@ -957,14 +996,14 @@ impl AnySolver {
|
|
let xy = this.board.xy(pos);
|
|
let xy = this.board.xy(pos);
|
|
// this.possible.display();
|
|
// this.possible.display();
|
|
// this.board.display();
|
|
// this.board.display();
|
|
- this.set(xy.0, xy.1, v+1);
|
|
|
|
|
|
+ this.set(xy.0, xy.1, v + 1);
|
|
// println!("SET {} ({},{}) = {}", pos, xy.0 + 1, xy.1 + 1, v+1);
|
|
// println!("SET {} ({},{}) = {}", pos, xy.0 + 1, xy.1 + 1, v+1);
|
|
-
|
|
|
|
|
|
+
|
|
found_something = true;
|
|
found_something = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
};
|
|
-
|
|
|
|
|
|
+
|
|
// Change to 0..WIDTH ... Keep it simple.
|
|
// Change to 0..WIDTH ... Keep it simple.
|
|
for i in 0..width {
|
|
for i in 0..width {
|
|
// println!("Column {i}:");
|
|
// println!("Column {i}:");
|
|
@@ -976,8 +1015,8 @@ impl AnySolver {
|
|
// println!("Cell {i}:");
|
|
// println!("Cell {i}:");
|
|
g = grp.cell(i);
|
|
g = grp.cell(i);
|
|
group_process(self, g);
|
|
group_process(self, g);
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
if found_something == true {
|
|
if found_something == true {
|
|
pass2 = true;
|
|
pass2 = true;
|
|
// Ok, pass 2 found something.
|
|
// Ok, pass 2 found something.
|
|
@@ -992,180 +1031,107 @@ impl AnySolver {
|
|
if pass1 {
|
|
if pass1 {
|
|
pass1_again = false;
|
|
pass1_again = false;
|
|
found_something = true;
|
|
found_something = true;
|
|
|
|
+ } else {
|
|
|
|
+ // Ok, we didn't find anything.
|
|
|
|
+ // Break out of loop, get unstuck.
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // After changing Pass1 to loop, I don't think I need to go over the
|
|
|
|
- // groups now. Besides, possible should be covering all the groups
|
|
|
|
- // anyway!
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- println!("Set2:");
|
|
|
|
- self.board.display();
|
|
|
|
- self.possible.display();
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
- // This is a mess here. It looks obsoleted by the above pass1 loop.
|
|
|
|
|
|
+ // Pass 3:
|
|
|
|
+ // - Find pairs & remove those numbers from corresponding group.
|
|
|
|
|
|
- // No, it isn't.
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- Set2:
|
|
|
|
-╔═══╦═══╦═══╗
|
|
|
|
-║ 1║7 8║3 ║
|
|
|
|
-║ 73║ ║68 ║
|
|
|
|
-║286║934║751║
|
|
|
|
-╠═══╬═══╬═══╣
|
|
|
|
-║ ║1 7║ ║
|
|
|
|
-║ 2 ║ ║ 9 ║
|
|
|
|
-║ 14║ ║86 ║
|
|
|
|
-╠═══╬═══╬═══╣
|
|
|
|
-║ 8║3 1║9 ║
|
|
|
|
-║ ║ ║ ║
|
|
|
|
-║432║879║516║
|
|
|
|
-╚═══╩═══╩═══╝
|
|
|
|
-(1,1):59 (2,1):459 (3,1): (4,1): (5,1):256 (6,1): (7,1): (8,1):24 (9,1):249
|
|
|
|
-(1,2):59 (2,2): (3,2): (4,2):25 (5,2):125 (6,2):25 (7,2): (8,2): (9,2):249
|
|
|
|
-(1,3): (2,3): (3,3): (4,3): (5,3): (6,3): (7,3): (8,3): (9,3):
|
|
|
|
-(1,4):35689 (2,4):569 (3,4):59 (4,4): (5,4):245689 (6,4): (7,4):24 (8,4):234 (9,4):2345
|
|
|
|
-(1,5):35678 (2,5): (3,5):57 (4,5):456 (5,5):4568 (6,5):356 (7,5):14 (8,5): (9,5):3457
|
|
|
|
-(1,6):3579 (2,6): (3,6): (4,6):25 (5,6):259 (6,6):235 (7,6): (8,6): (9,6):2357
|
|
|
|
-(1,7):567 (2,7):56 (3,7): (4,7): (5,7):2456 (6,7): (7,7): (8,7):247 (9,7):247
|
|
|
|
-(1,8):15679 (2,8):569 (3,8):579 (4,8):2456 (5,8):2456 (6,8):256 (7,8):24 (8,8):2347 (9,8):23478
|
|
|
|
-(1,9): (2,9): (3,9): (4,9): (5,9): (6,9): (7,9): (8,9): (9,9):
|
|
|
|
-
|
|
|
|
- See:
|
|
|
|
- (2,1) only has a 4 in cell/column.
|
|
|
|
- (5,2) only has a 1 in cell.
|
|
|
|
- (7,5) only has a 1 in column.
|
|
|
|
- (1,8) only has a 1 (rows/column).
|
|
|
|
- (9,8) only has 8.
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- let width = self.group.width;
|
|
|
|
let grp = self.group.clone();
|
|
let grp = self.group.clone();
|
|
- let mut values = Bits(0); // HashSet<u8> = HashSet::new();
|
|
|
|
-
|
|
|
|
- let mut group_process = |this: &mut Self, grp: &[usize]| {
|
|
|
|
- // 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]);
|
|
|
|
- for v in this.possible.possible[grp[gidx 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]);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- println!("values {:?}", values);
|
|
|
|
|
|
|
|
- // Now, check for singles.
|
|
|
|
- for v in values.iter() {
|
|
|
|
- println!("Check Value: {}", v);
|
|
|
|
-
|
|
|
|
- let mut count = 0;
|
|
|
|
- let mut pos = 0;
|
|
|
|
-
|
|
|
|
- for gidx in 0..width {
|
|
|
|
- if this.possible.possible[grp[gidx as usize]].get(v as usize) {
|
|
|
|
- // if this.possible[grp.0[gidx as usize] as usize].contains(&v) {
|
|
|
|
- count += 1;
|
|
|
|
- pos = grp[gidx as usize];
|
|
|
|
- if count > 1 {
|
|
|
|
- break;
|
|
|
|
- } else {
|
|
|
|
- print!(" IDX {} POS {} ", gidx, pos);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if count == 1 {
|
|
|
|
- // don't need this, it was v!
|
|
|
|
- // let value = this.possible[pos as usize].iter().next().cloned().unwrap();
|
|
|
|
- let xy = this.board.xy(pos);
|
|
|
|
- this.possible.display();
|
|
|
|
- this.board.display();
|
|
|
|
- this.set(xy.0, xy.1, v);
|
|
|
|
- println!("SET {} ({},{}) = {}", pos, xy.0 + 1, xy.1 + 1, v);
|
|
|
|
-
|
|
|
|
- found_something = true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- // Change to 0..WIDTH ... Keep it simple.
|
|
|
|
- for i in 0..width {
|
|
|
|
- println!("Column {i}:");
|
|
|
|
- let mut g = grp.column(i);
|
|
|
|
- group_process(self, g);
|
|
|
|
- println!("Row {i}:");
|
|
|
|
- g = grp.row(i);
|
|
|
|
- group_process(self, g);
|
|
|
|
- println!("Cell {i}:");
|
|
|
|
- g = grp.cell(i);
|
|
|
|
- group_process(self, g);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if found_something {
|
|
|
|
- return found_something;
|
|
|
|
- }
|
|
|
|
- */
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
|
|
+ println!("Pass 3:");
|
|
|
|
+ self.board.display();
|
|
|
|
+ self.possible.display();
|
|
|
|
|
|
- let width = self.group.width;
|
|
|
|
- let grp = self.group.clone();
|
|
|
|
|
|
+ assert_eq!(self.board.width, self.possible.width);
|
|
|
|
|
|
// Pair processing.
|
|
// Pair processing.
|
|
for i in 0..width {
|
|
for i in 0..width {
|
|
let mut g = grp.cell(i);
|
|
let mut g = grp.cell(i);
|
|
|
|
+ println!("Cell {}: {:?}", i, g);
|
|
|
|
|
|
for gidx in 0..WIDTH - 1 {
|
|
for gidx in 0..WIDTH - 1 {
|
|
let gpos = g[gidx as usize];
|
|
let gpos = g[gidx as usize];
|
|
- if self.possible.possible[gpos as usize].count_set() == 2 {
|
|
|
|
|
|
+ if self.possible.possible[gpos].count_set() == 2 {
|
|
// Found a pair
|
|
// Found a pair
|
|
|
|
+
|
|
for fidx in gidx + 1..width {
|
|
for fidx in gidx + 1..width {
|
|
let fpos = g[fidx as usize];
|
|
let fpos = g[fidx as usize];
|
|
if self.possible.possible[fpos as usize].count_set() == 2 {
|
|
if self.possible.possible[fpos as usize].count_set() == 2 {
|
|
// Ok, there's another pair
|
|
// 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.possible[gpos] == self.possible.possible[fpos as usize]
|
|
|
|
- {
|
|
|
|
|
|
+
|
|
|
|
+ if self.possible.possible[gpos] == self.possible.possible[fpos] {
|
|
// Ok, they have the same values!
|
|
// Ok, they have the same values!
|
|
// Ok, remove the items in the pair from the cell.
|
|
// Ok, remove the items in the pair from the cell.
|
|
// Don't touch the gpos/fpos records. Keep those!
|
|
// Don't touch the gpos/fpos records. Keep those!
|
|
|
|
+
|
|
|
|
+ // This looks .. WRONG! only z+1 when using set(value)!
|
|
|
|
+
|
|
let mut values: [u8; 2] = [0, 0];
|
|
let mut values: [u8; 2] = [0, 0];
|
|
let mut vpos = 0;
|
|
let mut vpos = 0;
|
|
for z in self.possible.possible[gpos].iter() {
|
|
for z in self.possible.possible[gpos].iter() {
|
|
- values[vpos] = z + 1;
|
|
|
|
|
|
+ values[vpos] = z;
|
|
vpos += 1;
|
|
vpos += 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Ok, other then being off by 1 (because x,y starts at 0 not 1),
|
|
|
|
+ // This is, at least, displaying the information properly.
|
|
|
|
+
|
|
|
|
+ self.possible.display();
|
|
|
|
+ println!(
|
|
|
|
+ "Pairs {gpos}({},{}) and {fpos}({},{}) {:?}",
|
|
|
|
+ self.possible.xy(gpos).0 + 1,
|
|
|
|
+ self.possible.xy(gpos).1 + 1,
|
|
|
|
+ self.possible.xy(fpos).0 + 1,
|
|
|
|
+ self.possible.xy(fpos).1 + 1,
|
|
|
|
+ values
|
|
|
|
+ );
|
|
|
|
+
|
|
let mut pair_removed = false;
|
|
let mut pair_removed = false;
|
|
|
|
|
|
// Check to see if anything was removed.
|
|
// Check to see if anything was removed.
|
|
|
|
|
|
for remove in 0..width {
|
|
for remove in 0..width {
|
|
if (gidx == remove) || (fidx == remove) {
|
|
if (gidx == remove) || (fidx == remove) {
|
|
|
|
+ // Skip the found pair indexes. Don't remove those!
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
+
|
|
// Ok, these aren't the ones to save, so:
|
|
// Ok, these aren't the ones to save, so:
|
|
let rpos = g[remove as usize];
|
|
let rpos = g[remove as usize];
|
|
if self.possible.possible[rpos].get(values[0] as usize) {
|
|
if self.possible.possible[rpos].get(values[0] as usize) {
|
|
self.possible.possible[rpos].set(values[0] as usize, false);
|
|
self.possible.possible[rpos].set(values[0] as usize, false);
|
|
found_something = true;
|
|
found_something = true;
|
|
pair_removed = true;
|
|
pair_removed = true;
|
|
|
|
+ println!("Removed {} from {}({},{})", values[0], rpos, self.possible.xy(rpos).0, self.possible.xy(rpos).1);
|
|
}
|
|
}
|
|
|
|
|
|
if self.possible.possible[rpos].get(values[1] as usize) {
|
|
if self.possible.possible[rpos].get(values[1] as usize) {
|
|
self.possible.possible[rpos].set(values[1] as usize, false);
|
|
self.possible.possible[rpos].set(values[1] as usize, false);
|
|
found_something = true;
|
|
found_something = true;
|
|
pair_removed = true;
|
|
pair_removed = true;
|
|
|
|
+ println!("Removed {} from {}({},{})", values[1], rpos, self.possible.xy(rpos).0, self.possible.xy(rpos).1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if pair_removed {
|
|
|
|
+ println!("pair removed...");
|
|
|
|
+ println!(
|
|
|
|
+ "--> Pairs {gpos}({},{}) and {fpos}({},{}) {:?}",
|
|
|
|
+ self.possible.xy(gpos).0 + 1,
|
|
|
|
+ self.possible.xy(gpos).1 + 1,
|
|
|
|
+ self.possible.xy(fpos).0 + 1,
|
|
|
|
+ self.possible.xy(fpos).1 + 1,
|
|
|
|
+ values
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
// Check the x's and y's to see if we can also process a row/column too.
|
|
// Check the x's and y's to see if we can also process a row/column too.
|
|
if self.possible.xy(gpos).0 == self.possible.xy(fpos).0 {
|
|
if self.possible.xy(gpos).0 == self.possible.xy(fpos).0 {
|
|
// Matching X - process column
|
|
// Matching X - process column
|
|
@@ -1232,27 +1198,28 @@ impl AnySolver {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
if pair_removed {
|
|
if pair_removed {
|
|
- if debug {
|
|
|
|
|
|
+ if true {
|
|
println!(
|
|
println!(
|
|
"Pair found! {} {}: {} {:?} and {} {:?} !",
|
|
"Pair found! {} {}: {} {:?} and {} {:?} !",
|
|
gidx,
|
|
gidx,
|
|
fidx,
|
|
fidx,
|
|
gpos,
|
|
gpos,
|
|
- xy(gpos),
|
|
|
|
|
|
+ self.board.xy(gpos),
|
|
fpos,
|
|
fpos,
|
|
- xy(fpos)
|
|
|
|
|
|
+ self.board.xy(fpos)
|
|
);
|
|
);
|
|
|
|
+ self.possible.display();
|
|
|
|
+ // panic!("... We're lost ...");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- */
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ println!("Pass 3 - Ending...");
|
|
found_something
|
|
found_something
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1290,13 +1257,14 @@ mod tests {
|
|
// board.display();
|
|
// board.display();
|
|
let mut solver = AnySolver::new_from(&board);
|
|
let mut solver = AnySolver::new_from(&board);
|
|
assert!(solver.validate_board());
|
|
assert!(solver.validate_board());
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ solver.reset_possible();
|
|
// solver.solve_logic();
|
|
// solver.solve_logic();
|
|
-
|
|
|
|
|
|
+
|
|
while (solver.solve_logic()) {
|
|
while (solver.solve_logic()) {
|
|
solver.board.display();
|
|
solver.board.display();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
assert!(solver.validate_board());
|
|
assert!(solver.validate_board());
|
|
assert!(solver.board.complete());
|
|
assert!(solver.board.complete());
|
|
|
|
|
|
@@ -1334,7 +1302,7 @@ mod tests {
|
|
while (solver.solve_logic()) {
|
|
while (solver.solve_logic()) {
|
|
solver.board.display();
|
|
solver.board.display();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
assert!(solver.validate_board());
|
|
assert!(solver.validate_board());
|
|
solver.board.display();
|
|
solver.board.display();
|
|
assert!(solver.board.complete());
|
|
assert!(solver.board.complete());
|