1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // ignore-pretty very bad with line comments
13 #![feature(box_syntax)]
14 #![allow(non_snake_case)]
16 use std::old_io::BufferedReader;
17 use std::old_io::stdio::StdReader;
19 use std::iter::repeat;
23 // Computes a single solution to a given 9x9 sudoku
25 // Call with "-" to read input sudoku from stdin
27 // The expected line-based format is:
30 // <row>,<column>,<color>
33 // Row and column are 0-based (i.e. <= 8) and color is 1-based (>=1,<=9).
34 // A color of 0 indicates an empty field.
36 // If called without arguments, sudoku solves a built-in example sudoku
39 // internal type of sudoku grids
40 type grid = Vec<Vec<u8> > ;
47 pub fn new(g: grid) -> Sudoku {
48 return Sudoku { grid: g }
51 pub fn from_vec(vec: &[[u8;9];9]) -> Sudoku {
52 let g = (0..9u).map(|i| {
53 (0..9u).map(|j| { vec[i][j] }).collect()
58 pub fn read(mut reader: &mut BufferedReader<StdReader>) -> Sudoku {
59 /* assert first line is exactly "9,9" */
60 assert!(reader.read_line().unwrap() == "9,9".to_string());
62 let mut g = repeat(vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8])
63 .take(10).collect::<Vec<_>>();
64 for line in reader.lines() {
65 let line = line.unwrap();
66 let comps: Vec<&str> = line.as_slice()
71 if comps.len() == 3u {
72 let row = comps[0].parse::<u8>().unwrap();
73 let col = comps[1].parse::<u8>().unwrap();
74 g[row as uint][col as uint] = comps[2].parse().unwrap();
77 panic!("Invalid sudoku file");
83 pub fn write(&self, writer: &mut old_io::Writer) {
85 write!(writer, "{}", self.grid[row as uint][0]);
87 write!(writer, " {}", self.grid[row as uint][col as uint]);
94 pub fn solve(&mut self) {
95 let mut work: Vec<(u8, u8)> = Vec::new(); /* queue of uncolored fields */
98 let color = self.grid[row as uint][col as uint];
100 work.push((row, col));
106 let end = work.len();
108 let (row, col) = work[ptr];
109 // is there another color to try?
110 let the_color = self.grid[row as uint][col as uint] +
112 if self.next_color(row, col, the_color) {
113 // yes: advance work list
116 // no: redo this field aft recoloring pred; unless there is none
117 if ptr == 0u { panic!("No solution found for this sudoku"); }
123 fn next_color(&mut self, row: u8, col: u8, start_color: u8) -> bool {
124 if start_color < 10u8 {
125 // colors not yet used
126 let mut avail = box Colors::new(start_color);
128 // drop colors already in use in neighbourhood
129 self.drop_colors(&mut *avail, row, col);
131 // find first remaining color that is available
132 let next = avail.next();
133 self.grid[row as uint][col as uint] = next;
136 self.grid[row as uint][col as uint] = 0u8;
140 // find colors available in neighbourhood of (row, col)
141 fn drop_colors(&mut self, avail: &mut Colors, row: u8, col: u8) {
142 for idx in 0u8..9u8 {
143 /* check same column fields */
144 avail.remove(self.grid[idx as uint][col as uint]);
145 /* check same row fields */
146 avail.remove(self.grid[row as uint][idx as uint]);
149 // check same block fields
150 let row0 = (row / 3u8) * 3u8;
151 let col0 = (col / 3u8) * 3u8;
152 for alt_row in row0..row0 + 3u8 {
153 for alt_col in col0..col0 + 3u8 {
154 avail.remove(self.grid[alt_row as uint][alt_col as uint]);
160 // Stores available colors as simple bitfield, bit 0 is always unset
163 static HEADS: u16 = (1u16 << 10) - 1; /* bits 9..0 */
166 fn new(start_color: u8) -> Colors {
167 // Sets bits 9..start_color
168 let tails = !0u16 << start_color as uint;
169 return Colors(HEADS & tails);
172 fn next(&self) -> u8 {
173 let Colors(c) = *self;
178 return val.trailing_zeros() as u8
182 fn remove(&mut self, color: u8) {
184 let Colors(val) = *self;
185 let mask = !(1u16 << color as uint);
186 *self = Colors(val & mask);
191 static DEFAULT_SUDOKU: [[u8;9];9] = [
192 /* 0 1 2 3 4 5 6 7 8 */
193 /* 0 */ [0u8, 4u8, 0u8, 6u8, 0u8, 0u8, 0u8, 3u8, 2u8],
194 /* 1 */ [0u8, 0u8, 8u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8],
195 /* 2 */ [7u8, 0u8, 0u8, 8u8, 0u8, 0u8, 0u8, 0u8, 0u8],
196 /* 3 */ [0u8, 0u8, 0u8, 5u8, 0u8, 0u8, 0u8, 0u8, 0u8],
197 /* 4 */ [0u8, 5u8, 0u8, 0u8, 0u8, 3u8, 6u8, 0u8, 0u8],
198 /* 5 */ [6u8, 8u8, 0u8, 0u8, 0u8, 0u8, 0u8, 9u8, 0u8],
199 /* 6 */ [0u8, 9u8, 5u8, 0u8, 0u8, 6u8, 0u8, 7u8, 0u8],
200 /* 7 */ [0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 6u8, 0u8],
201 /* 8 */ [4u8, 0u8, 0u8, 0u8, 0u8, 7u8, 2u8, 0u8, 3u8]
205 static DEFAULT_SOLUTION: [[u8;9];9] = [
206 /* 0 1 2 3 4 5 6 7 8 */
207 /* 0 */ [1u8, 4u8, 9u8, 6u8, 7u8, 5u8, 8u8, 3u8, 2u8],
208 /* 1 */ [5u8, 3u8, 8u8, 1u8, 2u8, 9u8, 7u8, 4u8, 6u8],
209 /* 2 */ [7u8, 2u8, 6u8, 8u8, 3u8, 4u8, 1u8, 5u8, 9u8],
210 /* 3 */ [9u8, 1u8, 4u8, 5u8, 6u8, 8u8, 3u8, 2u8, 7u8],
211 /* 4 */ [2u8, 5u8, 7u8, 4u8, 9u8, 3u8, 6u8, 1u8, 8u8],
212 /* 5 */ [6u8, 8u8, 3u8, 7u8, 1u8, 2u8, 5u8, 9u8, 4u8],
213 /* 6 */ [3u8, 9u8, 5u8, 2u8, 8u8, 6u8, 4u8, 7u8, 1u8],
214 /* 7 */ [8u8, 7u8, 2u8, 3u8, 4u8, 1u8, 9u8, 6u8, 5u8],
215 /* 8 */ [4u8, 6u8, 1u8, 9u8, 5u8, 7u8, 2u8, 8u8, 3u8]
219 fn colors_new_works() {
220 assert_eq!(*Colors::new(1), 1022u16);
221 assert_eq!(*Colors::new(2), 1020u16);
222 assert_eq!(*Colors::new(3), 1016u16);
223 assert_eq!(*Colors::new(4), 1008u16);
224 assert_eq!(*Colors::new(5), 992u16);
225 assert_eq!(*Colors::new(6), 960u16);
226 assert_eq!(*Colors::new(7), 896u16);
227 assert_eq!(*Colors::new(8), 768u16);
228 assert_eq!(*Colors::new(9), 512u16);
232 fn colors_next_works() {
233 assert_eq!(Colors(0).next(), 0u8);
234 assert_eq!(Colors(2).next(), 1u8);
235 assert_eq!(Colors(4).next(), 2u8);
236 assert_eq!(Colors(8).next(), 3u8);
237 assert_eq!(Colors(16).next(), 4u8);
238 assert_eq!(Colors(32).next(), 5u8);
239 assert_eq!(Colors(64).next(), 6u8);
240 assert_eq!(Colors(128).next(), 7u8);
241 assert_eq!(Colors(256).next(), 8u8);
242 assert_eq!(Colors(512).next(), 9u8);
243 assert_eq!(Colors(1024).next(), 0u8);
247 fn colors_remove_works() {
249 let mut colors = Colors::new(1);
255 assert_eq!(colors.next(), 2u8);
259 fn check_DEFAULT_SUDOKU_solution() {
261 let mut sudoku = Sudoku::from_vec(&DEFAULT_SUDOKU);
262 let solution = Sudoku::from_vec(&DEFAULT_SOLUTION);
268 assert!(sudoku.equal(&solution));
272 let args = os::args();
273 let use_default = args.len() == 1u;
274 let mut sudoku = if use_default {
275 Sudoku::from_vec(&DEFAULT_SUDOKU)
277 Sudoku::read(&mut *old_io::stdin().lock())
280 sudoku.write(&mut old_io::stdout());