sudoku_solver_iterative.jl 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #!/usr/bin/julia
  2. # Author: Trizen
  3. # Date: 12 February 2024
  4. # https://github.com/trizen
  5. # Solve Sudoku puzzle (iterative solution), if it has a unique solution.
  6. function is_valid(board, row, col, num)
  7. # Check if the number is not present in the current row and column
  8. for i in 1:9
  9. if (board[row][i] == num) || (board[i][col] == num)
  10. return false
  11. end
  12. end
  13. # Check if the number is not present in the current 3x3 subgrid
  14. start_row, start_col = 3*div(row-1, 3), 3*div(col-1, 3)
  15. for i in 1:3, j in 1:3
  16. if board[start_row + i][start_col + j] == num
  17. return false
  18. end
  19. end
  20. return true
  21. end
  22. function find_empty_locations(board)
  23. positions = []
  24. # Find all empty positions (cells with 0)
  25. for i in 1:9, j in 1:9
  26. if board[i][j] == 0
  27. push!(positions, [i, j])
  28. end
  29. end
  30. return positions
  31. end
  32. function find_empty_location(board)
  33. # Find an empty positions (cell with 0)
  34. for i in 1:9, j in 1:9
  35. if board[i][j] == 0
  36. return [i,j]
  37. end
  38. end
  39. return (nothing, nothing)
  40. end
  41. function solve_sudoku_fallback(board)
  42. row, col = find_empty_location(board)
  43. if (row == nothing && col == nothing)
  44. return true # Puzzle is solved
  45. end
  46. for num in 1:9
  47. if is_valid(board, row, col, num)
  48. # Try placing the number
  49. board[row][col] = num
  50. # Recursively try to solve the rest of the puzzle
  51. if solve_sudoku_fallback(board)
  52. return true
  53. end
  54. # If placing the current number doesn't lead to a solution, backtrack
  55. board[row][col] = 0
  56. end
  57. end
  58. return false # No solution found
  59. end
  60. function solve_sudoku(board)
  61. while true
  62. empty_locations = find_empty_locations(board)
  63. if length(empty_locations) == 0
  64. break # it's solved
  65. end
  66. found = false
  67. # Solve easy cases
  68. for (i,j) in empty_locations
  69. count = 0
  70. value = 0
  71. for n in 1:9
  72. if is_valid(board, i, j, n)
  73. count += 1
  74. value = n
  75. count > 1 && break
  76. end
  77. end
  78. if count == 1
  79. board[i][j] = value
  80. found = true
  81. end
  82. end
  83. found && continue
  84. # Solve more complex cases
  85. stats = Dict{String,Array}()
  86. for (i,j) in empty_locations
  87. arr = []
  88. for n in 1:9
  89. if is_valid(board, i, j, n)
  90. append!(arr, n)
  91. end
  92. end
  93. stats["$i $j"] = arr
  94. end
  95. cols = Dict{String,Int}()
  96. rows = Dict{String,Int}()
  97. subgrid = Dict{String,Int}()
  98. for (i,j) in empty_locations
  99. for v in stats["$i $j"]
  100. k1 = "$j $v"
  101. k2 = "$i $v"
  102. k3 = join([3*div(i-1,3), 3*div(j-1,3), v], " ")
  103. if !haskey(cols, k1)
  104. cols[k1] = 1
  105. else
  106. cols[k1] += 1
  107. end
  108. if !haskey(rows, k2)
  109. rows[k2] = 1
  110. else
  111. rows[k2] += 1
  112. end
  113. if !haskey(subgrid, k3)
  114. subgrid[k3] = 1
  115. else
  116. subgrid[k3] += 1
  117. end
  118. end
  119. end
  120. for (i,j) in empty_locations
  121. for v in stats["$i $j"]
  122. if (cols["$j $v"] == 1 ||
  123. rows["$i $v"] == 1 ||
  124. subgrid[join([3*div(i-1,3), 3*div(j-1,3), v], " ")] == 1)
  125. board[i][j] = v
  126. found = true
  127. end
  128. end
  129. end
  130. found && continue
  131. # Give up and try brute-force
  132. solve_sudoku_fallback(board)
  133. return board
  134. end
  135. return board
  136. end
  137. # Example usage:
  138. # Define the Sudoku puzzle as a 9x9 list with 0 representing empty cells
  139. sudoku_board = [
  140. [2, 0, 0, 0, 7, 0, 0, 0, 3],
  141. [1, 0, 0, 0, 0, 0, 0, 8, 0],
  142. [0, 0, 4, 2, 0, 9, 0, 0, 5],
  143. [9, 4, 0, 0, 0, 0, 6, 0, 8],
  144. [0, 0, 0, 8, 0, 0, 0, 9, 0],
  145. [0, 0, 0, 0, 0, 0, 0, 7, 0],
  146. [7, 2, 1, 9, 0, 8, 0, 6, 0],
  147. [0, 3, 0, 0, 2, 7, 1, 0, 0],
  148. [4, 0, 0, 0, 0, 3, 0, 0, 0]
  149. ]
  150. if true
  151. sudoku_board = [
  152. [0, 0, 0, 8, 0, 1, 0, 0, 0],
  153. [0, 0, 0, 0, 0, 0, 0, 4, 3],
  154. [5, 0, 0, 0, 0, 0, 0, 0, 0],
  155. [0, 0, 0, 0, 7, 0, 8, 0, 0],
  156. [0, 0, 0, 0, 0, 0, 1, 0, 0],
  157. [0, 2, 0, 0, 3, 0, 0, 0, 0],
  158. [6, 0, 0, 0, 0, 0, 0, 7, 5],
  159. [0, 0, 3, 4, 0, 0, 0, 0, 0],
  160. [0, 0, 0, 2, 0, 0, 6, 0, 0]
  161. ]
  162. end
  163. if false
  164. sudoku_board = [
  165. [8, 0, 0, 0, 0, 0, 0, 0, 0],
  166. [0, 0, 3, 6, 0, 0, 0, 0, 0],
  167. [0, 7, 0, 0, 9, 0, 2, 0, 0],
  168. [0, 5, 0, 0, 0, 7, 0, 0, 0],
  169. [0, 0, 0, 0, 4, 5, 7, 0, 0],
  170. [0, 0, 0, 1, 0, 0, 0, 3, 0],
  171. [0, 0, 1, 0, 0, 0, 0, 6, 8],
  172. [0, 0, 8, 5, 0, 0, 0, 1, 0],
  173. [0, 9, 0, 0, 0, 0, 4, 0, 0]
  174. ]
  175. end
  176. solution = solve_sudoku(sudoku_board)
  177. if (solution != nothing)
  178. for row in solution
  179. println(row)
  180. end
  181. else
  182. println("No unique solution exists.")
  183. end