Created
October 7, 2022 16:27
-
-
Save hskang9/d93928eb7e18d21d5cb2c9738708a229 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::io::{Error, ErrorKind}; | |
use std::str::FromStr; | |
use std::collections::HashSet; | |
use std::convert::TryInto; | |
const WIDTH : usize = 9; | |
const GRID_SIZE : usize = WIDTH * WIDTH; | |
#[derive(Debug, PartialEq)] | |
struct Sudoku { | |
pub grid: [i32; GRID_SIZE], | |
} | |
impl Sudoku { | |
pub fn new(grid : [i32; GRID_SIZE]) -> Sudoku { | |
Sudoku { | |
grid | |
} | |
} | |
pub fn get_row_iter(&self, idx: usize) -> impl Iterator<Item = &i32> { | |
let slice = &self.grid[WIDTH * idx ..]; | |
slice.iter().take(WIDTH) | |
} | |
pub fn get_col_iter(&self, idx: usize) -> impl Iterator<Item = &i32> { | |
let slice = &self.grid[idx..]; | |
slice.iter().step_by(WIDTH) | |
} | |
pub fn get_square_iter(&self, idx: usize) -> impl Iterator<Item = &i32> { | |
let idx1 = (idx / 3) * 3 * WIDTH + (idx % 3) * 3; | |
let idx2 = idx1 + WIDTH; | |
let idx3 = idx2 + WIDTH; | |
let it1 = self.grid[idx1..].iter().take(3); | |
let it2 = self.grid[idx2..].iter().take(3); | |
let it3 = self.grid[idx3..].iter().take(3); | |
it1.chain(it2.chain(it3)) | |
} | |
pub fn as_rows(&self) -> Vec<impl Iterator<Item = &i32>> { | |
let v : Vec<usize> = (0..WIDTH).collect(); | |
v.iter().map( |&i| self.get_row_iter(i) ).collect() | |
} | |
pub fn as_cols(&self) -> Vec<impl Iterator<Item = &i32>> { | |
let v : Vec<usize> = (0..WIDTH).collect(); | |
v.iter().map( |&i| self.get_col_iter(i) ).collect() | |
} | |
pub fn as_squares(&self) -> Vec<impl Iterator<Item = &i32>> { | |
let v : Vec<usize> = (0..WIDTH).collect(); | |
v.iter().map( |&i| self.get_square_iter(i) ).collect() | |
} | |
fn is_section_complete<'a> (it : impl Iterator<Item = &'a i32>) -> bool { | |
static VALUES : [i32; WIDTH] = [1,2,3,4,5,6,7,8,9]; | |
let set1 : HashSet<&i32> = VALUES.iter().collect(); | |
let set2 : HashSet<&i32> = it.collect(); | |
set1 == set2 | |
} | |
pub fn valid(&self) -> bool { | |
for row in self.as_rows() { | |
if !Sudoku::is_section_complete(row) { return false } | |
} | |
for col in self.as_cols() { | |
if !Sudoku::is_section_complete(col) { return false } | |
} | |
for sqr in self.as_squares() { | |
if !Sudoku::is_section_complete(sqr) { return false } | |
} | |
true | |
} | |
} | |
impl FromStr for Sudoku { | |
type Err = Error; | |
fn from_str(s: &str) -> Result<Self, Self::Err> { | |
let mut grid = vec![]; | |
let rows = s.split("\n").collect::<Vec<&str>>(); | |
for row in rows { | |
if row.len() != WIDTH { | |
return Err(Error::new(ErrorKind::InvalidData, "Invalid row length")); | |
} else { | |
for c in row.chars() { | |
if !c.is_digit(10) { | |
return Err(Error::new(ErrorKind::InvalidData, "Invalid number")); | |
} | |
grid.push(c.to_digit(10).unwrap() as i32); | |
} | |
} | |
} | |
println!("{:?} {}", grid, grid.len()); | |
let grid_slice: [i32; GRID_SIZE] = grid[..GRID_SIZE].try_into().unwrap(); | |
println!("{:?}", grid_slice); | |
Ok(Sudoku::new(grid_slice)) | |
} | |
} | |
fn main () { | |
let s: Sudoku = "123456789\n\ | |
456789123\n\ | |
789123456\n\ | |
234567891\n\ | |
567891234\n\ | |
891234567\n\ | |
345678912\n\ | |
678912345\n\ | |
912345678".parse().unwrap(); | |
println!("{:?}", s); | |
println!("{}", s.valid()); | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
#[test] | |
fn test_validate_sudoku() { | |
let sudoku: Sudoku = "534678912\n\ | |
672195348\n\ | |
198342567\n\ | |
859761423\n\ | |
426853791\n\ | |
713924856\n\ | |
961537284\n\ | |
287419635\n\ | |
345286179" | |
.parse() | |
.unwrap(); | |
assert!(sudoku.valid()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment