|
@@ -2,6 +2,7 @@
|
|
use crate::group::*;
|
|
use crate::group::*;
|
|
|
|
|
|
use std::collections::HashSet;
|
|
use std::collections::HashSet;
|
|
|
|
+use std::string::String;
|
|
|
|
|
|
/// Width of the sudoku board.
|
|
/// Width of the sudoku board.
|
|
const WIDTH: u8 = 9;
|
|
const WIDTH: u8 = 9;
|
|
@@ -67,15 +68,17 @@ impl Sudoku {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn load_from(&mut self, s: &str) {
|
|
|
|
|
|
+ /// Load puzzle from a string.
|
|
|
|
+ /// Note, we load from (top,left), to (bottom,left) by columns.
|
|
|
|
+ pub fn load_from_tld(&mut self, start_ch: char, blank: char, s: &str) {
|
|
self.clear();
|
|
self.clear();
|
|
let mut x: u8 = 0;
|
|
let mut x: u8 = 0;
|
|
let mut y: u8 = 0;
|
|
let mut y: u8 = 0;
|
|
|
|
+
|
|
for ch in s.chars() {
|
|
for ch in s.chars() {
|
|
- if ch >= 'b' {
|
|
|
|
- self.set(x, y, ch as u8 - 'a' as u8);
|
|
|
|
- // self.board[pos(x, y) as usize] = ch as u8 - 'a' as u8;
|
|
|
|
- };
|
|
|
|
|
|
+ if ch != blank {
|
|
|
|
+ self.set(x,y, (ch as u8-start_ch as u8) +1);
|
|
|
|
+ }
|
|
y += 1;
|
|
y += 1;
|
|
if y >= WIDTH {
|
|
if y >= WIDTH {
|
|
y = 0;
|
|
y = 0;
|
|
@@ -84,6 +87,55 @@ impl Sudoku {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /// Load puzzle from a string.
|
|
|
|
+ /// This loads from (top,left) to (top,right), by rows.
|
|
|
|
+ pub fn load_from_tlr(&mut self, start_ch: char, blank: char, s: &str) {
|
|
|
|
+ self.clear();
|
|
|
|
+ let mut i: u8 = 0;
|
|
|
|
+
|
|
|
|
+ for ch in s.chars() {
|
|
|
|
+ if ch != blank {
|
|
|
|
+ self.set(xy(i).0, xy(i).1, (ch as u8-start_ch as u8) +1);
|
|
|
|
+ }
|
|
|
|
+ i += 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn save_to_tld(&self, mut start_ch:char, blank: char) -> String {
|
|
|
|
+ let mut result = String::new();
|
|
|
|
+ result.reserve(MAX_SIZE as usize);
|
|
|
|
+ start_ch = (start_ch as u8 -1) as char;
|
|
|
|
+ let mut x:u8 = 0;
|
|
|
|
+ let mut y:u8 = 0;
|
|
|
|
+
|
|
|
|
+ for i in 0..MAX_SIZE {
|
|
|
|
+ if self.board[pos(x,y) as usize] == 0 {
|
|
|
|
+ result.push(blank);
|
|
|
|
+ } else {
|
|
|
|
+ result.push((start_ch as u8 + self.board[i as usize]) as char);
|
|
|
|
+ }
|
|
|
|
+ y += 1;
|
|
|
|
+ if y >= WIDTH {
|
|
|
|
+ y = 0;
|
|
|
|
+ x +=1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ result
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn save_to_tlr(&self, mut start_ch:char, blank: char) -> String {
|
|
|
|
+ let mut result = String::new();
|
|
|
|
+ result.reserve(MAX_SIZE as usize);
|
|
|
|
+ start_ch = (start_ch as u8 -1) as char;
|
|
|
|
+ for i in 0..MAX_SIZE {
|
|
|
|
+ if self.board[i as usize] == 0 {
|
|
|
|
+ result.push(blank);
|
|
|
|
+ } else {
|
|
|
|
+ result.push((start_ch as u8 + self.board[i as usize]) as char);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ result
|
|
|
|
+ }
|
|
pub fn set(&mut self, x: u8, y: u8, value: u8) {
|
|
pub fn set(&mut self, x: u8, y: u8, value: u8) {
|
|
self.board[pos(x, y) as usize] = value;
|
|
self.board[pos(x, y) as usize] = value;
|
|
// Ok, update the possible
|
|
// Ok, update the possible
|