Parse sudoku boards from strings
This commit is contained in:
		
							parent
							
								
									3136a94793
								
							
						
					
					
						commit
						d573aad4f2
					
				
					 3 changed files with 104 additions and 3 deletions
				
			
		
							
								
								
									
										62
									
								
								spec/parse_spec.cr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								spec/parse_spec.cr
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | ||||||
|  | require "./spec_helper" | ||||||
|  | 
 | ||||||
|  | describe Sudoku::Parser do | ||||||
|  | 
 | ||||||
|  |   it "should parse an empty board" do | ||||||
|  |     board_string = "....\n....\n....\n...." | ||||||
|  |     board = Sudoku::Parser.parse(board_string, block_size: 2) | ||||||
|  |     board.size.should eq 4 | ||||||
|  |     board.block_size.should eq 2 | ||||||
|  | 
 | ||||||
|  |     (0..3).each { |x| | ||||||
|  |       (0..3).each { |y| | ||||||
|  |         board.get(x, y).should eq nil | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   it "should raise an exception if number of rows and colums is different" do | ||||||
|  |     expect_raises(Sudoku::ParseException) do | ||||||
|  |       Sudoku::Parser.parse("....\n....", block_size: 2) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   it "should put numbers correctly on the board" do | ||||||
|  |     board_string = "1...\n.2..\n..3.\n...4" | ||||||
|  |     board = Sudoku::Parser.parse(board_string, block_size: 2) | ||||||
|  | 
 | ||||||
|  |     board.get(0,0).should eq 1 | ||||||
|  |     board.get(1,1).should eq 2 | ||||||
|  |     board.get(2,2).should eq 3 | ||||||
|  |     board.get(3,3).should eq 4 | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   it "should raise an exception if a cell contains a character that is not a number or a dot" do | ||||||
|  |     expect_raises(Sudoku::ParseException) do | ||||||
|  |       Sudoku::Parser.parse(".A..\n....\n....\n....", block_size: 2) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   it "should parse 9x9 boards correctly" do | ||||||
|  |     board_string = | ||||||
|  |     "8........\n" \ | ||||||
|  |     "..36.....\n" \ | ||||||
|  |     ".7..9.2..\n" \ | ||||||
|  |     ".5...7...\n" \ | ||||||
|  |     "....457..\n" \ | ||||||
|  |     "...1...3.\n" \ | ||||||
|  |     "..1....68\n" \ | ||||||
|  |     "..85...1.\n" \ | ||||||
|  |     ".9....4.." | ||||||
|  | 
 | ||||||
|  |     board = Sudoku::Parser.parse(board_string, block_size: 3) | ||||||
|  | 
 | ||||||
|  |     board.get(0,0).should eq 8 | ||||||
|  |     board.get(2,1).should eq 3 | ||||||
|  |     board.get(3,1).should eq 6 | ||||||
|  |     board.get(1,2).should eq 7 | ||||||
|  |     board.get(4,2).should eq 9 | ||||||
|  |     board.get(8,8).should eq nil | ||||||
|  |   end | ||||||
|  |    | ||||||
|  | end | ||||||
|  | @ -11,8 +11,13 @@ module Sudoku | ||||||
|     @grid : Array(Array(Value)) |     @grid : Array(Array(Value)) | ||||||
|     getter grid |     getter grid | ||||||
|      |      | ||||||
|  |     getter size | ||||||
|  |     getter block_size | ||||||
|  | 
 | ||||||
|     def initialize(@size : Int32, @block_size : Int32) |     def initialize(@size : Int32, @block_size : Int32) | ||||||
|       raise BoardException.new() unless @size.divisible_by?(@block_size) |       if !@size.divisible_by?(@block_size) | ||||||
|  |         raise BoardException.new("Invalid block size: #{@block_size} for board size: #{@size}") | ||||||
|  |       end | ||||||
|       @grid = Array(Array(Value)).new(@size) { Array(Value).new(@size, nil) } |       @grid = Array(Array(Value)).new(@size) { Array(Value).new(@size, nil) } | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,41 @@ | ||||||
| module Sudoku | module Sudoku | ||||||
|   # Parse a sudoku board from a string. Return a board. | 
 | ||||||
|  |   class ParseException < Exception | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   class Parser |   class Parser | ||||||
|     def self.parse(board_str) | 
 | ||||||
|  |     # Parse a sudoku board from a string. Return a board. | ||||||
|  |     # The string must contain valid board rows. Each row must be separated by a newline. | ||||||
|  |     # Blanks are represented by dots. | ||||||
|  |     # E.g.: | ||||||
|  |     # .1.2 | ||||||
|  |     # 2..4 | ||||||
|  |     # .3.. | ||||||
|  |     # .... | ||||||
|  |     def self.parse(board_str, block_size) | ||||||
|  |       rows = board_str.split('\n') | ||||||
|  |       board_size = rows.size | ||||||
|  |       board = Sudoku::Board.new(board_size, block_size) | ||||||
|  | 
 | ||||||
|  |       rows.each_with_index { |row, y| | ||||||
|  |         if row.size != board_size | ||||||
|  |           raise ParseException.new("Invalid row size: #{row.size} for row: #{row}") | ||||||
|  |         end | ||||||
|  | 
 | ||||||
|  |         row.each_char_with_index { |c, x| | ||||||
|  |           case c | ||||||
|  |           when '.' | ||||||
|  |             board.put(nil, x, y) | ||||||
|  |           when .number? | ||||||
|  |             board.put(c.to_s.to_i, x, y) | ||||||
|  |           else | ||||||
|  |             raise ParseException.new("Invalid character: #{c}") | ||||||
|  |           end | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       board | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue