diff --git a/Cargo.toml b/Cargo.toml index bc1486b..9b9df07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,5 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dependencies] \ No newline at end of file +[dependencies] +csv = "1.1.3" \ No newline at end of file diff --git a/puzzles/challenge.csv b/puzzles/challenge.csv new file mode 100644 index 0000000..1554699 --- /dev/null +++ b/puzzles/challenge.csv @@ -0,0 +1,9 @@ +0,0,9,6,2,0,0,0,4 +0,6,0,0,0,0,0,5,0 +0,3,0,0,5,8,6,0,0 +0,0,0,4,0,0,0,0,0 +0,0,0,0,0,0,3,2,0 +0,0,7,0,0,3,0,0,0 +0,7,6,0,0,4,0,9,0 +0,9,0,0,3,0,0,7,0 +0,8,0,0,9,0,5,0,2 diff --git a/puzzles/hard.csv b/puzzles/hard.csv new file mode 100644 index 0000000..624bbc1 --- /dev/null +++ b/puzzles/hard.csv @@ -0,0 +1,10 @@ +0,0,0,8,0,0,4,0,5 +1,0,0,0,0,0,0,0,0 +9,0,0,0,5,0,1,3,0 +3,0,0,6,9,5,0,0,2 +0,0,0,0,0,0,0,0,0 +0,0,6,4,8,0,0,1,0 +0,0,0,0,1,0,3,0,9 +0,8,0,0,6,0,0,0,0 +0,0,9,3,0,0,2,8,0 + diff --git a/puzzles/template.csv b/puzzles/template.csv new file mode 100644 index 0000000..2d37099 --- /dev/null +++ b/puzzles/template.csv @@ -0,0 +1,10 @@ +0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0 + diff --git a/src/main.rs b/src/main.rs index 04ca72f..b7e7442 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use std::rc::{Rc, Weak}; use std::cell::{RefCell}; use std::collections::HashSet; +use std::str::FromStr; const DEBUG: bool = false; @@ -734,6 +735,8 @@ fn solve_line(grid: &Grid, line: &Line){ println!("Solving {:?} {}", line.line_type, line.index); } + line.do_update.replace(false); + search_single_possibility(line); if DEBUG { grid.print(); @@ -749,16 +752,17 @@ fn solve_line(grid: &Grid, line: &Line){ grid.print(); } - line.do_update.replace(false); } fn solve_grid(grid: &Grid) { 'outer: loop { + let mut ran_something = false; for (_index, line_ref) in grid.rows.iter().enumerate() { //println!("Processing row {}", _index); let line_ref = &*(&**line_ref).borrow(); if line_ref.do_update() { solve_line(&grid, line_ref); + ran_something = true; } } for (_index, line_ref) in grid.columns.iter().enumerate() { @@ -766,6 +770,7 @@ fn solve_grid(grid: &Grid) { let line_ref = &*(&**line_ref).borrow(); if line_ref.do_update() { solve_line(&grid, line_ref); + ran_something = true; } } for (_index, line_ref) in grid.sections.iter().enumerate() { @@ -773,9 +778,15 @@ fn solve_grid(grid: &Grid) { let line_ref = &*(&**line_ref).borrow(); if line_ref.do_update() { solve_line(&grid, line_ref); + ran_something = true; } } + if !ran_something{ // No lines have changed since we last analyzed them + println!("Unable to find a solution (no changes)"); + break 'outer; + } + // Check if complete or invalid let mut appears_complete = true; for x in 0..9 { @@ -804,7 +815,7 @@ fn solve_grid(grid: &Grid) { } } - +/* fn main() { let grid = Grid::new(); @@ -852,9 +863,57 @@ fn main() { solve_grid(&grid); grid.print(); println!("\n"); +} +*/ +fn main() { + let grid = read_grid().unwrap(); + grid.print(); + println!("Solving grid"); + solve_grid(&grid); + grid.print(); +} + +fn read_grid() -> Result { + let mut reader = csv::ReaderBuilder::new() + .has_headers(false) + .from_reader(std::io::stdin()); + let grid = Grid::new(); + let mut row = 0; + for result in reader.records() { + if row > 8 { + return Err("Hit row limit"); + } + + let record = result.unwrap(); + + for column in 0..9 { + let value = record.get(column); + match value { + Some(x) => { + let digit_result = u8::from_str(x); + match digit_result { + Ok(digit) => { + if digit > 0 { + grid.get(row, column).unwrap().set(digit); + } + + }, + Err(_error) => {return Err("Invalid cell value")} + }; + + }, + None => {} + } + } + + row = row + 1; + + } + + return Ok(grid); } #[test]