|
@@ -6,14 +6,39 @@ New code -
|
|
|
The old code below only handles 3x3 puzzles only!
|
|
|
*/
|
|
|
|
|
|
+// use std::fmt;
|
|
|
+use strum::EnumIter;
|
|
|
+use strum::IntoEnumIterator;
|
|
|
+// use strum_macros::EnumIter;
|
|
|
+
|
|
|
+#[derive(Debug, EnumIter, PartialEq, Copy, Clone)]
|
|
|
+pub enum Groups {
|
|
|
+ Row,
|
|
|
+ Column,
|
|
|
+ Cell,
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ impl fmt::Display for Groups {
|
|
|
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
+ write!(f, "{:?}", self)
|
|
|
+ // or, alternatively:
|
|
|
+ // fmt::Debug::fmt(self, f)
|
|
|
+ }
|
|
|
+}
|
|
|
+*/
|
|
|
+
|
|
|
#[derive(Debug, Clone)]
|
|
|
pub struct AnyGroup {
|
|
|
pub size: u8,
|
|
|
pub width: u8,
|
|
|
pub max_index: usize,
|
|
|
+ pub groups: [Vec<usize>; 3],
|
|
|
+ /*
|
|
|
pub row: Vec<usize>,
|
|
|
pub column: Vec<usize>,
|
|
|
pub cell: Vec<usize>,
|
|
|
+ */
|
|
|
}
|
|
|
|
|
|
/// Find the number of digits needed to display given number.
|
|
@@ -29,14 +54,18 @@ fn find_number_width(mut number: usize) -> usize {
|
|
|
|
|
|
impl AnyGroup {
|
|
|
pub fn new(board_size: u8) -> Self {
|
|
|
- let width = board_size as usize * board_size as usize;
|
|
|
+ let b_width = board_size as usize * board_size as usize;
|
|
|
+ let size = b_width * b_width;
|
|
|
let mut g = AnyGroup {
|
|
|
size: board_size,
|
|
|
width: board_size * board_size,
|
|
|
- max_index: width * width,
|
|
|
- row: vec![0; width * width],
|
|
|
- column: vec![0; width * width],
|
|
|
- cell: vec![0; width * width],
|
|
|
+ max_index: size,
|
|
|
+ groups: [vec![0; size], vec![0; size], vec![0; size]],
|
|
|
+ /*
|
|
|
+ row: vec![0; b_width * b_width],
|
|
|
+ column: vec![0; size],
|
|
|
+ cell: vec![0; size],
|
|
|
+ */
|
|
|
};
|
|
|
g.calculate();
|
|
|
g
|
|
@@ -51,25 +80,31 @@ impl AnyGroup {
|
|
|
((index % width) as u8, (index / width) as u8)
|
|
|
}
|
|
|
|
|
|
+ pub fn group(&self, g: Groups, row: u8) -> &[usize] {
|
|
|
+ let width = self.width as usize;
|
|
|
+ let start = row as usize * width;
|
|
|
+ &self.groups[g as usize][start..start + width]
|
|
|
+ }
|
|
|
+
|
|
|
pub fn row(&self, row: u8) -> &[usize] {
|
|
|
// return slice of row:
|
|
|
let width = self.width as usize;
|
|
|
let start = row as usize * width;
|
|
|
- &self.row[start..start + width]
|
|
|
+ &self.groups[Groups::Row as usize][start..start + width]
|
|
|
}
|
|
|
|
|
|
pub fn column(&self, column: u8) -> &[usize] {
|
|
|
// return slice of row:
|
|
|
let width = self.width as usize;
|
|
|
let start = column as usize * width;
|
|
|
- &self.column[start..start + width]
|
|
|
+ &self.groups[Groups::Column as usize][start..start + width]
|
|
|
}
|
|
|
|
|
|
pub fn cell(&self, cell: u8) -> &[usize] {
|
|
|
// return slice of cell:
|
|
|
let width = self.width as usize;
|
|
|
let start = cell as usize * width;
|
|
|
- &self.cell[start..start + width]
|
|
|
+ &self.groups[Groups::Cell as usize][start..start + width]
|
|
|
}
|
|
|
|
|
|
/// Which cell contains (x,y)?
|
|
@@ -81,8 +116,11 @@ impl AnyGroup {
|
|
|
for y in 0..self.width {
|
|
|
for x in 0..self.width {
|
|
|
let index = x as usize + y as usize * self.width as usize;
|
|
|
- self.row[index] = self.pos(x, y);
|
|
|
- self.column[index] = self.pos(y, x);
|
|
|
+ self.groups[Groups::Row as usize][index] = self.pos(x, y);
|
|
|
+ self.groups[Groups::Column as usize][index] = self.pos(y, x);
|
|
|
+
|
|
|
+ // self.row[index] = self.pos(x, y);
|
|
|
+ // self.column[index] = self.pos(y, x);
|
|
|
|
|
|
let x_off = x / self.size;
|
|
|
let y_off = y / self.size;
|
|
@@ -92,11 +130,15 @@ impl AnyGroup {
|
|
|
// x_mod + y_mod * self.size;
|
|
|
// y is correct:
|
|
|
// x_off + y_off * self.size
|
|
|
- self.cell[index] = self.pos(
|
|
|
+ self.groups[Groups::Cell as usize][index] =
|
|
|
+ self.pos(x_mod + y_mod * self.size, x_off + y_off * self.size);
|
|
|
+
|
|
|
+ /* self.cell[index] = self.pos(
|
|
|
x_mod + y_mod * self.size,
|
|
|
x_off + y_off * self.size, // x_mod + x_off * self.size,
|
|
|
// y_off
|
|
|
);
|
|
|
+ */
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -124,6 +166,23 @@ impl AnyGroup {
|
|
|
println!("");
|
|
|
};
|
|
|
|
|
|
+ for g in Groups::iter() {
|
|
|
+ println!("{:?}:", g);
|
|
|
+
|
|
|
+ for i in 0..self.width {
|
|
|
+ let r = self.group(g, i);
|
|
|
+ /*
|
|
|
+ print!("[{:2}]: ", i);
|
|
|
+ for j in r {
|
|
|
+ let xy = self.xy(*j);
|
|
|
+ print!("{0:1$}({2:2},{3:2}) ", j, max_index_size, xy.0, xy.1);
|
|
|
+ }
|
|
|
+ println!("");
|
|
|
+ */
|
|
|
+ printer(i, r);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /*
|
|
|
println!("rows:");
|
|
|
// println!("{:?}", self.row);
|
|
|
for i in 0..self.width {
|
|
@@ -167,56 +226,74 @@ impl AnyGroup {
|
|
|
*/
|
|
|
printer(i, r);
|
|
|
}
|
|
|
+ */
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
#[cfg(test)]
|
|
|
mod tests {
|
|
|
use crate::group::*;
|
|
|
|
|
|
#[test]
|
|
|
+ /// Verify that each index (0..max_index) is defined in each group.
|
|
|
+ /// - Verify that it is used, and only once.
|
|
|
fn check_dynamic() {
|
|
|
- // Verify that each index (0..max_index) is defined in each group.
|
|
|
- // - Verify that it is used, and only once.
|
|
|
+
|
|
|
|
|
|
for size in 3..=5 {
|
|
|
let g = AnyGroup::new(size);
|
|
|
+ // g.display();
|
|
|
let mut all = vec![0 as u8; g.max_index];
|
|
|
|
|
|
// Verify the X,Y values are in the correct cell.
|
|
|
- all.fill(0);
|
|
|
+ for gr in Groups::iter() {
|
|
|
+ all.fill(0);
|
|
|
|
|
|
- for idx in 0..g.width {
|
|
|
- let grp = g.cell(idx);
|
|
|
- // g.display();
|
|
|
- for indexes in grp {
|
|
|
- let (x, y) = g.xy(*indexes);
|
|
|
+ for idx in 0..g.width {
|
|
|
+ let grp = g.group(gr, idx); // cell(idx);
|
|
|
+ // g.display();
|
|
|
+ for indexes in grp {
|
|
|
+ let (x, y) = g.xy(*indexes);
|
|
|
+ assert!(
|
|
|
+ all[*indexes] == 0,
|
|
|
+ "{:?} Size {} Index [{}]({},{}) already seen",
|
|
|
+ gr,
|
|
|
+ size,
|
|
|
+ *indexes,
|
|
|
+ x + 1,
|
|
|
+ y + 1
|
|
|
+ );
|
|
|
+ all[*indexes] = 1;
|
|
|
+ if gr == Groups::Cell {
|
|
|
+ assert_eq!(
|
|
|
+ g.which_cell(x, y),
|
|
|
+ idx,
|
|
|
+ "Verify {:?} [{}]({},{}) in cell {}",
|
|
|
+ gr,
|
|
|
+ *indexes,
|
|
|
+ x,
|
|
|
+ y,
|
|
|
+ idx
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for indexes in 0..g.max_index {
|
|
|
+ let (x, y) = g.xy(indexes);
|
|
|
assert!(
|
|
|
- all[*indexes] == 0,
|
|
|
- "Size {} Index [{}]({},{}) already seen",
|
|
|
+ all[indexes] == 1,
|
|
|
+ "{:?} Size {} Index [{}]({},{}) not seen",
|
|
|
+ gr,
|
|
|
size,
|
|
|
- *indexes,
|
|
|
+ indexes,
|
|
|
x + 1,
|
|
|
y + 1
|
|
|
);
|
|
|
- all[*indexes] = 1;
|
|
|
- assert_eq!(g.which_cell(x, y), idx, "Verify [{}]({},{}) in cell {}", *indexes, x, y, idx);
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- for indexes in 0..g.max_index {
|
|
|
- let (x, y) = g.xy(indexes);
|
|
|
- assert!(
|
|
|
- all[indexes] == 1,
|
|
|
- "Size {} Index [{}]({},{}) not seen",
|
|
|
- size,
|
|
|
- indexes,
|
|
|
- x + 1,
|
|
|
- y + 1
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
+ /*
|
|
|
all.fill(0);
|
|
|
for idx in 0..g.width {
|
|
|
let grp = g.row(idx);
|
|
@@ -277,6 +354,7 @@ mod tests {
|
|
|
y + 1
|
|
|
);
|
|
|
}
|
|
|
+ */
|
|
|
}
|
|
|
}
|
|
|
}
|