sudoku-jedi 0.0.4

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 74911c606d986649ad04415a8c460349c8cb61dd
4
+ data.tar.gz: ccd085050a3bfab521a84baaf8c453d1125c2c75
5
+ SHA512:
6
+ metadata.gz: a43339c43965b19bb3bfd5cbd7a1ee6c4de4f16a419cdff78019c8240d86928a4529e92cfd3134eb9dc0f9fd1b1f8adfd6350a3c161bc2b2e319d3d45b6fe166
7
+ data.tar.gz: 395aad6b71cb3d67647557b5258c3e3b4864ba30b9f2b3fdfc263d1b01ea203a5bee273a96544f1b9201c0c5310a7ac7e79e9876c543c42f132b46a44480200b
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ lannguage: ruby
2
+ cache: bundler
3
+
4
+ rvm:
5
+ - 2.2.0
6
+
7
+ script: 'bundle exec rake'
8
+
9
+ notifications:
10
+ email:
11
+ recipients:
12
+ - ajn123@vt.edu
13
+ on_failure: change
14
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sudoku_solver.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,77 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec feature)
6
+
7
+ ## Uncomment to clear the screen before every task
8
+ # clearing :on
9
+
10
+ ## Guard internally checks for changes in the Guardfile and exits.
11
+ ## If you want Guard to automatically start up again, run guard in a
12
+ ## shell loop, e.g.:
13
+ ##
14
+ ## $ while bundle exec guard; do echo "Restarting Guard..."; done
15
+ ##
16
+ ## Note: if you are using the `directories` clause above and you are not
17
+ ## watching the project directory ('.'), the you will want to move the Guardfile
18
+ ## to a watched dir and symlink it back, e.g.
19
+ #
20
+ # $ mkdir config
21
+ # $ mv Guardfile config/
22
+ # $ ln -s config/Guardfile .
23
+ #
24
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
25
+
26
+ # Note: The cmd option is now required due to the increasing number of ways
27
+ # rspec may be run, below are examples of the most common uses.
28
+ # * bundler: 'bundle exec rspec'
29
+ # * bundler binstubs: 'bin/rspec'
30
+ # * spring: 'bin/rspec' (This will use spring if running and you have
31
+ # installed the spring binstubs per the docs)
32
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
33
+ # * 'just' rspec: 'rspec'
34
+
35
+ guard :rspec, cmd: "bundle exec rspec" do
36
+ require "guard/rspec/dsl"
37
+ dsl = Guard::RSpec::Dsl.new(self)
38
+
39
+ # Feel free to open issues for suggestions and improvements
40
+
41
+ # RSpec files
42
+ rspec = dsl.rspec
43
+ watch(rspec.spec_helper) { rspec.spec_dir }
44
+ watch(rspec.spec_support) { rspec.spec_dir }
45
+ watch(rspec.spec_files)
46
+
47
+ # Ruby files
48
+ ruby = dsl.ruby
49
+ dsl.watch_spec_files_for(ruby.lib_files)
50
+
51
+ # Rails files
52
+ rails = dsl.rails(view_extensions: %w(erb haml slim))
53
+ dsl.watch_spec_files_for(rails.app_files)
54
+ dsl.watch_spec_files_for(rails.views)
55
+
56
+ watch(rails.controllers) do |m|
57
+ [
58
+ rspec.spec.("routing/#{m[1]}_routing"),
59
+ rspec.spec.("controllers/#{m[1]}_controller"),
60
+ rspec.spec.("acceptance/#{m[1]}")
61
+ ]
62
+ end
63
+
64
+ # Rails config changes
65
+ watch(rails.spec_helper) { rspec.spec_dir }
66
+ watch(rails.routes) { "#{rspec.spec_dir}/routing" }
67
+ watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
68
+
69
+ # Capybara features specs
70
+ watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
71
+
72
+ # Turnip features and steps
73
+ watch(%r{^spec/acceptance/(.+)\.feature$})
74
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
75
+ Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
76
+ end
77
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 ajn123
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # Sudoku Jedi
2
+ [![Build Status](https://travis-ci.org/RubyQuarry/sudoku_solver.svg?branch=master)](https://travis-ci.org/RubyQuarry/sudoku_solver)
3
+ [![Coverage Status](https://coveralls.io/repos/RubyQuarry/sudoku_solver/badge.png)](https://coveralls.io/r/RubyQuarry/sudoku_solver)
4
+ [![Gem Version](https://badge.fury.io/rb/sudoku-jedi.svg)](http://badge.fury.io/rb/sudoku-jedi)
5
+
6
+ Currently solves easy to moderate sudoku puzzles in a flash!
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'sudoku-jedi'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install sudoku_solver
23
+
24
+ ## Usage
25
+
26
+ Sudoku-Jedi can solve sodokus for you. All you have to do is put a sudoku in a text with zeros marked as the
27
+ empty cells for example: a.txt
28
+ ```
29
+ 043080250
30
+ 600000000
31
+ 000001094
32
+ 900004070
33
+ 000608000
34
+ 010200003
35
+ 820500000
36
+ 000000005
37
+ 034090710
38
+ ```
39
+
40
+ Then calling
41
+ ```
42
+ sudoku-jedi solve a.txt
43
+ ```
44
+ will result in your printed answer in the terminal.
45
+
46
+
47
+ ## Contributing
48
+
49
+ 1. Fork it ( https://github.com/RubyQuarry/sudoku_solver/fork )
50
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
51
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
52
+ 4. Push to the branch (`git push origin my-new-feature`)
53
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
+
4
+ # Run with `rake spec`
5
+ RSpec::Core::RakeTask.new(:spec) do |task|
6
+ task.rspec_opts = ['--color']
7
+ end
8
+
9
+ task :default => :spec
data/bin/sudoku-jedi ADDED
@@ -0,0 +1,2 @@
1
+ require 'sudoku_solver/cli'
2
+ CLI.start
@@ -0,0 +1,16 @@
1
+ require_relative 'container'
2
+
3
+ class Box < Container
4
+ attr_accessor :box, :position
5
+
6
+ def initialize(arr, y=0, x=0)
7
+ super(arr)
8
+ Struct.new("Coordinate", :x, :y) if !Struct::const_defined? "Coordinate"
9
+ @position = Struct::Coordinate.new(x, y)
10
+ end
11
+
12
+ def blank_spaces
13
+ [(position.y / 3) * 3 + (position.x / 3), position.y, position.x]
14
+ end
15
+
16
+ end
@@ -0,0 +1,6 @@
1
+ class Cell
2
+ attr_accessor :num
3
+ def initialize(num)
4
+ @num = num
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ require 'thor'
2
+ require_relative 'grid'
3
+ class CLI < Thor
4
+
5
+ desc "solve [FILE NAME]", "Solves a sudoku puzzle from a text file"
6
+ def solve(file_name)
7
+ file = File.open(file_name, "rb")
8
+ contents = file.read.gsub("\n", "")
9
+ contents.gsub!(" ","")
10
+ grid = Grid.new(contents.scan(/\d{9}/))
11
+ grid.solve
12
+ grid.print_values_formatted
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ require_relative 'container'
2
+ class Column < Container
3
+
4
+
5
+
6
+ end
@@ -0,0 +1,35 @@
1
+ class Container
2
+
3
+ attr_accessor :arr, :remaining_blocks
4
+ def initialize(arr)
5
+ @arr = arr
6
+ end
7
+ # Find the missing elements in the section
8
+ def difference
9
+ complete
10
+ remaining
11
+ end
12
+
13
+ def remaining
14
+ Array(1..9) - arr
15
+ end
16
+
17
+ def arr
18
+ @arr.map!(&:to_i)
19
+ end
20
+
21
+ def contain?(num)
22
+ complete
23
+ arr.include? num
24
+ end
25
+
26
+ def pencil_in
27
+ end
28
+
29
+
30
+ def complete
31
+ if remaining.count == 1
32
+ arr.map { |elem| elem == 0 ? remaining.first : elem }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,250 @@
1
+ require_relative 'box'
2
+ require_relative 'point'
3
+ require 'set'
4
+
5
+ class Grid
6
+ attr_accessor :remaining_nums, :points
7
+ def initialize(txt_file)
8
+ @points = []
9
+ txt_file.each_with_index do |text, row|
10
+ text.split("").map(&:to_i).each_with_index do |num, col|
11
+ @points << Point.new(row, col, num)
12
+ end
13
+ end
14
+
15
+ @points.select { |po| po.value == 0 }.each do |poi|
16
+ poi.nums = Array(1..9) - (get_box(poi.box) + get_row(poi.y) + get_column(poi.x))
17
+ end
18
+ end
19
+
20
+ def print_values_formatted
21
+ puts "SOLUTION"
22
+ @points.each_slice(9) do |s|
23
+ puts s.map{ |p| p.value}.join
24
+ end
25
+ end
26
+
27
+ def print_values
28
+ a = @points.map { |p| p.value}.join
29
+ puts a
30
+ a
31
+ end
32
+
33
+ def get_box(num)
34
+ @points.select { |point| point.box == num }.map { |b| b.value }
35
+ end
36
+
37
+ def get_row(num)
38
+ @points.select { |point| point.y == num }.map { |b| b.value }
39
+ end
40
+
41
+ def get_column(num)
42
+ @points.select { |point| point.x == num }.map { |b| b.value }
43
+ end
44
+
45
+ def fill_row(num)
46
+ @points.select { |point| point.x == num }
47
+ end
48
+
49
+ def find_diff(point)
50
+ point.nums = point.nums - (get_box(point.box) + get_row(point.y) + get_column(point.x))
51
+ end
52
+
53
+ def flat_points
54
+ @points.select { |p| p.value == 0 }
55
+ end
56
+
57
+ def get_values(arr)
58
+ arr.map { |b| b.value }
59
+ end
60
+
61
+ def update_points
62
+ @points.select { |po| po.value == 0 }.each do |poi|
63
+ find_diff(poi)
64
+ end
65
+ (0..8).each do |num|
66
+ [:box, :x, :y].each do |fields|
67
+ yield @points.select { |p| p.send(fields) == num }
68
+ end
69
+ end
70
+ end
71
+
72
+ def fill_in
73
+ remaining_points.each do |p|
74
+ find_diff(p)
75
+ end
76
+ end
77
+
78
+
79
+ def remaining_points
80
+ @points.select { |p| p.value == 0 }
81
+ end
82
+
83
+ def components
84
+ [:x, :y, :box]
85
+ end
86
+
87
+ def pinned_points
88
+ remaining_points.each do |point|
89
+ components.each do |symbol|
90
+ point.nums.each do |num|
91
+ if @points.select { |p| p.include?(num) && p.send(symbol) == point.send(symbol) && p != point }.count == 0
92
+ point.value = num
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ def solve
100
+ while !is_solved?
101
+ all_naked_pairs
102
+ hidden_pairs
103
+ pointing_pairs
104
+ box_line_reduction
105
+ x_wing
106
+ end
107
+ end
108
+
109
+ def all_naked_pairs
110
+ fill_in
111
+ pinned_points
112
+ naked_pairs
113
+ end
114
+
115
+ def naked_pairs
116
+ remaining_points.each do |point|
117
+ next if point.nums.count <= 1
118
+ components.each do |symbol|
119
+ possible = remaining_points.select { |p| p.subset?(point) && p != point && p.send(symbol) == point.send(symbol) && p.nums.count >= 2 }
120
+ possible << point
121
+ if possible.count == point.nums.count
122
+ compare_points(possible).each do |type|
123
+ found = remaining_points.select { |p| p.send(type) == point.send(type) && (!possible.include?(p)) }
124
+ found.each do |f|
125
+ f.nums = (f.nums - point.nums)
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ def pointing_pairs
134
+ all_naked_pairs
135
+ remaining_points.each do |point|
136
+ (1..9).each do |num|
137
+ [:x, :y].each do |symbol|
138
+ possible = @points.select { |p| p.send(symbol) == point.send(symbol) && p.box == point.box && p.include?(num) }
139
+ if possible.count >= 2
140
+ if @points.select { |p| p.box == point.box && (!possible.include?(p)) && p.include?(num) }.count == 0
141
+ remove = remaining_points.select { |p| p.box != point.box && p.send(symbol) == point.send(symbol) && p.include?(num) }
142
+ remove.each do |r|
143
+ r.nums = (r.nums - [num])
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ def box_line_reduction
153
+ pointing_pairs
154
+ remaining_points.each do |point|
155
+ (1..9).each do |num|
156
+ [:x, :y].each do |symbol|
157
+ possible = remaining_points.select { |p| p.send(symbol) == point.send(symbol) && p.box == point.box && p.include?(num) }
158
+ if possible.count >= 2
159
+ if @points.select { |p| p.send(symbol) == point.send(symbol) && (!possible.include?(p)) && p.include?(num) }.count == 0
160
+ remove = remaining_points.select { |p| p.box == point.box && p.include?(num) && (!possible.include?(p)) }
161
+ remove.each do |r|
162
+ r.nums = (r.nums - [num])
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ def is_solved?
172
+ @points.select{ |p| p.value == 0 }.count == 0
173
+ end
174
+
175
+ def print_values_formatted
176
+ puts "GRID"
177
+ @points.each_slice(9) do |s|
178
+ puts s.map{ |p| p.value}.join
179
+ end
180
+ end
181
+
182
+
183
+ def compare_points(arr)
184
+ a = []
185
+ a << :x if arr.all? { |w| w.x == arr.first.x }
186
+ a << :y if arr.all? { |s| s.y == arr.first.y }
187
+ a << :box if arr.all? { |t| t.box == arr.first.box }
188
+ a
189
+ end
190
+
191
+
192
+ def hidden_pairs
193
+ all_naked_pairs
194
+ # @points.select { |p| p.x == 6 && p.y == 4 }.first.nums = @points.select { |p| p.x == 6 && p.y == 4 }.first.nums - [1,5]
195
+ # @points.select { |p| p.x == 6 && p.y == 6 }.first.nums = @points.select { |p| p.x == 6 && p.y == 6 }.first.nums - [3,6]
196
+
197
+ remaining_points.each do |point|
198
+ next if point.nums.count <= 1
199
+ point.nums.combination(2).each do |arr|
200
+ components.each do |symbol|
201
+ remove = @points.select { |p| p.send(symbol) == point.send(symbol) && arr.to_set.subset?(p.nums.to_set) && p.nums.count >= 2}
202
+ if remove.count == 2 && @points.select { |p| p.send(symbol) == point.send(symbol) && ( arr.include?(p.value)) }.count == 0
203
+ #remove.each { |r| r.nums = arr }
204
+ return
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ def box_count(box, num)
212
+ @points.select { |p| p.box == box && p.nums.to_set.subset?(num.to_set) }.count
213
+ end
214
+
215
+ def x_wing
216
+ box_line_reduction
217
+ remaining_points.each do |point|
218
+ point.nums.each do |num|
219
+ [:x, :y].each do |symbol|
220
+ arr = @points.select{ |p| p.nums.include?(num) && p.send(flip(symbol)) == point.send(flip(symbol)) && p.value == 0 }
221
+ if arr.count == 2 && @points.select { |p| p.value == num && p.send(flip(symbol)) == point.send(flip(symbol)) }.count == 0
222
+ last = @points.select { |p| p.nums.include?(num) && arr.map{ |a| a.send(symbol) }.include?(p.send(symbol)) && (!arr.include?(p)) && p.value == 0 && check_row(p.y,p,num,symbol) }
223
+ if last.all? { |x| x.send(flip(symbol)) == last.first.send(flip(symbol)) } && last.count == 2 && @points.select { |p| p.value == num && p.send(flip(symbol)) == last.first.send(flip(symbol)) }.count == 0
224
+ final = arr + last
225
+ places = final.map { |m| m.send(symbol) }.uniq
226
+ remaining_points.select { |p| places.include?(p.send(symbol)) && (!final.include?(p)) }.each do |poi|
227
+ poi.nums = poi.nums - [num]
228
+ end
229
+ end
230
+ end
231
+ end
232
+ end
233
+ end
234
+
235
+ end
236
+
237
+ def check_row(row, point, num, symbol)
238
+ a = @points.select { |p| p.send(flip(symbol)) == row && p != point }.map { |x| x.nums }.flatten
239
+ a.count(num) <= 1
240
+ end
241
+
242
+ def flip(n)
243
+ if n == :y
244
+ :x
245
+ else
246
+ :y
247
+ end
248
+ end
249
+
250
+ end
@@ -0,0 +1,71 @@
1
+ require_relative 'container'
2
+ require 'set'
3
+
4
+ class Point
5
+ attr_accessor :box, :position, :nums, :value
6
+
7
+ def initialize(y=0, x=0, value = 0)
8
+ @value = value
9
+ Struct.new("Coordinate", :x, :y) if !Struct::const_defined? "Coordinate"
10
+ @position = Struct::Coordinate.new(x, y)
11
+ @nums = []
12
+ @box = (position.y / 3) * 3 + (position.x / 3)
13
+ end
14
+
15
+ def nums
16
+ @nums.sort
17
+ end
18
+
19
+
20
+ def share(point)
21
+ a = []
22
+ a << :box if @box == point.box
23
+ a << :x if x == point.x
24
+ a << :y if y == point.y
25
+ return a
26
+ end
27
+
28
+ def value=(val)
29
+ if @value == 0
30
+ @value = val
31
+ if @value != 0
32
+ @nums = [val]
33
+ end
34
+ end
35
+ end
36
+
37
+ def nums=(n)
38
+ if @value == 0
39
+ @nums = n
40
+ if @nums.count == 1
41
+ @value = @nums.first
42
+ @nums = [@value]
43
+ end
44
+ end
45
+ end
46
+
47
+
48
+ def include?(num)
49
+ nums.include?(num) || (num == value)
50
+ end
51
+
52
+ def subset?(point)
53
+ nums.to_set.subset?(point.nums.to_set)
54
+ end
55
+
56
+
57
+ def x
58
+ @position.x
59
+ end
60
+
61
+ def y
62
+ @position.y
63
+ end
64
+
65
+ def blank_spaces
66
+ [(position.y / 3) * 3 + (position.x / 3), position.y, position.x]
67
+ end
68
+
69
+
70
+ end
71
+
@@ -0,0 +1,4 @@
1
+ require_relative 'container'
2
+ class Row < Container
3
+
4
+ end
@@ -0,0 +1,3 @@
1
+ module SudokuSolver
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,10 @@
1
+ require "sudoku_solver/version"
2
+ require "sudoku_solver/cell"
3
+ require "sudoku_solver/box"
4
+ require 'sudoku_solver/row'
5
+ require 'sudoku_solver/column'
6
+ require 'sudoku_solver/grid'
7
+ require 'sudoku_solver/cli'
8
+ module SudokuSolver
9
+ # Your code goes here...
10
+ end
data/spec/box_spec.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ describe Box do
3
+ let(:box) { Box.new([1,2,4,5,6,7,8,9], 0, 5)}
4
+ context "Coordinates" do
5
+ it "is correct" do
6
+ expect(box.blank_spaces).to eql([1, 0, 5])
7
+ @let_box = Box.new([], 8, 8)
8
+ expect(@let_box.blank_spaces).to eql([8, 8, 8])
9
+ end
10
+ end
11
+ context "#differance" do
12
+ it "shows the incorrect differance" do
13
+ expect(box.difference).to_not eql(Array(5..9))
14
+ end
15
+ it "show the correct differance" do
16
+ expect(box.difference).to eql([3])
17
+ end
18
+ end
19
+ context "#complete" do
20
+ it "completes the cell" do
21
+ @in_box = Box.new([1,0,3,4,5,6,7,8,9])
22
+ expect(@in_box.complete).to eql(Array(1..9))
23
+ end
24
+ end
25
+ end
data/spec/cell_spec.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ describe Cell do
3
+ let(:cell) { Cell.new(234) }
4
+ it "#num" do
5
+ expect(cell.num).to eql(234)
6
+ end
7
+
8
+ end
data/spec/grid_spec.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grid do
4
+ let(:grid) { Grid.new(%w{050400716
5
+ 409061200
6
+ 106205400
7
+ 007046035
8
+ 680390007
9
+ 940050680
10
+ 091003024
11
+ 060904501
12
+ 704510060})}
13
+
14
+ context "point conversion" do
15
+
16
+ it "solves with points" do
17
+ @new_grid = Grid.new(%w{050030090
18
+ 200000007
19
+ 400507008
20
+ 345601879
21
+ 791000265
22
+ 800000003
23
+ 502403906
24
+ 683050741
25
+ 910070032})
26
+ @new_grid.solve
27
+ expect(@new_grid.is_solved?).to eql(true)
28
+ # puts @new_grid.points[9*9 - 3].nums
29
+ end
30
+ it "solves a triplet" do
31
+ @sec_grid = Grid.new(%w{070408029
32
+ 002000004
33
+ 854020007
34
+ 008374200
35
+ 020000000
36
+ 003261700
37
+ 000093612
38
+ 200000403
39
+ 130642070})
40
+ @sec_grid.solve
41
+ expect(@sec_grid.print_values).to eql("671438529392715864854926137518374296726859341943261785487593612269187453135642978")
42
+ end
43
+
44
+ it "solves a hard puzzle" do
45
+ @hard_grid = Grid.new(%w{300200000
46
+ 000107000
47
+ 706030500
48
+ 070009080
49
+ 900020004
50
+ 010800050
51
+ 009040301
52
+ 000702000
53
+ 000008006})
54
+ @hard_grid.solve
55
+ expect(@hard_grid.print_values).to eql("351286497492157638786934512275469183938521764614873259829645371163792845547318926")
56
+ end
57
+ it "solves x-wing puzzle" do
58
+ @x_grid = Grid.new(%w{043080250
59
+ 600000000
60
+ 000001094
61
+ 900004070
62
+ 000608000
63
+ 010200003
64
+ 820500000
65
+ 000000005
66
+ 034090710})
67
+ puts "hard grid"
68
+ @x_grid.solve
69
+ expect(@x_grid.print_values).to eql("143986257679425381285731694962354178357618942418279563821567439796143825534892716")
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,98 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require 'sudoku_solver'
5
+
6
+ # This file was generated by the `rspec --init` command. Conventionally, all
7
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
8
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
9
+ # file to always be loaded, without a need to explicitly require it in any files.
10
+ #
11
+ # Given that it is always loaded, you are encouraged to keep this file as
12
+ # light-weight as possible. Requiring heavyweight dependencies from this file
13
+ # will add to the boot time of your test suite on EVERY test run, even for an
14
+ # individual file that may not need all of that loaded. Instead, consider making
15
+ # a separate helper file that requires the additional dependencies and performs
16
+ # the additional setup, and require it from the spec files that actually need it.
17
+ #
18
+ # The `.rspec` file also contains a few flags that are not defaults but that
19
+ # users commonly want.
20
+ #
21
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
22
+ RSpec.configure do |config|
23
+ # rspec-expectations config goes here. You can use an alternate
24
+ # assertion/expectation library such as wrong or the stdlib/minitest
25
+ # assertions if you prefer.
26
+ config.expect_with :rspec do |expectations|
27
+ # This option will default to `true` in RSpec 4. It makes the `description`
28
+ # and `failure_message` of custom matchers include text for helper methods
29
+ # defined using `chain`, e.g.:
30
+ # be_bigger_than(2).and_smaller_than(4).description
31
+ # # => "be bigger than 2 and smaller than 4"
32
+ # ...rather than:
33
+ # # => "be bigger than 2"
34
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
35
+ end
36
+
37
+ # rspec-mocks config goes here. You can use an alternate test double
38
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
39
+ config.mock_with :rspec do |mocks|
40
+ # Prevents you from mocking or stubbing a method that does not exist on
41
+ # a real object. This is generally recommended, and will default to
42
+ # `true` in RSpec 4.
43
+ mocks.verify_partial_doubles = true
44
+ end
45
+
46
+ config.expect_with :rspec do |c|
47
+ c.syntax = :expect
48
+ end
49
+
50
+ # The settings below are suggested to provide a good initial experience
51
+ # with RSpec, but feel free to customize to your heart's content.
52
+ =begin
53
+ # These two settings work together to allow you to limit a spec run
54
+ # to individual examples or groups you care about by tagging them with
55
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
56
+ # get run.
57
+ config.filter_run :focus
58
+ config.run_all_when_everything_filtered = true
59
+
60
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
61
+ # For more details, see:
62
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
63
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
64
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
65
+ config.disable_monkey_patching!
66
+
67
+ # This setting enables warnings. It's recommended, but in some cases may
68
+ # be too noisy due to issues in dependencies.
69
+ config.warnings = true
70
+
71
+ # Many RSpec users commonly either run the entire suite or an individual
72
+ # file, and it's useful to allow more verbose output when running an
73
+ # individual spec file.
74
+ if config.files_to_run.one?
75
+ # Use the documentation formatter for detailed output,
76
+ # unless a formatter has already been configured
77
+ # (e.g. via a command-line flag).
78
+ config.default_formatter = 'doc'
79
+ end
80
+
81
+ # Print the 10 slowest examples and example groups at the
82
+ # end of the spec run, to help surface which specs are running
83
+ # particularly slow.
84
+ config.profile_examples = 10
85
+
86
+ # Run specs in random order to surface order dependencies. If you find an
87
+ # order dependency and want to debug it, you can fix the order by providing
88
+ # the seed, which is printed after each run.
89
+ # --seed 1234
90
+ config.order = :random
91
+
92
+ # Seed global randomization in this process using the `--seed` CLI option.
93
+ # Setting this allows you to use `--seed` to deterministically reproduce
94
+ # test failures related to randomization by passing the same `--seed` value
95
+ # as the one that triggered the failure.
96
+ Kernel.srand config.seed
97
+ =end
98
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sudoku_solver/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sudoku-jedi"
8
+ spec.version = SudokuSolver::VERSION
9
+ spec.authors = ["ajn123"]
10
+ spec.email = ["ajn123@vt.edu"]
11
+ spec.summary = %q{Solves a sudoku puzzle}
12
+ spec.description = %q{Solves easy to moderate soduku puzzles efficiently}
13
+ spec.homepage = "https://github.com/RubyQuarry/sudoku-jedi"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "rspec-nc"
25
+ spec.add_development_dependency "guard"
26
+ spec.add_development_dependency "guard-rspec"
27
+ spec.add_development_dependency "pry"
28
+ spec.add_development_dependency "pry-remote"
29
+ spec.add_development_dependency "pry-nav"
30
+ spec.add_development_dependency "coveralls"
31
+ spec.add_dependency "thor"
32
+ end
33
+
metadata ADDED
@@ -0,0 +1,228 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sudoku-jedi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - ajn123
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-nc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry-remote
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry-nav
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: coveralls
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: thor
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: Solves easy to moderate soduku puzzles efficiently
168
+ email:
169
+ - ajn123@vt.edu
170
+ executables:
171
+ - sudoku-jedi
172
+ extensions: []
173
+ extra_rdoc_files: []
174
+ files:
175
+ - ".coveralls.yml"
176
+ - ".gitignore"
177
+ - ".rspec"
178
+ - ".travis.yml"
179
+ - Gemfile
180
+ - Guardfile
181
+ - LICENSE.txt
182
+ - README.md
183
+ - Rakefile
184
+ - bin/sudoku-jedi
185
+ - lib/sudoku_solver.rb
186
+ - lib/sudoku_solver/box.rb
187
+ - lib/sudoku_solver/cell.rb
188
+ - lib/sudoku_solver/cli.rb
189
+ - lib/sudoku_solver/column.rb
190
+ - lib/sudoku_solver/container.rb
191
+ - lib/sudoku_solver/grid.rb
192
+ - lib/sudoku_solver/point.rb
193
+ - lib/sudoku_solver/row.rb
194
+ - lib/sudoku_solver/version.rb
195
+ - spec/box_spec.rb
196
+ - spec/cell_spec.rb
197
+ - spec/grid_spec.rb
198
+ - spec/spec_helper.rb
199
+ - sudoku_solver.gemspec
200
+ homepage: https://github.com/RubyQuarry/sudoku-jedi
201
+ licenses:
202
+ - MIT
203
+ metadata: {}
204
+ post_install_message:
205
+ rdoc_options: []
206
+ require_paths:
207
+ - lib
208
+ required_ruby_version: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - ">="
211
+ - !ruby/object:Gem::Version
212
+ version: '0'
213
+ required_rubygems_version: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: '0'
218
+ requirements: []
219
+ rubyforge_project:
220
+ rubygems_version: 2.4.5
221
+ signing_key:
222
+ specification_version: 4
223
+ summary: Solves a sudoku puzzle
224
+ test_files:
225
+ - spec/box_spec.rb
226
+ - spec/cell_spec.rb
227
+ - spec/grid_spec.rb
228
+ - spec/spec_helper.rb