PageRenderTime 47ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/sudoku_test.rb

https://github.com/adivik2000/sudoku
Ruby | 264 lines | 217 code | 47 blank | 0 comment | 0 complexity | c16f25719ba3663d070d8b93950bc317 MD5 | raw file
  1. require 'rubygems'
  2. require 'test/unit'
  3. require 'shoulda'
  4. require 'sudoku'
  5. class CellTest < Test::Unit::TestCase
  6. def create_group_with(cell, *numbers)
  7. g = Group.new
  8. g << cell
  9. numbers.each do |n|
  10. c = Cell.new
  11. c.number = n
  12. g << c
  13. end
  14. g
  15. end
  16. context 'a cell' do
  17. setup do
  18. @cell = Cell.new("C25")
  19. end
  20. should 'know its name' do
  21. assert_equal "C25", @cell.to_s
  22. end
  23. should 'be inspectable' do
  24. assert_equal "C25", @cell.inspect
  25. end
  26. should 'initially have no number' do
  27. assert_nil @cell.number
  28. end
  29. should 'be able to set number' do
  30. @cell.number = 4
  31. assert_equal 4, @cell.number
  32. end
  33. should 'accept a zero as no number' do
  34. @cell.number = 0
  35. assert_nil @cell.number
  36. end
  37. should 'report all numbers are available' do
  38. assert_equal( Set[*(1..9)], @cell.available_numbers )
  39. end
  40. context 'within a group' do
  41. setup do
  42. @group = create_group_with(@cell, 3, 4, 5)
  43. end
  44. should 'report available numbers not in the group' do
  45. assert_equal Set[1, 2, 6, 7, 8, 9], @cell.available_numbers
  46. end
  47. should 'report no available numbers if a number has been assigned' do
  48. @cell.number = 6
  49. assert_equal Set[], @cell.available_numbers
  50. end
  51. end
  52. end
  53. end
  54. class GroupTest < Test::Unit::TestCase
  55. context 'a group of cells' do
  56. setup do
  57. @group = Group.new
  58. end
  59. should 'exist' do
  60. assert_not_nil @group
  61. end
  62. context 'with cells' do
  63. setup do
  64. @cells = (1..10).map { |i| Cell.new("C#{i}") }
  65. @cells.each do |c| @group << c end
  66. end
  67. should 'give a list of numbers' do
  68. assert_equal Set[], @group.numbers
  69. end
  70. context 'with some numbers' do
  71. setup do
  72. @cells[0].number = 3
  73. @cells[3].number = 6
  74. end
  75. should 'give a list of the remaining missing numbers' do
  76. assert_equal [3, 6], @group.numbers.sort
  77. end
  78. end
  79. end
  80. end
  81. end
  82. module Puzzles
  83. Wiki =
  84. "53 7 " +
  85. "6 195 " +
  86. " 98 6 " +
  87. "8 6 3" +
  88. "4 8 3 1" +
  89. "7 2 6" +
  90. " 6 28 " +
  91. " 419 5" +
  92. " 8 79"
  93. Medium =
  94. " 4 7 3 " +
  95. " 85 1 " +
  96. " 15 3 9 " +
  97. "5 7 21 " +
  98. " 6 8 " +
  99. " 81 6 9" +
  100. " 2 4 57 " +
  101. " 7 29 " +
  102. " 5 7 8 "
  103. Evil =
  104. " 53 694 " +
  105. " 3 1 6" +
  106. " 3 " +
  107. "7 9 " +
  108. " 1 3 2 " +
  109. " 2 7" +
  110. " 6 " +
  111. "8 7 5 " +
  112. " 436 81 "
  113. end
  114. class BoardTest < Test::Unit::TestCase
  115. include Puzzles
  116. context 'a board' do
  117. setup do
  118. @board = Board.new
  119. end
  120. should 'be inspectable' do
  121. assert_match %r(^<Board \.{81}>$), @board.inspect
  122. end
  123. should 'initially give all 9 numbers for all cells' do
  124. @board.each do |cell|
  125. assert_equal((1..9).to_a, cell.available_numbers.sort)
  126. end
  127. end
  128. should 'parse a string representation of the puzzle' do
  129. @board.parse(Wiki)
  130. assert_equal "5 3 . . 7 . . . . \n" +
  131. "6 . . 1 9 5 . . . \n" +
  132. ". 9 8 . . . . 6 . \n\n" +
  133. "8 . . . 6 . . . 3 \n" +
  134. "4 . . 8 . 3 . . 1 \n" +
  135. "7 . . . 2 . . . 6 \n\n" +
  136. ". 6 . . . . 2 8 . \n" +
  137. ". . . 4 1 9 . . 5 \n" +
  138. ". . . . 8 . . 7 9 \n\n",
  139. @board.to_s
  140. end
  141. should 'solve the Wikipedia Puzzle' do
  142. board = Board.new.parse(Wiki)
  143. board.solve
  144. assert board.solved?
  145. assert_equal "534678912672195348198342567" +
  146. "859761423426853791713924856" +
  147. "961537284287419635345286179",
  148. board.encoding
  149. end
  150. should 'solve the Wikipedia Puzzle with DOS line endings' do
  151. board = Board.new.parse(open("puzzles/wiki_dos.sud") { |f| f.read })
  152. board.solve
  153. assert board.solved?
  154. assert_equal "534678912672195348198342567" +
  155. "859761423426853791713924856" +
  156. "961537284287419635345286179",
  157. board.encoding
  158. end
  159. should 'solve the Medium Puzzle' do
  160. board = Board.new.parse(Medium)
  161. board.solve
  162. assert board.solved?
  163. assert_equal "942187635368594127715236498" +
  164. "593478216476921853281365749" +
  165. "829643571137852964654719382",
  166. board.encoding
  167. end
  168. should 'solve the Evil Puzzle' do
  169. board = Board.new.parse(Evil)
  170. board.solve
  171. assert board.solved?
  172. assert_equal "285376941439125786176849235" +
  173. "752981364618734529394562817" +
  174. "567213498821497653943658172",
  175. board.encoding
  176. end
  177. end
  178. end
  179. class SudokuSolverTest < Test::Unit::TestCase
  180. WikiPuzzleFile = 'puzzles/wiki.sud'
  181. SOLUTION = %{5 3 4 6 7 8 9 1 2
  182. 6 7 2 1 9 5 3 4 8
  183. 1 9 8 3 4 2 5 6 7
  184. 8 5 9 7 6 1 4 2 3
  185. 4 2 6 8 5 3 7 9 1
  186. 7 1 3 9 2 4 8 5 6
  187. 9 6 1 5 3 7 2 8 4
  188. 2 8 7 4 1 9 6 3 5
  189. 3 4 5 2 8 6 1 7 9}
  190. def redirect_output
  191. old_stdout = $stdout
  192. $stdout = StringIO.new
  193. yield
  194. $stdout.string
  195. ensure
  196. $stdout = old_stdout
  197. end
  198. context 'a solver' do
  199. setup do
  200. @solver = SudokuSolver.new
  201. end
  202. should 'solve a puzzle' do
  203. result = redirect_output do
  204. @solver.run([WikiPuzzleFile])
  205. end
  206. assert_match(/#{SOLUTION}/, result)
  207. end
  208. should 'complain if no file given' do
  209. result = redirect_output do
  210. assert_raise(SystemExit) do
  211. @solver.run([])
  212. end
  213. end
  214. assert_match(/Usage:/, result)
  215. end
  216. end
  217. end