/sudoku_test.rb
Ruby | 264 lines | 217 code | 47 blank | 0 comment | 0 complexity | c16f25719ba3663d070d8b93950bc317 MD5 | raw file
- require 'rubygems'
- require 'test/unit'
- require 'shoulda'
- require 'sudoku'
- class CellTest < Test::Unit::TestCase
- def create_group_with(cell, *numbers)
- g = Group.new
- g << cell
- numbers.each do |n|
- c = Cell.new
- c.number = n
- g << c
- end
- g
- end
- context 'a cell' do
- setup do
- @cell = Cell.new("C25")
- end
- should 'know its name' do
- assert_equal "C25", @cell.to_s
- end
- should 'be inspectable' do
- assert_equal "C25", @cell.inspect
- end
- should 'initially have no number' do
- assert_nil @cell.number
- end
- should 'be able to set number' do
- @cell.number = 4
- assert_equal 4, @cell.number
- end
- should 'accept a zero as no number' do
- @cell.number = 0
- assert_nil @cell.number
- end
- should 'report all numbers are available' do
- assert_equal( Set[*(1..9)], @cell.available_numbers )
- end
- context 'within a group' do
- setup do
- @group = create_group_with(@cell, 3, 4, 5)
- end
- should 'report available numbers not in the group' do
- assert_equal Set[1, 2, 6, 7, 8, 9], @cell.available_numbers
- end
- should 'report no available numbers if a number has been assigned' do
- @cell.number = 6
- assert_equal Set[], @cell.available_numbers
- end
- end
- end
- end
- class GroupTest < Test::Unit::TestCase
- context 'a group of cells' do
- setup do
- @group = Group.new
- end
-
- should 'exist' do
- assert_not_nil @group
- end
- context 'with cells' do
- setup do
- @cells = (1..10).map { |i| Cell.new("C#{i}") }
- @cells.each do |c| @group << c end
- end
- should 'give a list of numbers' do
- assert_equal Set[], @group.numbers
- end
- context 'with some numbers' do
- setup do
- @cells[0].number = 3
- @cells[3].number = 6
- end
- should 'give a list of the remaining missing numbers' do
- assert_equal [3, 6], @group.numbers.sort
- end
- end
- end
- end
- end
- module Puzzles
- Wiki =
- "53 7 " +
- "6 195 " +
- " 98 6 " +
- "8 6 3" +
- "4 8 3 1" +
- "7 2 6" +
- " 6 28 " +
- " 419 5" +
- " 8 79"
- Medium =
- " 4 7 3 " +
- " 85 1 " +
- " 15 3 9 " +
- "5 7 21 " +
- " 6 8 " +
- " 81 6 9" +
- " 2 4 57 " +
- " 7 29 " +
- " 5 7 8 "
-
- Evil =
- " 53 694 " +
- " 3 1 6" +
- " 3 " +
- "7 9 " +
- " 1 3 2 " +
- " 2 7" +
- " 6 " +
- "8 7 5 " +
- " 436 81 "
- end
- class BoardTest < Test::Unit::TestCase
- include Puzzles
- context 'a board' do
- setup do
- @board = Board.new
- end
- should 'be inspectable' do
- assert_match %r(^<Board \.{81}>$), @board.inspect
- end
- should 'initially give all 9 numbers for all cells' do
- @board.each do |cell|
- assert_equal((1..9).to_a, cell.available_numbers.sort)
- end
- end
- should 'parse a string representation of the puzzle' do
- @board.parse(Wiki)
- assert_equal "5 3 . . 7 . . . . \n" +
- "6 . . 1 9 5 . . . \n" +
- ". 9 8 . . . . 6 . \n\n" +
- "8 . . . 6 . . . 3 \n" +
- "4 . . 8 . 3 . . 1 \n" +
- "7 . . . 2 . . . 6 \n\n" +
- ". 6 . . . . 2 8 . \n" +
- ". . . 4 1 9 . . 5 \n" +
- ". . . . 8 . . 7 9 \n\n",
- @board.to_s
- end
- should 'solve the Wikipedia Puzzle' do
- board = Board.new.parse(Wiki)
- board.solve
- assert board.solved?
- assert_equal "534678912672195348198342567" +
- "859761423426853791713924856" +
- "961537284287419635345286179",
- board.encoding
- end
- should 'solve the Wikipedia Puzzle with DOS line endings' do
- board = Board.new.parse(open("puzzles/wiki_dos.sud") { |f| f.read })
- board.solve
- assert board.solved?
- assert_equal "534678912672195348198342567" +
- "859761423426853791713924856" +
- "961537284287419635345286179",
- board.encoding
- end
- should 'solve the Medium Puzzle' do
- board = Board.new.parse(Medium)
- board.solve
- assert board.solved?
- assert_equal "942187635368594127715236498" +
- "593478216476921853281365749" +
- "829643571137852964654719382",
- board.encoding
- end
- should 'solve the Evil Puzzle' do
- board = Board.new.parse(Evil)
- board.solve
- assert board.solved?
- assert_equal "285376941439125786176849235" +
- "752981364618734529394562817" +
- "567213498821497653943658172",
- board.encoding
- end
- end
- end
- class SudokuSolverTest < Test::Unit::TestCase
- WikiPuzzleFile = 'puzzles/wiki.sud'
- SOLUTION = %{5 3 4 6 7 8 9 1 2
- 6 7 2 1 9 5 3 4 8
- 1 9 8 3 4 2 5 6 7
- 8 5 9 7 6 1 4 2 3
- 4 2 6 8 5 3 7 9 1
- 7 1 3 9 2 4 8 5 6
- 9 6 1 5 3 7 2 8 4
- 2 8 7 4 1 9 6 3 5
- 3 4 5 2 8 6 1 7 9}
-
- def redirect_output
- old_stdout = $stdout
- $stdout = StringIO.new
- yield
- $stdout.string
- ensure
- $stdout = old_stdout
- end
- context 'a solver' do
- setup do
- @solver = SudokuSolver.new
- end
- should 'solve a puzzle' do
- result = redirect_output do
- @solver.run([WikiPuzzleFile])
- end
- assert_match(/#{SOLUTION}/, result)
- end
- should 'complain if no file given' do
- result = redirect_output do
- assert_raise(SystemExit) do
- @solver.run([])
- end
- end
- assert_match(/Usage:/, result)
- end
- end
- end