sudokude 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/sudokude.rb +141 -0
  2. metadata +62 -0
data/lib/sudokude.rb ADDED
@@ -0,0 +1,141 @@
1
+ module Sudokude
2
+ class Sudoku
3
+ def initialize(sudoku)
4
+ raise "This is not the proper size" if sudoku.map {|e| e.size } != [9,9,9,9,9,9,9,9,9]
5
+ @sudoku = {}
6
+ j = 0
7
+
8
+ # This code creates a hash table with key indexes for each value.
9
+ # The key is made up of three digits and shows the exact location
10
+ # of the number.
11
+ sudoku.each do |row|
12
+ 9.times do |i|
13
+ if i <= 2 && j <= 2
14
+ b = 0
15
+ elsif i <= 5 && j <= 2
16
+ b = 1
17
+ elsif i > 5 && j <= 2
18
+ b = 2
19
+ elsif i <= 2 && j <= 5
20
+ b = 3
21
+ elsif i <= 5 && j <= 5
22
+ b = 4
23
+ elsif i > 5 && j <= 5
24
+ b = 5
25
+ elsif i <= 2 && j > 5
26
+ b = 6
27
+ elsif i <= 5 && j > 5
28
+ b = 7
29
+ else
30
+ b = 8
31
+ end
32
+ @sudoku[i.to_s + j.to_s + b.to_s] = row[i]
33
+ end
34
+ j += 1
35
+ end
36
+ end
37
+
38
+ def print
39
+ @sudoku.values.each_slice(9).to_a.each do |row|
40
+ row.map! do |e|
41
+ if e.nil?
42
+ "n"
43
+ else
44
+ e
45
+ end
46
+ end
47
+ puts row.join(" ")
48
+ end
49
+ end
50
+
51
+ def solve!
52
+ unsolved = {}
53
+ @keysizes = []
54
+ @sudoku.each do |key, value|
55
+ if value.nil?
56
+ unsolved[key] = [1,2,3,4,5,6,7,8,9]
57
+ end
58
+ end
59
+
60
+ until solved
61
+
62
+ # Simple elimination method
63
+ unsolved.each do |key, value|
64
+ value.reject! do |number|
65
+ (@sudoku.row(key[1].to_i) + @sudoku.column(key[0].to_i) + @sudoku.box(key[2].to_i)).include?(number)
66
+ end
67
+ @sudoku[key] = value[0] if value.size == 1
68
+ unsolved.delete_if { |key, value| value.empty? }
69
+ end
70
+
71
+
72
+ # Naked multiples method
73
+ unsolved.each do |key, value|
74
+ if unsolved.row(key[1].to_i).has_naked_multiple?(value)
75
+ unsolved.each do |nkey, nvalue|
76
+ nvalue.reject! { |n| value.include?(n) } if (!(nvalue-value).empty? && key[1] == nkey[1])
77
+ end
78
+ end
79
+ if unsolved.column(key[0].to_i).has_naked_multiple?(value)
80
+ unsolved.each do |nkey, nvalue|
81
+ nvalue.reject! { |n| value.include?(n) } if (!(nvalue-value).empty? && key[0] == nkey[0])
82
+ end
83
+ end
84
+ if unsolved.box(key[2].to_i).has_naked_multiple?(value)
85
+ unsolved.each do |nkey, nvalue|
86
+ nvalue.reject! { |n| value.include?(n) } if (!(nvalue-value).empty? && key[2] == nkey[2])
87
+ end
88
+ end
89
+
90
+ @sudoku[key] = value[0] if value.size == 1
91
+ unsolved.delete_if { |key, value| value.empty? }
92
+ end
93
+
94
+ if unsolvable
95
+ puts "Impossible to solve. Best solution (n if no solution):"
96
+ break
97
+ end
98
+ end
99
+
100
+ print
101
+
102
+ end
103
+
104
+ private
105
+
106
+ # Array#compact removes all nils. A solved puzzle has no nils to remove.
107
+ def solved
108
+ @sudoku.values.compact.size == 81
109
+ end
110
+
111
+
112
+ # This evaluates the number of solved keys in the puzzle. If no new blanks have been
113
+ # filled in over multiple passes through the solving methods, then the puzzle cannot
114
+ # be solved.
115
+ def unsolvable
116
+ @keysizes << @sudoku.values.compact.size
117
+ @keysizes[-1] == @keysizes[-3]
118
+ end
119
+
120
+ end
121
+
122
+ class Hash
123
+ def row(i)
124
+ self.select { |key, value| key[1].to_i == i }.values
125
+ end
126
+
127
+ def column(i)
128
+ self.select { |key, value| key[0].to_i == i }.values
129
+ end
130
+
131
+ def box(i)
132
+ self.select { |key, value| key[2].to_i == i }.values
133
+ end
134
+ end
135
+
136
+ class Array
137
+ def has_naked_multiple?(item)
138
+ self.select { |e| (e - item).empty? }.size == item.size
139
+ end
140
+ end
141
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sudokude
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Dan Chao
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2013-09-19 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: This program solves Sudoku puzzles in the form of nested arrays
22
+ email: daniel.h.chao@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/sudokude.rb
31
+ has_rdoc: true
32
+ homepage:
33
+ licenses: []
34
+
35
+ post_install_message:
36
+ rdoc_options: []
37
+
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.3.6
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Solve sudoku puzzles
61
+ test_files: []
62
+