sudokude 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+