use clap::Parser; use regex::Regex; #[derive(Parser)] #[command(version, about, long_about = None)] struct Cli { // The sudoku field given as a space separated string from left to right, top to bottom, 0 denotes value // absense field: String, // Size of one size of the field. For standard 9x9 input 9 (default) #[arg(short, long)] field_size: usize, } #[derive(PartialEq, Debug, Clone)] struct Playfield { fields: Vec>, open_fields: Vec, } #[derive(Clone, PartialEq, Debug)] struct Field { possible_values: Vec, value: Option, } impl Playfield { fn new(size: usize) -> Playfield { let fields = vec![ vec![ Field { possible_values: Vec::::new(), value: None }; size ]; size ]; Self { fields, open_fields: Vec::::new(), } } } impl Field { fn new(value: u32) -> Field { Self { possible_values: Vec::::new(), value: Some(value), } } fn default() -> Field { Self { possible_values: Vec::::new(), value: None, } } } fn main() { let cli = Cli::parse(); let playfield = parse_playfield(&cli.field, cli.field_size); } fn parse_playfield(field: &String, field_size: usize) -> Playfield { let mut playfield = Playfield::new(field_size); let chars = field.split(" ").collect::>(); if !is_right_field_size(&chars, field_size) { panic!( "Input must have dimension of size {size}x{size}", size = field_size ); } for row in 0..field_size { for col in 0..field_size { let field = &mut playfield.fields[row][col]; let char_field = chars.get(row * field_size + col).unwrap(); if *char_field == "0" { continue; } field.value = Some(char_field.parse().unwrap()); } } return playfield; } fn is_right_field_size(field: &Vec<&str>, field_size: usize) -> bool { return field.len() == field_size * field_size; } #[cfg(test)] mod tests { use super::*; #[test] fn test_parse_field() { let input = "1 2 3 0 0 0 3 2 1"; let field_size = 3; let playfield = parse_playfield(&input.to_string(), field_size); assert_eq!( playfield, Playfield { fields: vec![ vec![Field::new(1), Field::new(2), Field::new(3)], vec![Field::default(), Field::default(), Field::default()], vec![Field::new(3), Field::new(2), Field::new(1)] ], open_fields: vec![] } ) } #[test] #[should_panic(expected = "Input must have dimension of size 2x2")] fn test_parse_field_too_long_input() { let input = "1 2 3 0 0 0 3 2 1"; let field_size = 2; let _ = parse_playfield(&input.to_string(), field_size); } #[test] #[should_panic(expected = "Input must have dimension of size 2x2")] fn test_parse_field_too_short_input() { let input = "1 2 3"; let field_size = 3; let _ = parse_playfield(&input.to_string(), field_size); } #[test] #[should_panic(expected = "Input must contain only digits followed by space")] fn test_parse_field_wrong_character() { let input = "1 2 3 0 0 0 3 2 a"; let field_size = 3; let _ = parse_playfield(&input.to_string(), field_size); } }