use std::fmt; // load sudoku use crate::*; /// Width of the sudoku board. const WIDTH: u8 = 9; // /// Size (width * height) of the board. // const MAX_SIZE: u8 = 81; // #[derive(Debug)] /// Define a Group of sudoku positions. /// This defines rows, columns, and cells for analysis. #[derive(PartialEq)] pub struct Group(pub [u8; WIDTH as usize]); /* pub struct Group { pub items: [u8; WIDTH as usize], } */ /// Group of positions for rows. const GROUP_ROW: [Group; 9] = [ Group([ pos1(1, 1), pos1(2, 1), pos1(3, 1), pos1(4, 1), pos1(5, 1), pos1(6, 1), pos1(7, 1), pos1(8, 1), pos1(9, 1), ]), Group([ pos1(1, 2), pos1(2, 2), pos1(3, 2), pos1(4, 2), pos1(5, 2), pos1(6, 2), pos1(7, 2), pos1(8, 2), pos1(9, 2), ]), Group([ pos1(1, 3), pos1(2, 3), pos1(3, 3), pos1(4, 3), pos1(5, 3), pos1(6, 3), pos1(7, 3), pos1(8, 3), pos1(9, 3), ]), Group([ pos1(1, 4), pos1(2, 4), pos1(3, 4), pos1(4, 4), pos1(5, 4), pos1(6, 4), pos1(7, 4), pos1(8, 4), pos1(9, 4), ]), Group([ pos1(1, 5), pos1(2, 5), pos1(3, 5), pos1(4, 5), pos1(5, 5), pos1(6, 5), pos1(7, 5), pos1(8, 5), pos1(9, 5), ]), Group([ pos1(1, 6), pos1(2, 6), pos1(3, 6), pos1(4, 6), pos1(5, 6), pos1(6, 6), pos1(7, 6), pos1(8, 6), pos1(9, 6), ]), Group([ pos1(1, 7), pos1(2, 7), pos1(3, 7), pos1(4, 7), pos1(5, 7), pos1(6, 7), pos1(7, 7), pos1(8, 7), pos1(9, 7), ]), Group([ pos1(1, 8), pos1(2, 8), pos1(3, 8), pos1(4, 8), pos1(5, 8), pos1(6, 8), pos1(7, 8), pos1(8, 8), pos1(9, 8), ]), Group([ pos1(1, 9), pos1(2, 9), pos1(3, 9), pos1(4, 9), pos1(5, 9), pos1(6, 9), pos1(7, 9), pos1(8, 9), pos1(9, 9), ]), ]; /// Group of positions for columns. const GROUP_COLUMN: [Group; 9] = [ Group([ pos1(1, 1), pos1(1, 2), pos1(1, 3), pos1(1, 4), pos1(1, 5), pos1(1, 6), pos1(1, 7), pos1(1, 8), pos1(1, 9), ]), Group([ pos1(2, 1), pos1(2, 2), pos1(2, 3), pos1(2, 4), pos1(2, 5), pos1(2, 6), pos1(2, 7), pos1(2, 8), pos1(2, 9), ]), Group([ pos1(3, 1), pos1(3, 2), pos1(3, 3), pos1(3, 4), pos1(3, 5), pos1(3, 6), pos1(3, 7), pos1(3, 8), pos1(3, 9), ]), Group([ pos1(4, 1), pos1(4, 2), pos1(4, 3), pos1(4, 4), pos1(4, 5), pos1(4, 6), pos1(4, 7), pos1(4, 8), pos1(4, 9), ]), Group([ pos1(5, 1), pos1(5, 2), pos1(5, 3), pos1(5, 4), pos1(5, 5), pos1(5, 6), pos1(5, 7), pos1(5, 8), pos1(5, 9), ]), Group([ pos1(6, 1), pos1(6, 2), pos1(6, 3), pos1(6, 4), pos1(6, 5), pos1(6, 6), pos1(6, 7), pos1(6, 8), pos1(6, 9), ]), Group([ pos1(7, 1), pos1(7, 2), pos1(7, 3), pos1(7, 4), pos1(7, 5), pos1(7, 6), pos1(7, 7), pos1(7, 8), pos1(7, 9), ]), Group([ pos1(8, 1), pos1(8, 2), pos1(8, 3), pos1(8, 4), pos1(8, 5), pos1(8, 6), pos1(8, 7), pos1(8, 8), pos1(8, 9), ]), Group([ pos1(9, 1), pos1(9, 2), pos1(9, 3), pos1(9, 4), pos1(9, 5), pos1(9, 6), pos1(9, 7), pos1(9, 8), pos1(9, 9), ]), ]; /// Group of positions for cells (3x3 grid). const GROUP_CELL: [Group; 9] = [ Group([ pos1(1, 1), pos1(2, 1), pos1(3, 1), pos1(1, 2), pos1(2, 2), pos1(3, 2), pos1(1, 3), pos1(2, 3), pos1(3, 3), ]), Group([ pos1(4, 1), pos1(5, 1), pos1(6, 1), pos1(4, 2), pos1(5, 2), pos1(6, 2), pos1(4, 3), pos1(5, 3), pos1(6, 3), ]), Group([ pos1(7, 1), pos1(8, 1), pos1(9, 1), pos1(7, 2), pos1(8, 2), pos1(9, 2), pos1(7, 3), pos1(8, 3), pos1(9, 3), ]), Group([ pos1(1, 4), pos1(2, 4), pos1(3, 4), pos1(1, 5), pos1(2, 5), pos1(3, 5), pos1(1, 6), pos1(2, 6), pos1(3, 6), ]), Group([ pos1(4, 4), pos1(5, 4), pos1(6, 4), pos1(4, 5), pos1(5, 5), pos1(6, 5), pos1(4, 6), pos1(5, 6), pos1(6, 6), ]), Group([ pos1(7, 4), pos1(8, 4), pos1(9, 4), pos1(7, 5), pos1(8, 5), pos1(9, 5), pos1(7, 6), pos1(8, 6), pos1(9, 6), ]), Group([ pos1(1, 7), pos1(2, 7), pos1(3, 7), pos1(1, 8), pos1(2, 8), pos1(3, 8), pos1(1, 9), pos1(2, 9), pos1(3, 9), ]), Group([ pos1(4, 7), pos1(5, 7), pos1(6, 7), pos1(4, 8), pos1(5, 8), pos1(6, 8), pos1(4, 9), pos1(5, 9), pos1(6, 9), ]), Group([ pos1(7, 7), pos1(8, 7), pos1(9, 7), pos1(7, 8), pos1(8, 8), pos1(9, 8), pos1(7, 9), pos1(8, 9), pos1(9, 9), ]), ]; impl fmt::Debug for Group { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if f.alternate() { write!(f, "Group {{ {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}] }}", self.0[0], xy(self.0[0]).0, xy(self.0[0]).1, self.0[1], xy(self.0[1]).0, xy(self.0[1]).1, self.0[2], xy(self.0[2]).0, xy(self.0[2]).1, self.0[3], xy(self.0[3]).0, xy(self.0[3]).1, self.0[4], xy(self.0[4]).0, xy(self.0[4]).1, self.0[5], xy(self.0[5]).0, xy(self.0[5]).1, self.0[6], xy(self.0[6]).0, xy(self.0[6]).1, self.0[7], xy(self.0[7]).0, xy(self.0[7]).1, self.0[8], xy(self.0[8]).0, xy(self.0[8]).1, ) } else { f.debug_struct("Group").field("items", &self).finish() } } } pub fn for_column(x: u8) -> &'static Group { &GROUP_COLUMN[x as usize] } pub fn for_row(y: u8) -> &'static Group { &GROUP_ROW[y as usize] } pub fn for_cell(i: u8) -> &'static Group { &GROUP_CELL[i as usize] } /// Which cell contains this x,y? pub fn which_cell(x: u8, y: u8) -> u8 { (x / 3) + (y / 3) * 3 } #[cfg(test)] mod tests { // use crate::sudoku::*; use crate::group::*; // use crate::sudoku::group::*; // use crate::Group; // use group::*; // use crate::{for_cell, for_column, for_row}; #[test] fn check_columns() { let mut g = Group::new(); for i in 0..9 { println!("Index={}", i); g.for_column(i, 1); let new_g = for_column(i); assert_eq!(g, *new_g); } } #[test] fn check_rows() { let mut g = Group::new(); for i in 0..9 { println!("Index={}", i); g.for_row(1, i); let new_g = for_row(i); assert_eq!(g, *new_g); } } #[test] fn check_cells() { let mut g = Group::new(); for i in 0..9 { println!("Index={}", i); g.for_block((i % 3) * 3, (i / 3) * 3); let new_g = for_cell(i); assert_eq!(g, *new_g); } } } impl Group { pub fn new() -> Self { Group([0; WIDTH as usize]) } pub fn for_column(&mut self, x: u8, _y: u8) { for y in 0..WIDTH { self.0[y as usize] = pos(x, y); } } pub fn for_row(&mut self, _x: u8, y: u8) { for x in 0..WIDTH { self.0[x as usize] = pos(x, y); } } pub fn for_block(&mut self, x: u8, y: u8) { // Find starting block positions let sb_x = x - (x % 3); let sb_y = y - (y % 3); 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); self.0[i as usize] = pos(sb_x + ix, sb_y + iy); } } pub fn for_iter(&mut self, i: u8) { let sb_x = (i % 3) * 3; let sb_y = (i / 3) * 3; self.for_block(sb_x, sb_y); } pub fn display(&self) { for i in 0..WIDTH { let v = self.0[i as usize]; print!("{} [{},{}] ", v, xy(v).0, xy(v).1); } println!(""); } }