doku 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +66 -2
- data/VERSION +1 -1
- data/lib/doku/dancing_links.rb +14 -19
- data/lib/doku/hexadoku.rb +24 -1
- data/lib/doku/hexamurai.rb +40 -1
- data/lib/doku/solver.rb +2 -7
- data/lib/doku/sudoku.rb +16 -1
- data/spec/dancing_links_spec.rb +16 -4
- data/spec/solution_spec.rb +10 -19
- metadata +23 -23
data/README.rdoc
CHANGED
@@ -2,14 +2,78 @@
|
|
2
2
|
|
3
3
|
Doku is a Ruby[http://www.rubylang.org/] gem for solving Sudoku-like puzzles using the {Dancing Links}[http://en.wikipedia.org/wiki/Dancing_Links] algorithm by Donald Knuth.
|
4
4
|
|
5
|
+
Currently it supports these puzzles:
|
6
|
+
|
7
|
+
* Sudoku
|
8
|
+
* Hexadoku
|
9
|
+
* Hexamurai
|
10
|
+
|
5
11
|
== Installation
|
6
12
|
|
7
13
|
At the command line, type
|
8
14
|
|
9
15
|
gem install doku
|
10
16
|
|
11
|
-
You might need to prefix
|
17
|
+
You might need to prefix the command with <code>sudo</code> depending on where your gems are stored.
|
12
18
|
|
13
19
|
== Example code
|
14
20
|
|
15
|
-
|
21
|
+
require 'rubygems'
|
22
|
+
require 'doku'
|
23
|
+
|
24
|
+
puzzle = Doku::Sudoku.new <<END
|
25
|
+
...|..8|...
|
26
|
+
..7|.35|..9
|
27
|
+
5..|4.6|8..
|
28
|
+
---+---+---
|
29
|
+
...|..4|2..
|
30
|
+
4..|...|.37
|
31
|
+
8..|...|5..
|
32
|
+
---+---+---
|
33
|
+
.9.|.67|...
|
34
|
+
..3|...|1.5
|
35
|
+
...|...|..3
|
36
|
+
END
|
37
|
+
|
38
|
+
puts puzzle.solve || "No solutions."
|
39
|
+
|
40
|
+
== Introduction
|
41
|
+
|
42
|
+
This gem is designed to solve Sudoku-like puzzles. For the purposes of this gem, a "Sudoku-like" puzzle is a defined to be a puzzle consisting of a set of glyphs (i.e. symbols), a set of squares, and a set of groups of squares. Additionally, the number of squares in each group must be equal to the number of glyphs. Given a partial assignment of glyphs to squares, the goal is to assign a glyph to every square such that no two squares in the same group are assigned the same glyph.
|
43
|
+
|
44
|
+
For example, in Sudoku, the glyphs are the numbers 0 through 9, the squares are the squares of a 9x9 grid, and the groups consist of nine rows, nine columns, and nine 3x3 squares.
|
45
|
+
|
46
|
+
Every Sudoku-like puzzle can be reduced to an {exact cover problem}[http://en.wikipedia.org/wiki/Exact_cover]. From there is can be efficiently solved with the {Dancing Links}[http://arxiv.org/abs/cs/0011047] algorithm discovered by Donald Knuth. That is the main purpose of this gem.
|
47
|
+
|
48
|
+
== Classes and Modules Overview
|
49
|
+
|
50
|
+
The Doku::Puzzle class is an abstract class for working with Sudoku-like puzzles. It implements the concepts of groups, glyphs and squares. Each instance of this class represents a particular assignment of glyphs to squares; at its core, an instance is just a hash where the keys are squares and values are glyphs. This class provides <code>[]</code> and <code>[]=</code> methods for reading and modifying instances of the puzzle. It provides equality comparison and solution checking.
|
51
|
+
|
52
|
+
The Puzzle class includes the Doku::SolvableWithDancingLinks module which provides methods for solving puzzles using the Dancing Links algorithm. The solutions returned are instances of Puzzle.
|
53
|
+
|
54
|
+
The Doku::SquareOnGrid module provides methods used for Sudoku-like puzzles that can be drawn on a 2D grid. It implements the string representations of the puzzle by providing an <code>initialize</code> method that creates puzzles from strings and a <code>to_s</code> method that creates strings from puzzles. It provides <code>get</code> and <code>set</code> methods for modifying suqares of the puzzle by their coordinates.
|
55
|
+
|
56
|
+
The classes Doku::Sudoku, Doku::Hexadoku, and Doku::Hexamurai all inherit from Doku::Puzzle and include Doku::SquareOnGrid. Because of the framework set up by that class and that module, the definitions of these classes are short and the methods provided by each of them are rich and consistent with eachother.
|
57
|
+
|
58
|
+
The Doku::DancingLinks module contains several class that comprise a general-purpose implementation of the Dancing Links algorithm. This module is included in the Doku gem for convenience, but it is not specifically for solving Sudoku-like puzzles; it can be applied to any exact cover problem.
|
59
|
+
|
60
|
+
== Detailed Documentation
|
61
|
+
|
62
|
+
For detailed documentation of every class, module, and method, see the "Class List" link above.
|
63
|
+
|
64
|
+
== Contributing
|
65
|
+
|
66
|
+
You are invited to fork the {Doku github repository}[https://github.com/DavidEGrayson/doku] and work on improving the gem.
|
67
|
+
|
68
|
+
There are many directions this gem could go in. The direction will be determined by user feedback and by whatever the developers feel like working on. Possible improvements could be:
|
69
|
+
|
70
|
+
* A command-line utility for solving puzzles. This requires us to define a file format for puzzles.
|
71
|
+
* A C extension or a column size cache to make the Dancing Links algorithm faster.
|
72
|
+
* Hooks for providing progress updates during the solving of hard puzzles.
|
73
|
+
* Outputting puzzles in SVG format. Could include SVG animations that show the process of solving the puzzle!
|
74
|
+
* More types of puzzles that are solvable (e.g. puzzles that have groups with fewer squares than the number of glyphs).
|
75
|
+
* Improve this page. Ideally the method names should be linkified on the {rubydoc.info page}[http://rubydoc.info/github/DavidEGrayson/doku/master], but I still want something presentable to be on the {github repository}[https://github.com/DavidEGrayson/doku]. Here's an example of a link that looks good on RubyDoc.info but not on github: {Doku::Sudoku Sudoku}. If either YARD or Github could be configured to use a different file on the front page, that would suffice!
|
76
|
+
|
77
|
+
== Philosophy
|
78
|
+
|
79
|
+
This gem is meant to showcase beautiful Ruby code. Test-driven development was used at all times during the development of this gem. I have spent many hours reviewing the code, looking for ways to make it simpler, and refactoring it. Every class and public method is documented. Every method is short. There are no ugly hacks. All method names were chosen carefully. At every level, the power of the Ruby language is exploited to its fullest potential. --David Grayson
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.1
|
data/lib/doku/dancing_links.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'backports' unless defined?(Enumerator)
|
2
|
-
require 'set'
|
3
2
|
|
4
3
|
module Doku; end
|
5
4
|
|
@@ -7,8 +6,8 @@ module Doku; end
|
|
7
6
|
# {http://arxiv.org/abs/cs/0011047 Dancing Links}
|
8
7
|
# algorithm discovered by Donald Knuth for solving
|
9
8
|
# {http://en.wikipedia.org/wiki/Exact_cover exact cover problems}.
|
10
|
-
# This module is included in the Doku gem for convenience, but it
|
11
|
-
#
|
9
|
+
# This module is included in the Doku gem for convenience, but it is not
|
10
|
+
# specifically for solving Sudoku-like puzzles; it can be applied to any
|
12
11
|
# exact cover problem.
|
13
12
|
# The main class in this module is {LinkMatrix}. All the other classes and
|
14
13
|
# modules are helpers for this class.
|
@@ -370,7 +369,8 @@ module Doku::DancingLinks
|
|
370
369
|
# @param row_id (Object) The id of this row. This is used to express express exact covers and as the argument to {#remove_row}.
|
371
370
|
def add_row(column_ids, row_id=column_ids.dup)
|
372
371
|
first_node = nil
|
373
|
-
|
372
|
+
column_ids = column_ids.uniq if column_ids.respond_to?(:uniq)
|
373
|
+
column_ids.each do |column_id|
|
374
374
|
column = find_or_create_column(column_id)
|
375
375
|
node = Node.new
|
376
376
|
|
@@ -409,19 +409,20 @@ module Doku::DancingLinks
|
|
409
409
|
@rows[id]
|
410
410
|
end
|
411
411
|
|
412
|
-
# This
|
413
|
-
# LinkMatrix that represents an exact cover problem, using the
|
412
|
+
# This method is equivalent to {#each_exact_cover} but uses
|
414
413
|
# the algorithm described on page 5 of Donald Knuth's paper "Dancing Links".
|
415
414
|
# This method is just here for purists who want to be sure they are using
|
416
415
|
# Donald Knuth's algorithm.
|
417
|
-
# For most
|
416
|
+
# For most users, it is recommended to use the more flexible, non-recursive
|
418
417
|
# function {#each_exact_cover} and the methods based on it: {#exact_covers}
|
419
|
-
# and {#find_exact_cover}
|
418
|
+
# and {#find_exact_cover} because it can be difficult to debug programs with
|
419
|
+
# deep stacks.
|
420
420
|
# @return (Array) Array of row_ids of the rows/sets that are in the cover,
|
421
421
|
# or nil if no exact cover was found.
|
422
|
-
def
|
422
|
+
def each_exact_cover_recursive(k=0, o=[], &block)
|
423
423
|
if right == self
|
424
|
-
|
424
|
+
yield o[0...k].collect &:row_id # Success
|
425
|
+
return
|
425
426
|
end
|
426
427
|
|
427
428
|
c = smallest_column
|
@@ -434,9 +435,7 @@ module Doku::DancingLinks
|
|
434
435
|
j.column.cover
|
435
436
|
end
|
436
437
|
|
437
|
-
|
438
|
-
return answer # Success
|
439
|
-
end
|
438
|
+
each_exact_cover_recursive(k+1, o, &block)
|
440
439
|
|
441
440
|
r.nodes_except_self_leftward.each do |j|
|
442
441
|
j.column.uncover
|
@@ -463,16 +462,12 @@ module Doku::DancingLinks
|
|
463
462
|
# @return (Enumerable) Enumerable of exact covers. Each exact cover is
|
464
463
|
# an array of row ids of the rows/sets that are in the cover.
|
465
464
|
def exact_covers
|
466
|
-
|
467
|
-
each_exact_cover do |ec|
|
468
|
-
y << ec
|
469
|
-
end
|
470
|
-
end
|
465
|
+
enum_for :each_exact_cover
|
471
466
|
end
|
472
467
|
|
473
468
|
# Searches for exact covers and yields them as it finds them.
|
474
469
|
# NOTE: This method mutates the LinkMatrix while it is running, but
|
475
|
-
#
|
470
|
+
# when it is finished the matrix will be back to its original state.
|
476
471
|
# @yield exact_cover
|
477
472
|
# @yieldparam exact_cover (Array) Array of row_ids of the rows/sets that are
|
478
473
|
# in the cover.
|
data/lib/doku/hexadoku.rb
CHANGED
@@ -7,7 +7,30 @@ module Doku
|
|
7
7
|
# This is a more complex version of Sudoku with a 16x16 grid, using
|
8
8
|
# hex digits 0 through F.
|
9
9
|
# Each instance of this class represents a particular arrangement of
|
10
|
-
# numbers written in the boxes.
|
10
|
+
# numbers (glyphs) written in the boxes.
|
11
|
+
#
|
12
|
+
# The template for this puzzle is:
|
13
|
+
# puzzle = Doku::Hexadoku.new <<END
|
14
|
+
# ....|....|....|....
|
15
|
+
# ....|....|....|....
|
16
|
+
# ....|....|....|....
|
17
|
+
# ....|....|....|....
|
18
|
+
# ----+----+----+----
|
19
|
+
# ....|....|....|....
|
20
|
+
# ....|....|....|....
|
21
|
+
# ....|....|....|....
|
22
|
+
# ....|....|....|....
|
23
|
+
# ----+----+----+----
|
24
|
+
# ....|....|....|....
|
25
|
+
# ....|....|....|....
|
26
|
+
# ....|....|....|....
|
27
|
+
# ....|....|....|....
|
28
|
+
# ----+----+----+----
|
29
|
+
# ....|....|....|....
|
30
|
+
# ....|....|....|....
|
31
|
+
# ....|....|....|....
|
32
|
+
# ....|....|....|....
|
33
|
+
# END
|
11
34
|
class Hexadoku < Puzzle
|
12
35
|
include PuzzleOnGrid
|
13
36
|
extend PuzzleOnGrid::ClassMethods # improves generated docs
|
data/lib/doku/hexamurai.rb
CHANGED
@@ -7,7 +7,46 @@ module Doku
|
|
7
7
|
# five {Hexadoku} puzzles superimposed on eachother.
|
8
8
|
# The {http://www.elektor.com/magazines/2011/july-047-august/hexamurai.1852786.lynkx Hexamurai puzzle appeared in the July/August issue of Elektor magazine}.
|
9
9
|
# Each instance of this class represents a particular arrangement of
|
10
|
-
# numbers written in the boxes.
|
10
|
+
# numbers (glyphs) written in the boxes.
|
11
|
+
#
|
12
|
+
# The template for this puzzle is:
|
13
|
+
# puzzle = Doku::Hexamurai.new <<END
|
14
|
+
# |........|........|
|
15
|
+
# |........|........|
|
16
|
+
# |........|........|
|
17
|
+
# |........|........|
|
18
|
+
# |........|........|
|
19
|
+
# |........|........|
|
20
|
+
# |........|........|
|
21
|
+
# |........|........|
|
22
|
+
# --------+--------+--------+--------
|
23
|
+
# ........|........|........|........
|
24
|
+
# ........|........|........|........
|
25
|
+
# ........|........|........|........
|
26
|
+
# ........|........|........|........
|
27
|
+
# ........|........|........|........
|
28
|
+
# ........|........|........|........
|
29
|
+
# ........|........|........|........
|
30
|
+
# ........|........|........|........
|
31
|
+
# --------+--------+--------+--------
|
32
|
+
# ........|........|........|........
|
33
|
+
# ........|........|........|........
|
34
|
+
# ........|........|........|........
|
35
|
+
# ........|........|........|........
|
36
|
+
# ........|........|........|........
|
37
|
+
# ........|........|........|........
|
38
|
+
# ........|........|........|........
|
39
|
+
# ........|........|........|........
|
40
|
+
# --------+--------+--------+--------
|
41
|
+
# |........|........|
|
42
|
+
# |........|........|
|
43
|
+
# |........|........|
|
44
|
+
# |........|........|
|
45
|
+
# |........|........|
|
46
|
+
# |........|........|
|
47
|
+
# |........|........|
|
48
|
+
# |........|........|
|
49
|
+
# END
|
11
50
|
class Hexamurai < Puzzle
|
12
51
|
include PuzzleOnGrid
|
13
52
|
extend Doku::PuzzleOnGrid::ClassMethods # improves generated docs
|
data/lib/doku/solver.rb
CHANGED
@@ -9,18 +9,13 @@ module Doku
|
|
9
9
|
# Returns the first solution found by the Dancing Links algorithm,
|
10
10
|
# or nil if there is no solution.
|
11
11
|
def solve
|
12
|
-
|
13
|
-
return nil
|
12
|
+
solutions.first
|
14
13
|
end
|
15
14
|
|
16
15
|
# An enumerator for all the solutions to the puzzle.
|
17
16
|
# @return (Enumerable)
|
18
17
|
def solutions
|
19
|
-
|
20
|
-
each_solution do |solution|
|
21
|
-
y << solution
|
22
|
-
end
|
23
|
-
end
|
18
|
+
enum_for :each_solution
|
24
19
|
end
|
25
20
|
|
26
21
|
# This method lets you iterate over each solution.
|
data/lib/doku/sudoku.rb
CHANGED
@@ -5,7 +5,22 @@ require_relative 'grid'
|
|
5
5
|
module Doku
|
6
6
|
# This class represents {http://en.wikipedia.org/wiki/Sudoku Sudoku}.
|
7
7
|
# Each instance of this class represents a particular arrangement of
|
8
|
-
# numbers written in the boxes.
|
8
|
+
# numbers (glyphs) written in the boxes.
|
9
|
+
#
|
10
|
+
# The template for this puzzle is:
|
11
|
+
# puzzle = Doku::Sudoku.new <<END
|
12
|
+
# ...|...|...
|
13
|
+
# ...|...|...
|
14
|
+
# ...|...|...
|
15
|
+
# ---+---+---
|
16
|
+
# ...|...|...
|
17
|
+
# ...|...|...
|
18
|
+
# ...|...|...
|
19
|
+
# ---+---+---
|
20
|
+
# ...|...|...
|
21
|
+
# ...|...|...
|
22
|
+
# ...|...|...
|
23
|
+
# END
|
9
24
|
class Sudoku < Puzzle
|
10
25
|
include PuzzleOnGrid
|
11
26
|
extend PuzzleOnGrid::ClassMethods # improves generated docs
|
data/spec/dancing_links_spec.rb
CHANGED
@@ -75,9 +75,9 @@ describe Doku::DancingLinks::LinkMatrix do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
describe "
|
78
|
+
describe "each_exact_cover_recursive" do
|
79
79
|
it "find the trivial cover for the trivial matrix" do
|
80
|
-
Doku::DancingLinks::LinkMatrix.new.
|
80
|
+
Doku::DancingLinks::LinkMatrix.new.enum_for(:each_exact_cover_recursive).to_a.should == [[]]
|
81
81
|
end
|
82
82
|
|
83
83
|
it "works even if final(k) < max(k)" do
|
@@ -88,7 +88,19 @@ describe Doku::DancingLinks::LinkMatrix do
|
|
88
88
|
[ 3,4, ],
|
89
89
|
[ 4,5],
|
90
90
|
[1,2,3,4,5] ]
|
91
|
-
m.
|
91
|
+
m.enum_for(:each_exact_cover_recursive).to_a.should == [[[1, 2, 3, 4, 5]]]
|
92
|
+
end
|
93
|
+
|
94
|
+
it "can find multiple solutions" do
|
95
|
+
m = Doku::DancingLinks::LinkMatrix.from_sets({
|
96
|
+
:a => [1,2, ],
|
97
|
+
:b => [ 3,4,5],
|
98
|
+
:c => [1, 3, 5],
|
99
|
+
:d => [ 2, 4, ],
|
100
|
+
})
|
101
|
+
solutions = m.enum_for(:each_exact_cover_recursive).to_a.collect { |s| s.sort }
|
102
|
+
solutions.should include [:a, :b]
|
103
|
+
solutions.should include [:c, :d]
|
92
104
|
end
|
93
105
|
end
|
94
106
|
|
@@ -136,7 +148,7 @@ describe Doku::DancingLinks::LinkMatrix do
|
|
136
148
|
[ 2,3, 6 ],
|
137
149
|
[1, 4 ],
|
138
150
|
[ 2, 7],
|
139
|
-
|
151
|
+
[ 4,5, 7],
|
140
152
|
]
|
141
153
|
@m = Doku::DancingLinks::LinkMatrix.from_sets @subsets, @universe
|
142
154
|
end
|
data/spec/solution_spec.rb
CHANGED
@@ -41,12 +41,6 @@ END
|
|
41
41
|
END
|
42
42
|
end
|
43
43
|
|
44
|
-
it "can also find the solution using Donald Knuth's recursive DLX" do
|
45
|
-
sm = @puzzle.to_link_matrix
|
46
|
-
exact_cover = sm.find_exact_cover_recursive
|
47
|
-
solution = @puzzle.exact_cover_to_solution exact_cover
|
48
|
-
solution.should == @solution
|
49
|
-
end
|
50
44
|
end
|
51
45
|
|
52
46
|
context 'given a sudoku puzzle with two solutions' do
|
@@ -64,13 +58,8 @@ END
|
|
64
58
|
..3|...|1.5
|
65
59
|
...|...|..3
|
66
60
|
END
|
67
|
-
end
|
68
61
|
|
69
|
-
|
70
|
-
solutions = @puzzle.solutions.to_a
|
71
|
-
solutions.size.should == 2
|
72
|
-
|
73
|
-
solutions.should include Doku::Sudoku.new <<END
|
62
|
+
@solution1 = Doku::Sudoku.new <<END
|
74
63
|
964|278|351
|
75
64
|
287|135|649
|
76
65
|
531|496|872
|
@@ -83,8 +72,7 @@ END
|
|
83
72
|
723|849|165
|
84
73
|
648|512|793
|
85
74
|
END
|
86
|
-
|
87
|
-
solutions.should include Doku::Sudoku.new <<END
|
75
|
+
@solution2 = Doku::Sudoku.new <<END
|
88
76
|
964|278|351
|
89
77
|
287|531|649
|
90
78
|
531|496|872
|
@@ -97,6 +85,14 @@ END
|
|
97
85
|
723|849|165
|
98
86
|
648|152|793
|
99
87
|
END
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'finds two solutions' do
|
91
|
+
solutions = @puzzle.solutions.to_a
|
92
|
+
solutions.size.should == 2
|
93
|
+
|
94
|
+
solutions.should include @solution1
|
95
|
+
solutions.should include @solution2
|
100
96
|
|
101
97
|
solutions[0].should be_a_solution_for @puzzle
|
102
98
|
solutions[1].should be_a_solution_for @puzzle
|
@@ -130,11 +126,6 @@ END
|
|
130
126
|
sc = sm.columns.min_by(&:size)
|
131
127
|
sc.size.should > 0
|
132
128
|
end
|
133
|
-
|
134
|
-
it 'finds no solutions using the recursive algorithm' do
|
135
|
-
sm = @puzzle.to_link_matrix
|
136
|
-
sm.find_exact_cover_recursive.should == nil
|
137
|
-
end
|
138
129
|
end
|
139
130
|
|
140
131
|
context 'given a hexadoku puzzle' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-02-27 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: backports
|
16
|
-
requirement: &
|
16
|
+
requirement: &12242900 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *12242900
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &12241680 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *12241680
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: bundler
|
38
|
-
requirement: &
|
38
|
+
requirement: &12240840 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *12240840
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: jeweler
|
49
|
-
requirement: &
|
49
|
+
requirement: &12256480 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 1.6.2
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *12256480
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rcov
|
60
|
-
requirement: &
|
60
|
+
requirement: &12255860 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *12255860
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
|
-
requirement: &
|
71
|
+
requirement: &12255300 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *12255300
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: watchr
|
82
|
-
requirement: &
|
82
|
+
requirement: &12253280 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *12253280
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: ruby-prof
|
93
|
-
requirement: &
|
93
|
+
requirement: &12251880 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *12251880
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: linecache19
|
104
|
-
requirement: &
|
104
|
+
requirement: &12250680 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *12250680
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: ruby-debug-base19
|
115
|
-
requirement: &
|
115
|
+
requirement: &12249640 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: 0.11.26
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *12249640
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: ruby-debug19
|
126
|
-
requirement: &
|
126
|
+
requirement: &12264740 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ! '>='
|
@@ -131,7 +131,7 @@ dependencies:
|
|
131
131
|
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *12264740
|
135
135
|
description: ! 'This gem allows you to represent Sudoku-like puzzles
|
136
136
|
|
137
137
|
(Sudoku, Hexadoku, and Hexamurai) as objects and find
|