|  | @@ -1,6 +1,7 @@
 | 
	
		
			
				|  |  |  use serde_derive::{Deserialize, Serialize};
 | 
	
		
			
				|  |  |  use serde_xml_rs::{from_reader, from_str, to_string};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +use std::fmt;
 | 
	
		
			
				|  |  |  use std::fs::File;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #[derive(Debug, Serialize, Deserialize, PartialEq)]
 | 
	
	
		
			
				|  | @@ -38,23 +39,33 @@ const MAX_SIZE: u8 = 81;
 | 
	
		
			
				|  |  |  #[derive(Debug)]
 | 
	
		
			
				|  |  |  struct Sudoku {
 | 
	
		
			
				|  |  |      board: [u8; MAX_SIZE as usize],
 | 
	
		
			
				|  |  | +    possible: [[u8; SIZE as usize]; MAX_SIZE as usize],
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// Translate x,y to position in board.
 | 
	
		
			
				|  |  |  const fn pos(x: u8, y: u8) -> u8 {
 | 
	
		
			
				|  |  |      x + (y * SIZE as u8)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// Translate post to x,y in board.
 | 
	
		
			
				|  |  | +const fn xy(pos: u8) -> (u8, u8) {
 | 
	
		
			
				|  |  | +    ((pos % SIZE), (pos / SIZE))
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  impl Sudoku {
 | 
	
		
			
				|  |  |      fn new() -> Self {
 | 
	
		
			
				|  |  |          let s = Sudoku {
 | 
	
		
			
				|  |  |              board: [0; MAX_SIZE as usize],
 | 
	
		
			
				|  |  | +            // possible: [[0; SIZE as usize]; MAX_SIZE as usize],
 | 
	
		
			
				|  |  | +            possible: [[1, 2, 3, 4, 5, 6, 7, 8, 9]; MAX_SIZE as usize],
 | 
	
		
			
				|  |  |          };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          s
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      fn clear(&mut self) {
 | 
	
		
			
				|  |  |          for x in 0..MAX_SIZE {
 | 
	
		
			
				|  |  |              self.board[x as usize] = 0;
 | 
	
		
			
				|  |  | +            self.possible[x as usize] = [1, 2, 3, 4, 5, 6, 7, 8, 9];
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -91,7 +102,7 @@ impl Sudoku {
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              println!("");
 | 
	
		
			
				|  |  |              if y % 3 == 2 {
 | 
	
		
			
				|  |  | -                if (y + 1 == SIZE) {
 | 
	
		
			
				|  |  | +                if y + 1 == SIZE {
 | 
	
		
			
				|  |  |                      println!("╚═══╩═══╩═══╝");
 | 
	
		
			
				|  |  |                  } else {
 | 
	
		
			
				|  |  |                      println!("╠═══╬═══╬═══╣");
 | 
	
	
		
			
				|  | @@ -99,82 +110,115 @@ impl Sudoku {
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fn display_possible(&self) {
 | 
	
		
			
				|  |  | +        for y in 0..SIZE {
 | 
	
		
			
				|  |  | +            for x in 0..SIZE {
 | 
	
		
			
				|  |  | +                print!("({},{}):", x, y);
 | 
	
		
			
				|  |  | +                for i in 0..SIZE {
 | 
	
		
			
				|  |  | +                    let pos = self.possible[pos(x, y) as usize][i as usize];
 | 
	
		
			
				|  |  | +                    if pos == 0 {
 | 
	
		
			
				|  |  | +                        print!(" ");
 | 
	
		
			
				|  |  | +                    } else {
 | 
	
		
			
				|  |  | +                        print!("{}", pos);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                print!(" ");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            println!("");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -/*
 | 
	
		
			
				|  |  | -const InRow: [u8; 81] = [1, 2, 3, 4, 5, 6, 7, 8, 9,
 | 
	
		
			
				|  |  | -1, 2, 3, 4, 5, 6, 7, 8, 9,
 | 
	
		
			
				|  |  | -1, 2, 3, 4, 5, 6, 7, 8, 9,
 | 
	
		
			
				|  |  | -1, 2, 3, 4, 5, 6, 7, 8, 9,
 | 
	
		
			
				|  |  | -1, 2, 3, 4, 5, 6, 7, 8, 9,
 | 
	
		
			
				|  |  | -1, 2, 3, 4, 5, 6, 7, 8, 9,
 | 
	
		
			
				|  |  | -1, 2, 3, 4, 5, 6, 7, 8, 9,
 | 
	
		
			
				|  |  | -1, 2, 3, 4, 5, 6, 7, 8, 9,
 | 
	
		
			
				|  |  | -];
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// rows, columns, and cells ?  (maybe?)
 | 
	
		
			
				|  |  | -// With the ability to know what RCC each item belongs?
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#[derive(Debug)]
 | 
	
		
			
				|  |  | -struct OnlyOne {
 | 
	
		
			
				|  |  | -    positions: [u8; SIZE as usize],
 | 
	
		
			
				|  |  | +// #[derive(Debug)]
 | 
	
		
			
				|  |  | +struct Group {
 | 
	
		
			
				|  |  | +    items: [u8; SIZE as usize],
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -const CELLS: [OnlyOne; 3] = [
 | 
	
		
			
				|  |  | -    OnlyOne {
 | 
	
		
			
				|  |  | -        positions: [
 | 
	
		
			
				|  |  | -            pos(1, 1),
 | 
	
		
			
				|  |  | -            pos(1, 2),
 | 
	
		
			
				|  |  | -            pos(1, 3),
 | 
	
		
			
				|  |  | -            pos(1, 4),
 | 
	
		
			
				|  |  | -            pos(1, 5),
 | 
	
		
			
				|  |  | -            pos(1, 6),
 | 
	
		
			
				|  |  | -            pos(1, 7),
 | 
	
		
			
				|  |  | -            pos(1, 8),
 | 
	
		
			
				|  |  | -            pos(1, 9),
 | 
	
		
			
				|  |  | -        ],
 | 
	
		
			
				|  |  | -    },
 | 
	
		
			
				|  |  | -    OnlyOne {
 | 
	
		
			
				|  |  | -        positions: [
 | 
	
		
			
				|  |  | -            pos(2, 1),
 | 
	
		
			
				|  |  | -            pos(2, 2),
 | 
	
		
			
				|  |  | -            pos(2, 3),
 | 
	
		
			
				|  |  | -            pos(2, 4),
 | 
	
		
			
				|  |  | -            pos(2, 5),
 | 
	
		
			
				|  |  | -            pos(2, 6),
 | 
	
		
			
				|  |  | -            pos(2, 7),
 | 
	
		
			
				|  |  | -            pos(2, 8),
 | 
	
		
			
				|  |  | -            pos(2, 9),
 | 
	
		
			
				|  |  | -        ],
 | 
	
		
			
				|  |  | -    },
 | 
	
		
			
				|  |  | -    OnlyOne {
 | 
	
		
			
				|  |  | -        positions: [
 | 
	
		
			
				|  |  | -            pos(3, 1),
 | 
	
		
			
				|  |  | -            pos(3, 2),
 | 
	
		
			
				|  |  | -            pos(3, 3),
 | 
	
		
			
				|  |  | -            pos(3, 4),
 | 
	
		
			
				|  |  | -            pos(3, 5),
 | 
	
		
			
				|  |  | -            pos(3, 6),
 | 
	
		
			
				|  |  | -            pos(3, 7),
 | 
	
		
			
				|  |  | -            pos(3, 8),
 | 
	
		
			
				|  |  | -            pos(3, 9),
 | 
	
		
			
				|  |  | -        ],
 | 
	
		
			
				|  |  | -    },
 | 
	
		
			
				|  |  | -];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const POS1: OnlyOne = OnlyOne {
 | 
	
		
			
				|  |  | -    positions: [0, 1, 2, 3, 4, 5, 6, 7, 8],
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | +impl fmt::Debug for Group {
 | 
	
		
			
				|  |  | +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
	
		
			
				|  |  | +        if f.alternate() {
 | 
	
		
			
				|  |  | +            write!(f, "Group {{ {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}], {}[{},{}] }}",
 | 
	
		
			
				|  |  | +                self.items[0], xy(self.items[0]).0, xy(self.items[0]).1,
 | 
	
		
			
				|  |  | +                self.items[1], xy(self.items[1]).0, xy(self.items[1]).1,
 | 
	
		
			
				|  |  | +                self.items[2], xy(self.items[2]).0, xy(self.items[2]).1,
 | 
	
		
			
				|  |  | +                self.items[3], xy(self.items[3]).0, xy(self.items[3]).1,
 | 
	
		
			
				|  |  | +                self.items[4], xy(self.items[4]).0, xy(self.items[4]).1,
 | 
	
		
			
				|  |  | +                self.items[5], xy(self.items[5]).0, xy(self.items[5]).1,
 | 
	
		
			
				|  |  | +                self.items[6], xy(self.items[6]).0, xy(self.items[6]).1,
 | 
	
		
			
				|  |  | +                self.items[7], xy(self.items[7]).0, xy(self.items[7]).1,
 | 
	
		
			
				|  |  | +                self.items[8], xy(self.items[8]).0, xy(self.items[8]).1,
 | 
	
		
			
				|  |  | +            )
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            f.debug_struct("Group").field("items", &self.items).finish()
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl Group {
 | 
	
		
			
				|  |  | +    fn new() -> Self {
 | 
	
		
			
				|  |  | +        Group {
 | 
	
		
			
				|  |  | +            items: [0; SIZE as usize],
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fn for_column(&mut self, x: u8, _y: u8) {
 | 
	
		
			
				|  |  | +        for y in 0..SIZE {
 | 
	
		
			
				|  |  | +            self.items[y as usize] = pos(x, y);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    fn for_row(&mut self, _x: u8, y: u8) {
 | 
	
		
			
				|  |  | +        for x in 0..SIZE {
 | 
	
		
			
				|  |  | +            self.items[x as usize] = pos(x, y);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    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..SIZE {
 | 
	
		
			
				|  |  | +            let ix = i % 3;
 | 
	
		
			
				|  |  | +            let iy = i / 3;
 | 
	
		
			
				|  |  | +            // println!("i = {}, sb.x = {} sb.y = {}, ix = {} iy = {}", i, sb_x, sb_y, ix, iy);
 | 
	
		
			
				|  |  | +            self.items[i as usize] = pos(sb_x + ix, sb_y + iy);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fn display(&self) {
 | 
	
		
			
				|  |  | +        for i in 0..SIZE {
 | 
	
		
			
				|  |  | +            let v = self.items[i as usize];
 | 
	
		
			
				|  |  | +            print!("{} [{},{}] ", v, xy(v).0, xy(v).1);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        println!("");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  fn main() {
 | 
	
		
			
				|  |  |      let filename = "../puzzle1";
 | 
	
		
			
				|  |  |      let fh = File::open(filename).unwrap();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      let puzzle: Ksudoku = from_reader(fh).unwrap();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      println!("Puzzle: {:?}", puzzle);
 | 
	
		
			
				|  |  | -    println!("CELLS: {:?}", CELLS);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      let mut s = Sudoku::new();
 | 
	
		
			
				|  |  |      s.load_xsudoku(&puzzle.game.puzzle.values);
 | 
	
		
			
				|  |  |      s.display();
 | 
	
		
			
				|  |  | +    s.display_possible();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let mut g = Group::new();
 | 
	
		
			
				|  |  | +    g.for_row(1, 1);
 | 
	
		
			
				|  |  | +    print!("Row: ");
 | 
	
		
			
				|  |  | +    println!("{:?}", g);
 | 
	
		
			
				|  |  | +    println!("{:#?}", g);
 | 
	
		
			
				|  |  | +    // g.display();
 | 
	
		
			
				|  |  | +    print!("Col: ");
 | 
	
		
			
				|  |  | +    g.for_column(1, 1);
 | 
	
		
			
				|  |  | +    println!("{:?}", g);
 | 
	
		
			
				|  |  | +    // g.display();
 | 
	
		
			
				|  |  | +    println!("Blk testing output: ");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    for i in 0..SIZE {
 | 
	
		
			
				|  |  | +        g.for_block(i, i);
 | 
	
		
			
				|  |  | +        println!("({},{} {:#?})", i, i, g);
 | 
	
		
			
				|  |  | +        // g.display();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 |