|  | @@ -37,7 +37,9 @@ struct Ksudoku {
 | 
	
		
			
				|  |  |      game: Game,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const SIZE: u8 = 9;
 | 
	
		
			
				|  |  | +/// Width of the sudoku board.
 | 
	
		
			
				|  |  | +const WIDTH: u8 = 9;
 | 
	
		
			
				|  |  | +/// Size (width * height) of the board.
 | 
	
		
			
				|  |  |  const MAX_SIZE: u8 = 81;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #[derive(Debug)]
 | 
	
	
		
			
				|  | @@ -46,18 +48,19 @@ struct Sudoku {
 | 
	
		
			
				|  |  |      possible: [HashSet<u8>; MAX_SIZE as usize],
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Translate x,y to position in board.
 | 
	
		
			
				|  |  | +/// Translate x,y to position in board.
 | 
	
		
			
				|  |  |  const fn pos(x: u8, y: u8) -> u8 {
 | 
	
		
			
				|  |  | -    x + (y * SIZE as u8)
 | 
	
		
			
				|  |  | +    x + (y * WIDTH as u8)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/// Translate x,y (with starting index of 1) to position in board.
 | 
	
		
			
				|  |  |  const fn pos1(x: u8, y: u8) -> u8 {
 | 
	
		
			
				|  |  | -    (x - 1) + ((y - 1) * SIZE as u8)
 | 
	
		
			
				|  |  | +    (x - 1) + ((y - 1) * WIDTH as u8)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Translate post to x,y in board.
 | 
	
		
			
				|  |  | +/// Translate post to x,y in board.
 | 
	
		
			
				|  |  |  const fn xy(pos: u8) -> (u8, u8) {
 | 
	
		
			
				|  |  | -    ((pos % SIZE), (pos / SIZE))
 | 
	
		
			
				|  |  | +    ((pos % WIDTH), (pos / WIDTH))
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /*
 | 
	
	
		
			
				|  | @@ -108,7 +111,7 @@ impl Sudoku {
 | 
	
		
			
				|  |  |                  // self.board[pos(x, y) as usize] = ch as u8 - 'a' as u8;
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  |              y += 1;
 | 
	
		
			
				|  |  | -            if y >= SIZE {
 | 
	
		
			
				|  |  | +            if y >= WIDTH {
 | 
	
		
			
				|  |  |                  y = 0;
 | 
	
		
			
				|  |  |                  x += 1;
 | 
	
		
			
				|  |  |              }
 | 
	
	
		
			
				|  | @@ -116,6 +119,30 @@ impl Sudoku {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn set(&mut self, x: u8, y: u8, value: u8) {
 | 
	
		
			
				|  |  | +        self.board[pos(x, y) as usize] = value;
 | 
	
		
			
				|  |  | +        // Ok, update the possible
 | 
	
		
			
				|  |  | +        let mut g = for_row(y); 
 | 
	
		
			
				|  |  | +        // g.for_row(x, y);
 | 
	
		
			
				|  |  | +        for g in g.items {
 | 
	
		
			
				|  |  | +            // remove value from these sets.
 | 
	
		
			
				|  |  | +            self.possible[g as usize].take(&value);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        g = for_column(x); 
 | 
	
		
			
				|  |  | +        // g.for_column(x, y);
 | 
	
		
			
				|  |  | +        for g in g.items {
 | 
	
		
			
				|  |  | +            // remove value from these sets.
 | 
	
		
			
				|  |  | +            self.possible[g as usize].take(&value);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        g = for_cell(which_cell(x,y)); 
 | 
	
		
			
				|  |  | +        // g.for_block(x, y);
 | 
	
		
			
				|  |  | +        for g in g.items {
 | 
	
		
			
				|  |  | +            // remove value from these sets.
 | 
	
		
			
				|  |  | +            self.possible[g as usize].take(&value);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        self.possible[pos(x, y) as usize].clear();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fn set2(&mut self, x: u8, y: u8, value: u8) {
 | 
	
		
			
				|  |  |          self.board[pos(x, y) as usize] = value;
 | 
	
		
			
				|  |  |          // Ok, update the possible
 | 
	
		
			
				|  |  |          let mut g = Group::new();
 | 
	
	
		
			
				|  | @@ -124,11 +151,13 @@ impl Sudoku {
 | 
	
		
			
				|  |  |              // remove value from these sets.
 | 
	
		
			
				|  |  |              self.possible[g as usize].take(&value);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  |          g.for_column(x, y);
 | 
	
		
			
				|  |  |          for g in g.items {
 | 
	
		
			
				|  |  |              // remove value from these sets.
 | 
	
		
			
				|  |  |              self.possible[g as usize].take(&value);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  |          g.for_block(x, y);
 | 
	
		
			
				|  |  |          for g in g.items {
 | 
	
		
			
				|  |  |              // remove value from these sets.
 | 
	
	
		
			
				|  | @@ -137,11 +166,12 @@ impl Sudoku {
 | 
	
		
			
				|  |  |          self.possible[pos(x, y) as usize].clear();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      fn display(&self) {
 | 
	
		
			
				|  |  |          println!("╔═══╦═══╦═══╗");
 | 
	
		
			
				|  |  | -        for y in 0..SIZE {
 | 
	
		
			
				|  |  | +        for y in 0..WIDTH {
 | 
	
		
			
				|  |  |              print!("║");
 | 
	
		
			
				|  |  | -            for x in 0..SIZE {
 | 
	
		
			
				|  |  | +            for x in 0..WIDTH {
 | 
	
		
			
				|  |  |                  let item = self.board[pos(x as u8, y as u8) as usize];
 | 
	
		
			
				|  |  |                  if item == 0 {
 | 
	
		
			
				|  |  |                      print!(" ");
 | 
	
	
		
			
				|  | @@ -154,7 +184,7 @@ impl Sudoku {
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              println!("");
 | 
	
		
			
				|  |  |              if y % 3 == 2 {
 | 
	
		
			
				|  |  | -                if y + 1 == SIZE {
 | 
	
		
			
				|  |  | +                if y + 1 == WIDTH {
 | 
	
		
			
				|  |  |                      println!("╚═══╩═══╩═══╝");
 | 
	
		
			
				|  |  |                  } else {
 | 
	
		
			
				|  |  |                      println!("╠═══╬═══╬═══╣");
 | 
	
	
		
			
				|  | @@ -164,8 +194,8 @@ impl Sudoku {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn display_possible(&self) {
 | 
	
		
			
				|  |  | -        for y in 0..SIZE {
 | 
	
		
			
				|  |  | -            for x in 0..SIZE {
 | 
	
		
			
				|  |  | +        for y in 0..WIDTH {
 | 
	
		
			
				|  |  | +            for x in 0..WIDTH {
 | 
	
		
			
				|  |  |                  let mut possible = String::new();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  for p in self.possible[pos(x, y) as usize].iter() {
 | 
	
	
		
			
				|  | @@ -212,7 +242,7 @@ impl Sudoku {
 | 
	
		
			
				|  |  |          let mut group_process = |this: &mut Self, grp: &Group| {
 | 
	
		
			
				|  |  |              // Collect all the possible values within the group.
 | 
	
		
			
				|  |  |              values.clear();
 | 
	
		
			
				|  |  | -            for gidx in 0..SIZE {
 | 
	
		
			
				|  |  | +            for gidx in 0..WIDTH {
 | 
	
		
			
				|  |  |                  // println!("possible: {:?}", this.possible[grp.items[gidx as usize] as usize]);
 | 
	
		
			
				|  |  |                  values.extend(&this.possible[grp.items[gidx as usize] as usize]);
 | 
	
		
			
				|  |  |                  // println!("now     : {:?}", this.possible[grp.items[gidx as usize] as usize]);
 | 
	
	
		
			
				|  | @@ -224,7 +254,7 @@ impl Sudoku {
 | 
	
		
			
				|  |  |              for v in values.iter() {
 | 
	
		
			
				|  |  |                  let mut count = 0;
 | 
	
		
			
				|  |  |                  let mut pos = 0;
 | 
	
		
			
				|  |  | -                for gidx in 0..SIZE {
 | 
	
		
			
				|  |  | +                for gidx in 0..WIDTH {
 | 
	
		
			
				|  |  |                      if this.possible[grp.items[gidx as usize] as usize].contains(&v) {
 | 
	
		
			
				|  |  |                          count += 1;
 | 
	
		
			
				|  |  |                          pos = grp.items[gidx as usize];
 | 
	
	
		
			
				|  | @@ -244,25 +274,28 @@ impl Sudoku {
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // Change to 0..SIZE ...  Keep it simple.
 | 
	
		
			
				|  |  | -        for i in 0..SIZE {
 | 
	
		
			
				|  |  | -            g.for_column(i, 1);
 | 
	
		
			
				|  |  | +        for i in 0..WIDTH {
 | 
	
		
			
				|  |  | +            let mut g = for_column(i);
 | 
	
		
			
				|  |  | +            // g.for_column(i, 1);
 | 
	
		
			
				|  |  |              group_process(self, &g);
 | 
	
		
			
				|  |  | -            g.for_row(1, i);
 | 
	
		
			
				|  |  | +            g = for_row(i);
 | 
	
		
			
				|  |  | +            // g.for_row(1, i);
 | 
	
		
			
				|  |  |              group_process(self, &g);
 | 
	
		
			
				|  |  | -            g.for_iter(i);
 | 
	
		
			
				|  |  | +            g = for_cell(i);
 | 
	
		
			
				|  |  | +            // g.for_iter(i);
 | 
	
		
			
				|  |  |              group_process(self, &g);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          println!("Looking for pairs...");
 | 
	
		
			
				|  |  |          // PAIR processing.
 | 
	
		
			
				|  |  | -        for i in 0..SIZE {
 | 
	
		
			
				|  |  | +        for i in 0..WIDTH {
 | 
	
		
			
				|  |  |              g.for_iter(i);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            for gidx in 0..SIZE - 1 {
 | 
	
		
			
				|  |  | +            for gidx in 0..WIDTH - 1 {
 | 
	
		
			
				|  |  |                  let gpos = g.items[gidx as usize];
 | 
	
		
			
				|  |  |                  if self.possible[gpos as usize].len() == 2 {
 | 
	
		
			
				|  |  |                      // Found a pair
 | 
	
		
			
				|  |  | -                    for fidx in gidx + 1..SIZE {
 | 
	
		
			
				|  |  | +                    for fidx in gidx + 1..WIDTH {
 | 
	
		
			
				|  |  |                          let fpos = g.items[fidx as usize];
 | 
	
		
			
				|  |  |                          if self.possible[fpos as usize].len() == 2 {
 | 
	
		
			
				|  |  |                              // Ok, there's another pair
 | 
	
	
		
			
				|  | @@ -280,7 +313,7 @@ impl Sudoku {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                                  let mut pair_removed = false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                                for remove in 0..SIZE {
 | 
	
		
			
				|  |  | +                                for remove in 0..WIDTH {
 | 
	
		
			
				|  |  |                                      if (gidx == remove) || (fidx == remove) {
 | 
	
		
			
				|  |  |                                          continue;
 | 
	
		
			
				|  |  |                                      }
 | 
	
	
		
			
				|  | @@ -318,7 +351,7 @@ impl Sudoku {
 | 
	
		
			
				|  |  |                                          values[vpos] = *z;
 | 
	
		
			
				|  |  |                                          vpos += 1;
 | 
	
		
			
				|  |  |                                      }
 | 
	
		
			
				|  |  | -                                    for remove in 0..SIZE {
 | 
	
		
			
				|  |  | +                                    for remove in 0..WIDTH {
 | 
	
		
			
				|  |  |                                          if (remove == xy(gpos).1) || (remove == xy(fpos).1) {
 | 
	
		
			
				|  |  |                                              continue;
 | 
	
		
			
				|  |  |                                          }
 | 
	
	
		
			
				|  | @@ -345,7 +378,7 @@ impl Sudoku {
 | 
	
		
			
				|  |  |                                          values[vpos] = *z;
 | 
	
		
			
				|  |  |                                          vpos += 1;
 | 
	
		
			
				|  |  |                                      }
 | 
	
		
			
				|  |  | -                                    for remove in 0..SIZE {
 | 
	
		
			
				|  |  | +                                    for remove in 0..WIDTH {
 | 
	
		
			
				|  |  |                                          if (remove == xy(gpos).0) || (remove == xy(fpos).0) {
 | 
	
		
			
				|  |  |                                              continue;
 | 
	
		
			
				|  |  |                                          }
 | 
	
	
		
			
				|  | @@ -375,12 +408,15 @@ impl Sudoku {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // #[derive(Debug)]
 | 
	
		
			
				|  |  | +/// Define a Group of sudoku positions.
 | 
	
		
			
				|  |  | +/// This defines rows, columns, and cells for analysis.
 | 
	
		
			
				|  |  |  #[derive(PartialEq)]
 | 
	
		
			
				|  |  |  struct Group {
 | 
	
		
			
				|  |  | -    items: [u8; SIZE as usize],
 | 
	
		
			
				|  |  | +    items: [u8; WIDTH as usize],
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const ROW: [Group; 9] = [
 | 
	
		
			
				|  |  | +/// Group of positions for rows.
 | 
	
		
			
				|  |  | +const GROUP_ROW: [Group; 9] = [
 | 
	
		
			
				|  |  |      Group {
 | 
	
		
			
				|  |  |          items: [
 | 
	
		
			
				|  |  |              pos1(1, 1),
 | 
	
	
		
			
				|  | @@ -500,7 +536,8 @@ const ROW: [Group; 9] = [
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  ];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const COLUMN: [Group; 9] = [
 | 
	
		
			
				|  |  | +/// Group of positions for columns.
 | 
	
		
			
				|  |  | +const GROUP_COLUMN: [Group; 9] = [
 | 
	
		
			
				|  |  |      Group {
 | 
	
		
			
				|  |  |          items: [
 | 
	
		
			
				|  |  |              pos1(1, 1),
 | 
	
	
		
			
				|  | @@ -620,7 +657,8 @@ const COLUMN: [Group; 9] = [
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  ];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const CELL: [Group; 9] = [
 | 
	
		
			
				|  |  | +/// Group of positions for cells (3x3 grid).
 | 
	
		
			
				|  |  | +const GROUP_CELL: [Group; 9] = [
 | 
	
		
			
				|  |  |      Group {
 | 
	
		
			
				|  |  |          items: [
 | 
	
		
			
				|  |  |              pos1(1, 1),
 | 
	
	
		
			
				|  | @@ -761,15 +799,20 @@ impl fmt::Debug for Group {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  fn for_column(i: u8) -> &'static Group {
 | 
	
		
			
				|  |  | -    &COLUMN[i as usize]
 | 
	
		
			
				|  |  | +    &GROUP_COLUMN[i as usize]
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  fn for_row(i: u8) -> &'static Group {
 | 
	
		
			
				|  |  | -    &ROW[i as usize]
 | 
	
		
			
				|  |  | +    &GROUP_ROW[i as usize]
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  fn for_cell(i: u8) -> &'static Group {
 | 
	
		
			
				|  |  | -    &CELL[i as usize]
 | 
	
		
			
				|  |  | +    &GROUP_CELL[i as usize]
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/// Which cell contains this x,y?
 | 
	
		
			
				|  |  | +fn which_cell(x:u8, y:u8) -> u8 {
 | 
	
		
			
				|  |  | +    (x/3)+(y/3)*3
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #[cfg(test)]
 | 
	
	
		
			
				|  | @@ -816,17 +859,17 @@ mod tests {
 | 
	
		
			
				|  |  |  impl Group {
 | 
	
		
			
				|  |  |      fn new() -> Self {
 | 
	
		
			
				|  |  |          Group {
 | 
	
		
			
				|  |  | -            items: [0; SIZE as usize],
 | 
	
		
			
				|  |  | +            items: [0; WIDTH as usize],
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn for_column(&mut self, x: u8, _y: u8) {
 | 
	
		
			
				|  |  | -        for y in 0..SIZE {
 | 
	
		
			
				|  |  | +        for y in 0..WIDTH {
 | 
	
		
			
				|  |  |              self.items[y as usize] = pos(x, y);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      fn for_row(&mut self, _x: u8, y: u8) {
 | 
	
		
			
				|  |  | -        for x in 0..SIZE {
 | 
	
		
			
				|  |  | +        for x in 0..WIDTH {
 | 
	
		
			
				|  |  |              self.items[x as usize] = pos(x, y);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -834,7 +877,7 @@ impl Group {
 | 
	
		
			
				|  |  |          // Find starting block positions
 | 
	
		
			
				|  |  |          let sb_x = x - (x % 3);
 | 
	
		
			
				|  |  |          let sb_y = y - (y % 3);
 | 
	
		
			
				|  |  | -        for i in 0..SIZE {
 | 
	
		
			
				|  |  | +        for i in 0..WIDTH {
 | 
	
		
			
				|  |  |              let ix = i % 3;
 | 
	
		
			
				|  |  |              let iy = i / 3;
 | 
	
		
			
				|  |  |              // println!("i = {}, sb.x = {} sb.y = {}, ix = {} iy = {}", i, sb_x, sb_y, ix, iy);
 | 
	
	
		
			
				|  | @@ -849,7 +892,7 @@ impl Group {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn display(&self) {
 | 
	
		
			
				|  |  | -        for i in 0..SIZE {
 | 
	
		
			
				|  |  | +        for i in 0..WIDTH {
 | 
	
		
			
				|  |  |              let v = self.items[i as usize];
 | 
	
		
			
				|  |  |              print!("{} [{},{}] ", v, xy(v).0, xy(v).1);
 | 
	
		
			
				|  |  |          }
 |