grid_struct 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Guardfile +17 -0
- data/LICENSE.txt +22 -0
- data/README.md +326 -0
- data/Rakefile +7 -0
- data/grid_struct.gemspec +26 -0
- data/lib/grid_struct/selector.rb +38 -0
- data/lib/grid_struct/version.rb +3 -0
- data/lib/grid_struct.rb +186 -0
- data/spec/lib/grid_struct/selector_spec.rb +81 -0
- data/spec/lib/grid_struct_spec.rb +296 -0
- data/spec/spec_helper.rb +7 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8123cc6cecee6f31395c03f4f6bb71d097ac4fd1
|
4
|
+
data.tar.gz: 8a620e7b2af1da9daa5bdb595c388c535a14c16d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 64a7448a8fb6b4273d5dcf61d7625f523c5db7b9b97cc26cf66b8580a4df4c2cc2d7a28f4e785c82edd811ed305106be57c2768b1da0a909925dd600dfdae75a
|
7
|
+
data.tar.gz: 286fe7c82704872ecc924f2c414f5b0089b607623e4c2fecb79ee200ac547f3f7f7dfd3cde17e5c5755a9f5bd541f66f6df665f12d0b9288cc7fa7b34f811141
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
5
|
+
# rspec may be run, below are examples of the most common uses.
|
6
|
+
# * bundler: 'bundle exec rspec'
|
7
|
+
# * bundler binstubs: 'bin/rspec'
|
8
|
+
# * spring: 'bin/rsspec' (This will use spring if running and you have
|
9
|
+
# installed the spring binstubs per the docs)
|
10
|
+
# * zeus: 'zeus rspec' (requires the server to be started separetly)
|
11
|
+
# * 'just' rspec: 'rspec'
|
12
|
+
guard :rspec, cmd: 'bundle exec rspec' do
|
13
|
+
watch(%r{^spec/.+_spec\.rb$})
|
14
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
15
|
+
watch('spec/spec_helper.rb') { "spec" }
|
16
|
+
end
|
17
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Samuel Molinari
|
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,326 @@
|
|
1
|
+
# GridStruct
|
2
|
+
|
3
|
+
Manipulate grid like structure in Ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'grid_struct'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install grid_struct
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### Create a GridStruct
|
22
|
+
|
23
|
+
In order to create a grid, you have to pass a 2 arguments:
|
24
|
+
|
25
|
+
- ``rows``: the number of rows your grid has (the height of the grid)
|
26
|
+
- ``columns``: the number columns your grid has (the width of the grid)
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
rows = 9
|
30
|
+
columns = 5
|
31
|
+
|
32
|
+
# Create a grid of size 5x9
|
33
|
+
grid = GridStruct.new(rows, columns)
|
34
|
+
|
35
|
+
grid.size # => 45
|
36
|
+
grid.columns # => 5
|
37
|
+
grid.rows # => 9
|
38
|
+
```
|
39
|
+
|
40
|
+
It is possible to initialize the array with pre-set values.
|
41
|
+
The 3rd argument must be an array.
|
42
|
+
|
43
|
+
If we want to initialize the following grid:
|
44
|
+
|
45
|
+
```
|
46
|
+
+---+---+---+
|
47
|
+
| X | O | O |
|
48
|
+
+---+---+---+
|
49
|
+
| X | x | O |
|
50
|
+
+---+---+---+
|
51
|
+
| O | X | O |
|
52
|
+
+---+---+---+
|
53
|
+
|
54
|
+
```
|
55
|
+
|
56
|
+
Use the following array structure:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
# +-----------+-----------+-----------+
|
60
|
+
# | ROW 0 | ROW 1 | ROW 2 |
|
61
|
+
# +---------+-----------+-----------+-----------+
|
62
|
+
# | COLUMNS | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 | 2 |
|
63
|
+
grid_data = ['X','O','O','X','X','O','O','X','O']
|
64
|
+
|
65
|
+
tic_tac_toe = GridStruct.new(3, 3, grid_data)
|
66
|
+
```
|
67
|
+
|
68
|
+
``GridStruct`` actually store your values extactly the same way, in a 1-dimentional array.
|
69
|
+
|
70
|
+
### Basics
|
71
|
+
|
72
|
+
Now you know how to create grids, it's time to learn how to use our new data structure.
|
73
|
+
|
74
|
+
#### Read the data store
|
75
|
+
|
76
|
+
As mentionned above, your data are stored in a 1-dimentional array.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
tic_tac_toe.store # => ["X","O","O","X","X","O","O","X","O"]
|
80
|
+
|
81
|
+
GridStruct.new(9,9).store # => []
|
82
|
+
```
|
83
|
+
|
84
|
+
As you can see, the ``store`` always starts as an empty array unless you decide to pre-fill the grid.
|
85
|
+
|
86
|
+
#### Set value
|
87
|
+
|
88
|
+
To set a value, pass the row and column you want to fill, and a block that will return the value
|
89
|
+
|
90
|
+
```
|
91
|
+
GridStruct#set(row, column) { value }
|
92
|
+
```
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
sudoku_grid = GridStruct.new(9,9)
|
96
|
+
|
97
|
+
sudoku_grid.set(0,0) { 'Hello World' }
|
98
|
+
sudoku_grid.store # => ["Hello World"]
|
99
|
+
|
100
|
+
sudoku_grid.set(1,0) { 'Row: 1, Col: 0' }
|
101
|
+
sudoku_grid.store # => ["Hello World",nil,nil,nil,nil,nil,nil,nil,"Row: 1, Col: 0"]
|
102
|
+
```
|
103
|
+
|
104
|
+
#### Get value
|
105
|
+
|
106
|
+
To get a value at a specific coordinate, use th ``get`` method.
|
107
|
+
|
108
|
+
```
|
109
|
+
GridStruct#get(row, column) # => value
|
110
|
+
```
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
sudoku_grid.get(1,0) # => "Row: 1, Col: 0"
|
114
|
+
```
|
115
|
+
|
116
|
+
### Iterate
|
117
|
+
|
118
|
+
You can iterate through the grid using the each method
|
119
|
+
|
120
|
+
```
|
121
|
+
GridStruct#each { |value, row, column| # Do something }
|
122
|
+
```
|
123
|
+
|
124
|
+
### Mass update
|
125
|
+
|
126
|
+
#### Grid
|
127
|
+
|
128
|
+
Incase you need to update each element within the grid, use the ``map!`` method
|
129
|
+
|
130
|
+
```
|
131
|
+
GridStruct#map! { |value, row, column| # Return new value }
|
132
|
+
```
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
grid = GridStruct.new(3,3)
|
136
|
+
grid.map! { |value, row, column| (row * grid.columns) + column }
|
137
|
+
|
138
|
+
grid.store # => [0,1,2,3,4,5,6,7,8]
|
139
|
+
```
|
140
|
+
|
141
|
+
#### Row
|
142
|
+
|
143
|
+
You can update a specific row if needed, for example, if we want to update the middle row
|
144
|
+
|
145
|
+
```
|
146
|
+
GridStruct#map_row! { |value, column| # Return new value }
|
147
|
+
```
|
148
|
+
|
149
|
+
```
|
150
|
+
+---+---+---+
|
151
|
+
| 0 | 1 | 2 |
|
152
|
+
+---+---+---+
|
153
|
+
Update this row → | 3 | 4 | 5 |
|
154
|
+
+---+---+---+
|
155
|
+
| 6 | 7 | 8 |
|
156
|
+
+---+---+---+
|
157
|
+
```
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
grid.map_row!(1) { |value| value * 10 }
|
161
|
+
|
162
|
+
grid.store # => [0,1,2,30,40,50,6,7,8]
|
163
|
+
```
|
164
|
+
|
165
|
+
|
166
|
+
#### Column
|
167
|
+
|
168
|
+
You can update a specific row if needed, for example, if we want to update the middle row
|
169
|
+
|
170
|
+
```
|
171
|
+
GridStruct#map_column! { |value, row| # Return new value }
|
172
|
+
```
|
173
|
+
|
174
|
+
```
|
175
|
+
Update this columns
|
176
|
+
↓
|
177
|
+
+---+---+---+
|
178
|
+
| 0 | 1 | 2 |
|
179
|
+
+---+---+---+
|
180
|
+
| 3 | 4 | 5 |
|
181
|
+
+---+---+---+
|
182
|
+
| 6 | 7 | 8 |
|
183
|
+
+---+---+---+
|
184
|
+
```
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
grid.map_column!(2) { |value| value * 10 }
|
188
|
+
|
189
|
+
grid.store # => [0,1,20,3,4,50,6,7,80]
|
190
|
+
```
|
191
|
+
|
192
|
+
### Selectors
|
193
|
+
|
194
|
+
Selector gives you access to line of values within the grid, and allows you to
|
195
|
+
only act on that line. Each selector return a (or an array of) GridStruct::Selector.
|
196
|
+
|
197
|
+
#### Overview
|
198
|
+
|
199
|
+
A selector has the following instances:
|
200
|
+
|
201
|
+
- ``grid``: The grid it is selecting from
|
202
|
+
- ``indexes``: An array of indexes mapping to the selected values in the grid store
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
grid = GridStruct.new(3,3)
|
206
|
+
|
207
|
+
grid.map! do |value, row, column|
|
208
|
+
(row * grid.columns + column) * 10
|
209
|
+
end
|
210
|
+
|
211
|
+
grid.row(0) # => #<GridStruct::Selector:0x007fb3d11decf0 @grid=#<GridStruct:0x007fb3d15541f0 @columns=3, @rows=3, @store=[0, 10, 20, 30, 40, 50, 60, 70, 80]>, @indexes=[0, 1, 2]>
|
212
|
+
```
|
213
|
+
|
214
|
+
You can retrieve and update values using ``[]``. It will map the action to the grid.
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
first_row = grid.row(0)
|
218
|
+
|
219
|
+
first_row.to_a # => [0,10,20]
|
220
|
+
|
221
|
+
first_row[0] # => 0
|
222
|
+
first_row[1] # => 10
|
223
|
+
first_row[2] # => 20
|
224
|
+
|
225
|
+
first_row[0] = -100
|
226
|
+
|
227
|
+
grid.to_a # => [-100,10,20,30,40,50,60,70,80]
|
228
|
+
|
229
|
+
```
|
230
|
+
|
231
|
+
#### Row
|
232
|
+
|
233
|
+
To select a specific row, use the method ``row``
|
234
|
+
|
235
|
+
```
|
236
|
+
GridStruct#row(row_number)
|
237
|
+
```
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
rows = []
|
241
|
+
|
242
|
+
# Fetch selector for every rows
|
243
|
+
grid.rows.times.each do |row_index|
|
244
|
+
rows[row_index] = grid.row(row_index)
|
245
|
+
end
|
246
|
+
```
|
247
|
+
|
248
|
+
#### Column
|
249
|
+
|
250
|
+
To select a specific column, use the method ``column``
|
251
|
+
|
252
|
+
```
|
253
|
+
GridStruct#column(column_number)
|
254
|
+
```
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
columns = []
|
258
|
+
|
259
|
+
# Fetch selector for every columns
|
260
|
+
grid.columns.times.each do |column_index|
|
261
|
+
columns[column_index] = grid.column(column_index)
|
262
|
+
end
|
263
|
+
```
|
264
|
+
|
265
|
+
#### Diagonals
|
266
|
+
|
267
|
+
The diagonals retrieval works slightly differently from the two previous methods.
|
268
|
+
In order to retrieve diagonals, you must provide the coordinates of a cell in the grid. This will retrieve the diagonals that cross through that specific cell.
|
269
|
+
The returned array can be of size 0 (no diagonals found, for example, in a grid of size 1), 1 (when retrieving diagonals from the corners of the grid) or 2.
|
270
|
+
|
271
|
+
```
|
272
|
+
GridStruct#diagonals(1,1) # => [#<GridStruct::Selector ...>, #<GridStruct::Selector ...>]
|
273
|
+
```
|
274
|
+
|
275
|
+
```ruby
|
276
|
+
diagonals = grid.diagonals(1,1)
|
277
|
+
|
278
|
+
diagonals.first.to_a # => [0,40,80]
|
279
|
+
diagonals.last.to_a # => [30,40,60]
|
280
|
+
|
281
|
+
corner_diagonal = grid.diagonals(0,0) # fetch diagonals from top left corner
|
282
|
+
|
283
|
+
corner_diagonal.size # => 1
|
284
|
+
corner_diagonal.first.to_a # => [0,40,80]
|
285
|
+
```
|
286
|
+
|
287
|
+
#### Slice
|
288
|
+
|
289
|
+
Imagine a slice as a projection of a section of your grid.
|
290
|
+
Use the ``slice`` method to access a single slice.
|
291
|
+
|
292
|
+
```
|
293
|
+
GridStruct#slice(slice_index, rows: slice_rows, columns: slice_columns) # => #<GridStruct::Selector ...>
|
294
|
+
```
|
295
|
+
|
296
|
+
In the following example, we are manipulating a sudoku grid, and we want to access the middle 3x3 square
|
297
|
+
|
298
|
+
```ruby
|
299
|
+
sudoku_grid = GridStruct.new(9,9)
|
300
|
+
|
301
|
+
sudoku_grid.map! do |v, r, c|
|
302
|
+
(r * sudoku_grid.columns) + c + 1
|
303
|
+
end
|
304
|
+
|
305
|
+
sudoku_grid.slice(4, rows: 3, columns: 3) # => #<GridStruct:0x007fb3d16e4e70 @columns=3, @rows=3, @store=[31, 32, 33, 40, 41, 42, 49, 50, 51]>
|
306
|
+
```
|
307
|
+
|
308
|
+
Use the ``each_slice`` method to go through each slices
|
309
|
+
|
310
|
+
```
|
311
|
+
GridStruct#each_slice(slice_rows,slice_columns) { |slice, slice_index| # Do something }
|
312
|
+
```
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
sudoku_grid.each_slice(3,3) do |slice, index|
|
316
|
+
# Do something
|
317
|
+
end
|
318
|
+
```
|
319
|
+
|
320
|
+
## Contributing
|
321
|
+
|
322
|
+
1. Fork it
|
323
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
324
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
325
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
326
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/grid_struct.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'grid_struct/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "grid_struct"
|
8
|
+
spec.version = GridStruct::VERSION
|
9
|
+
spec.authors = ["Samuel Molinari"]
|
10
|
+
spec.email = ["samuel@molinari.me"]
|
11
|
+
spec.description = %q{Grid data structure}
|
12
|
+
spec.summary = %q{Handle a grid data structure}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
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.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "guard"
|
25
|
+
spec.add_development_dependency "guard-rspec"
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class ::GridStruct::Selector
|
2
|
+
|
3
|
+
attr_reader :grid, :indexes, :rows, :columns
|
4
|
+
|
5
|
+
def initialize(grid,*indexes)
|
6
|
+
@grid = grid
|
7
|
+
@indexes = indexes.freeze
|
8
|
+
end
|
9
|
+
|
10
|
+
def dimensions(rows,columns)
|
11
|
+
@rows = rows
|
12
|
+
@columns = columns
|
13
|
+
return self
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](i)
|
17
|
+
mapped_index = @indexes[i]
|
18
|
+
mapped_index.nil? ? nil : @grid.store[mapped_index]
|
19
|
+
end
|
20
|
+
|
21
|
+
def []=(i,value)
|
22
|
+
mapped_index = @indexes[i]
|
23
|
+
@grid.store[mapped_index] = value unless mapped_index.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_a
|
27
|
+
@indexes.size.times.map do |i|
|
28
|
+
self[i]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_grid(rows = nil,columns = nil)
|
33
|
+
rows ||= @rows
|
34
|
+
columns ||= @columns
|
35
|
+
GridStruct.new(rows,columns,to_a)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/grid_struct.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'grid_struct/version'
|
2
|
+
require 'grid_struct/selector'
|
3
|
+
|
4
|
+
class GridStruct
|
5
|
+
|
6
|
+
attr_reader :store,
|
7
|
+
:rows,
|
8
|
+
:columns
|
9
|
+
|
10
|
+
def initialize(rows, columns, store = [])
|
11
|
+
@rows = rows
|
12
|
+
@columns = columns
|
13
|
+
@store = store || []
|
14
|
+
end
|
15
|
+
|
16
|
+
def set(row,column)
|
17
|
+
@store[get_index(row,column)] = yield
|
18
|
+
end
|
19
|
+
|
20
|
+
def map!
|
21
|
+
size.times.map do |index|
|
22
|
+
value = @store[index]
|
23
|
+
row_column = get_row_column_at(index)
|
24
|
+
@store[index] = yield(value, row_column[:row], row_column[:column])
|
25
|
+
end
|
26
|
+
return self
|
27
|
+
end
|
28
|
+
|
29
|
+
def map_row!(n)
|
30
|
+
@columns.times.each do |column|
|
31
|
+
index = get_index(n,column)
|
32
|
+
value = @store[index]
|
33
|
+
@store[index] = yield(value,column)
|
34
|
+
end
|
35
|
+
return self
|
36
|
+
end
|
37
|
+
|
38
|
+
def map_column!(n)
|
39
|
+
@rows.times.each do |row|
|
40
|
+
index = get_index(row,n)
|
41
|
+
value = @store[index]
|
42
|
+
@store[index] = yield(value,row)
|
43
|
+
end
|
44
|
+
return self
|
45
|
+
end
|
46
|
+
|
47
|
+
def each
|
48
|
+
@store.fill(nil,@store.size...size).each.with_index do |value, index|
|
49
|
+
row_column = get_row_column_at(index)
|
50
|
+
yield(value,row_column[:row],row_column[:column])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def each_slice(rows,columns)
|
55
|
+
sub_rows = (@rows / rows.to_f).ceil
|
56
|
+
sub_columns = (@columns / columns.to_f).ceil
|
57
|
+
|
58
|
+
sub_rows.times.each do |sub_row|
|
59
|
+
sub_columns.ceil.times.each do |sub_column|
|
60
|
+
|
61
|
+
index = sub_column + (sub_row * sub_columns)
|
62
|
+
yield(slice(index, rows: rows, columns: columns), index)
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def get(row,column)
|
69
|
+
@store[get_index(row,column)]
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# TODO Improve
|
74
|
+
def slice(index,dimensions)
|
75
|
+
rows = dimensions[:rows]
|
76
|
+
columns = dimensions[:columns]
|
77
|
+
sub_columns = (@columns / columns.to_f).ceil
|
78
|
+
|
79
|
+
sub_row = index / sub_columns
|
80
|
+
sub_column = index - (sub_row * sub_columns)
|
81
|
+
|
82
|
+
indexes = []
|
83
|
+
rows.times.each do |r|
|
84
|
+
start_index = (r * @columns) +
|
85
|
+
(sub_row * rows * @columns) +
|
86
|
+
(sub_column * columns)
|
87
|
+
end_index = start_index + columns
|
88
|
+
|
89
|
+
start_row = get_row_column_at(start_index)[:row]
|
90
|
+
end_row = get_row_column_at(end_index)[:row]
|
91
|
+
|
92
|
+
if start_row != end_row
|
93
|
+
extras = [0,(end_index - @columns)].max % @columns
|
94
|
+
end_index -= extras
|
95
|
+
end
|
96
|
+
|
97
|
+
final_row_indexes = (start_index...end_index).to_a
|
98
|
+
final_row_indexes.fill(nil,final_row_indexes.size...columns)
|
99
|
+
indexes += final_row_indexes
|
100
|
+
end
|
101
|
+
|
102
|
+
return GridStruct::Selector.new(self, *indexes).dimensions(rows,columns)
|
103
|
+
end
|
104
|
+
|
105
|
+
def row(n)
|
106
|
+
start_index = (n * @columns)
|
107
|
+
end_index = start_index + @columns
|
108
|
+
GridStruct::Selector.new(self,*(start_index...end_index))
|
109
|
+
end
|
110
|
+
|
111
|
+
def column(n)
|
112
|
+
GridStruct::Selector.new(self,*@rows.times.map do |row|
|
113
|
+
get_index(row,n)
|
114
|
+
end)
|
115
|
+
end
|
116
|
+
|
117
|
+
def diagonals(row,column)
|
118
|
+
selectors = []
|
119
|
+
|
120
|
+
first = diagonal_builder({row: row, column: column})
|
121
|
+
second = diagonal_builder({row: row, column: column}, 1, -1)
|
122
|
+
|
123
|
+
selectors.push(GridStruct::Selector.new(self, *first)) if first.size > 1
|
124
|
+
selectors.push(GridStruct::Selector.new(self, *second)) if second.size > 1
|
125
|
+
|
126
|
+
return selectors
|
127
|
+
end
|
128
|
+
|
129
|
+
def size
|
130
|
+
@rows * @columns
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_a
|
134
|
+
store_size = @store.size
|
135
|
+
return @store.dup.fill(nil,store_size...size)
|
136
|
+
end
|
137
|
+
|
138
|
+
def ==(other)
|
139
|
+
@store == other.instance_variable_get(:@store)
|
140
|
+
end
|
141
|
+
|
142
|
+
protected
|
143
|
+
|
144
|
+
def get_index(row,column)
|
145
|
+
(row * @columns) + column
|
146
|
+
end
|
147
|
+
|
148
|
+
def get_row_column_at(index)
|
149
|
+
row = index / @columns
|
150
|
+
column = index - (row * @columns)
|
151
|
+
return { row: row, column: column }
|
152
|
+
end
|
153
|
+
|
154
|
+
def diagonal_builder(coordinates, row_direction = 1, column_direction = 1, diagonal_indexes = [], action = :push)
|
155
|
+
row = coordinates[:row]
|
156
|
+
column = coordinates[:column]
|
157
|
+
index = get_index(row,column)
|
158
|
+
|
159
|
+
if !diagonal_indexes.include?(index) &&
|
160
|
+
row >= 0 &&
|
161
|
+
column >= 0 &&
|
162
|
+
row < @rows &&
|
163
|
+
column < @columns
|
164
|
+
|
165
|
+
diagonal_indexes.method(action).call(get_index(row,column))
|
166
|
+
|
167
|
+
diagonal_builder({ row: row - (row_direction * 1),
|
168
|
+
column: column - (column_direction * 1) },
|
169
|
+
row_direction,
|
170
|
+
column_direction,
|
171
|
+
diagonal_indexes,
|
172
|
+
:unshift)
|
173
|
+
|
174
|
+
diagonal_builder({ row: row + (row_direction * 1),
|
175
|
+
column: column + (column_direction * 1) },
|
176
|
+
row_direction,
|
177
|
+
column_direction,
|
178
|
+
diagonal_indexes,
|
179
|
+
:push)
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
return diagonal_indexes
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ::GridStruct::Selector do
|
4
|
+
|
5
|
+
let(:grid) { GridStruct.new(9,9) }
|
6
|
+
let(:indexes) { [0,3,34,57] }
|
7
|
+
subject(:selector) { described_class.new(grid,*indexes) }
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
grid.map! do |value,row,column|
|
11
|
+
((row * grid.columns) + column) * 2
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it { is_expected.to have_attributes(grid: grid,
|
16
|
+
indexes: indexes) }
|
17
|
+
|
18
|
+
describe '#[]' do
|
19
|
+
it 'retrieve the x element in the current selection' do
|
20
|
+
expect(selector[0]).to eq 0
|
21
|
+
expect(selector[1]).to eq 6
|
22
|
+
expect(selector[2]).to eq 68
|
23
|
+
expect(selector[3]).to eq 114
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when mapped index is nil' do
|
27
|
+
let(:broken_selector) { described_class.new(grid, [0,nil,nil,nil]) }
|
28
|
+
|
29
|
+
it 'returns nil' do
|
30
|
+
expect(broken_selector[1]).to be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#[]=' do
|
36
|
+
it 'sets the value in the grid through the selector' do
|
37
|
+
selector[0] = -10
|
38
|
+
selector[1] = -3
|
39
|
+
selector[2] = 'hello world'
|
40
|
+
expect(grid.store[0]).to eq -10
|
41
|
+
expect(grid.store[3]).to eq -3
|
42
|
+
expect(grid.store[34]).to eq 'hello world'
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when mapped index is nil' do
|
46
|
+
let(:broken_selector) { described_class.new(grid, [0,nil,nil,nil]) }
|
47
|
+
|
48
|
+
it 'ignores action' do
|
49
|
+
store = grid.store
|
50
|
+
broken_selector[1] = 100
|
51
|
+
expect(grid.store).to eq store
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#dimensions' do
|
57
|
+
it 'sets the virtual dimensions of the current selection' do
|
58
|
+
selector.dimensions(2,3)
|
59
|
+
expect(selector.rows).to eq 2
|
60
|
+
expect(selector.columns).to eq 3
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#to_a' do
|
65
|
+
it 'fetches and returns selector values into an array' do
|
66
|
+
expect(selector.to_a).to eq [0,6,68,114]
|
67
|
+
end
|
68
|
+
it 'does not modify the grid when manipulating retuning array' do
|
69
|
+
array = selector.to_a
|
70
|
+
array[0] = -100
|
71
|
+
expect(grid.store[0]).not_to eq -100
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'to_grid' do
|
76
|
+
it 'converts current selection into a new grid, with the given dimensions' do
|
77
|
+
expect(selector.to_grid(2,2)).to eq GridStruct.new(2,2,[0,6,68,114])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,296 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ::GridStruct do
|
4
|
+
|
5
|
+
let(:sudoku_grid) { GridStruct.new(9,9) }
|
6
|
+
before(:each) do
|
7
|
+
# Fill grid as such
|
8
|
+
#
|
9
|
+
# |----|----|----|----|----|----|----|----|----|
|
10
|
+
# | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
11
|
+
# |----|----|----|----|----|----|----|----|----|
|
12
|
+
# | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
|
13
|
+
# |----|----|----|----|----|----|----|----|----|
|
14
|
+
# | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
|
15
|
+
# |----|----|----|----|----|----|----|----|----|
|
16
|
+
# | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
|
17
|
+
# |----|----|----|----|----|----|----|----|----|
|
18
|
+
# | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
|
19
|
+
# |----|----|----|----|----|----|----|----|----|
|
20
|
+
# | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
|
21
|
+
# |----|----|----|----|----|----|----|----|----|
|
22
|
+
# | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
|
23
|
+
# |----|----|----|----|----|----|----|----|----|
|
24
|
+
# | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 |
|
25
|
+
# |----|----|----|----|----|----|----|----|----|
|
26
|
+
# | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
|
27
|
+
# |----|----|----|----|----|----|----|----|----|
|
28
|
+
|
29
|
+
sudoku_grid.map! do |value, row, column|
|
30
|
+
row * sudoku_grid.columns + column
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:rows) { 2 }
|
35
|
+
let(:columns) { 3 }
|
36
|
+
subject(:grid) { GridStruct.new(rows, columns) }
|
37
|
+
|
38
|
+
it { is_expected.to have_attributes(rows: rows,
|
39
|
+
columns: columns) }
|
40
|
+
|
41
|
+
describe '#size' do
|
42
|
+
it 'is the multiplication of with and height' do
|
43
|
+
expect(grid.size).to be rows * columns
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#set' do
|
48
|
+
it 'sets the value at the given row and column' do
|
49
|
+
grid.set(0,0) { 1 }
|
50
|
+
store = grid.instance_variable_get(:@store)
|
51
|
+
expect(store).to eq [1]
|
52
|
+
|
53
|
+
grid.set(1,0) { 2 }
|
54
|
+
store = grid.instance_variable_get(:@store)
|
55
|
+
expect(store).to eq [1,nil,nil,2]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#each' do
|
60
|
+
before(:each) do
|
61
|
+
grid.instance_variable_set(:@store, [0,1,2,3,4,5])
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'iterates through each elements of the grid (left to right, top to bottom)' do
|
65
|
+
values = []
|
66
|
+
grid.each do |element,row,column|
|
67
|
+
values[(row * grid.columns) + column] = element
|
68
|
+
end
|
69
|
+
expect(values.size).to be grid.size
|
70
|
+
expect(values).to eq grid.to_a
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#map!' do
|
75
|
+
it 'replaces all the elements in the grid' do
|
76
|
+
grid.map! do |value, row, column|
|
77
|
+
(row + 1) * (column + 1)
|
78
|
+
end
|
79
|
+
store = grid.instance_variable_get(:@store)
|
80
|
+
expect(store).to eq [1,2,3,2,4,6]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#map_row!' do
|
85
|
+
it 'replaces the elements in the targeted row' do
|
86
|
+
grid.map_row!(0) { |value, column| column }
|
87
|
+
store = grid.instance_variable_get(:@store)
|
88
|
+
expect(store).to eq [0,1,2]
|
89
|
+
|
90
|
+
grid.map_row!(1) { |value, column| column**2 }
|
91
|
+
store = grid.instance_variable_get(:@store)
|
92
|
+
expect(store).to eq [0,1,2,0,1,4]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#map_column!' do
|
97
|
+
it 'replaces the elements in the targeted column' do
|
98
|
+
grid.map_column!(0) { |value, row| row }
|
99
|
+
store = grid.instance_variable_get(:@store)
|
100
|
+
expect(store).to eq [0,nil,nil,1]
|
101
|
+
|
102
|
+
grid.map_column!(1) { |value, row| row + 1 }
|
103
|
+
store = grid.instance_variable_get(:@store)
|
104
|
+
expect(store).to eq [0,1,nil,1,2]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe '#each_slice' do
|
109
|
+
it 'iterates through sub-grids of the given rows and columns' do
|
110
|
+
sub_grids = []
|
111
|
+
sudoku_grid.each_slice(3,3) do |sub_grid,index|
|
112
|
+
sub_grids[index] = sub_grid
|
113
|
+
end
|
114
|
+
expect(sub_grids[0].to_a).to eq [0,1,2,9,10,11,18,19,20]
|
115
|
+
expect(sub_grids[1].to_a).to eq [3,4,5,12,13,14,21,22,23]
|
116
|
+
expect(sub_grids[2].to_a).to eq [6,7,8,15,16,17,24,25,26]
|
117
|
+
expect(sub_grids[3].to_a).to eq [27,28,29,36,37,38,45,46,47]
|
118
|
+
expect(sub_grids[4].to_a).to eq [30,31,32,39,40,41,48,49,50]
|
119
|
+
expect(sub_grids[5].to_a).to eq [33,34,35,42,43,44,51,52,53]
|
120
|
+
expect(sub_grids[6].to_a).to eq [54,55,56,63,64,65,72,73,74]
|
121
|
+
expect(sub_grids[7].to_a).to eq [57,58,59,66,67,68,75,76,77]
|
122
|
+
expect(sub_grids[8].to_a).to eq [60,61,62,69,70,71,78,79,80]
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'when slice is equal to the grid' do
|
126
|
+
it 'iterates a single time with a copy of the current grid' do
|
127
|
+
selector = nil
|
128
|
+
sudoku_grid.each_slice(9,9) do |sub_grid|
|
129
|
+
selector = sub_grid
|
130
|
+
end
|
131
|
+
expect(selector.to_grid).to eq sudoku_grid
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when slice is bigger than the grid' do
|
136
|
+
it 'iterates a single time with content of current grid with extra edges' do
|
137
|
+
selector = nil
|
138
|
+
sudoku_grid.each_slice(10,10) do |sub_grid|
|
139
|
+
selector = sub_grid
|
140
|
+
end
|
141
|
+
sudoku_grid.rows.times.each do |row_index|
|
142
|
+
expect(selector.to_grid.row(row_index).to_a).to eq (sudoku_grid.row(row_index).to_a + [nil])
|
143
|
+
end
|
144
|
+
sudoku_grid.columns.times.each do |column_index|
|
145
|
+
expect(selector.to_grid.column(column_index).to_a).to eq (sudoku_grid.column(column_index).to_a + [nil])
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when last slice bleeds out of the grid' do
|
151
|
+
it 'nullify the extras' do
|
152
|
+
sub_grids = []
|
153
|
+
sudoku_grid.each_slice(2,4) do |sub_grid,index|
|
154
|
+
sub_grids[index] = sub_grid
|
155
|
+
end
|
156
|
+
expect(sub_grids[2].to_a).to eq [8,nil,nil,nil,17,nil,nil,nil]
|
157
|
+
expect(sub_grids[5].to_a).to eq [26,nil,nil,nil,35,nil,nil,nil]
|
158
|
+
expect(sub_grids[8].to_a).to eq [44,nil,nil,nil,53,nil,nil,nil]
|
159
|
+
expect(sub_grids[11].to_a).to eq [62,nil,nil,nil,71,nil,nil,nil]
|
160
|
+
expect(sub_grids[12].to_a).to eq [72,73,74,75,nil,nil,nil,nil]
|
161
|
+
expect(sub_grids[13].to_a).to eq [76,77,78,79,nil,nil,nil,nil]
|
162
|
+
expect(sub_grids[14].to_a).to eq [80,nil,nil,nil,nil,nil,nil,nil]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe '#get' do
|
168
|
+
context 'a non-set cell' do
|
169
|
+
it 'returns nil' do
|
170
|
+
expect(grid.get(0,0)).to be_nil
|
171
|
+
end
|
172
|
+
end
|
173
|
+
context 'an already set cell' do
|
174
|
+
before(:each) do
|
175
|
+
grid.instance_variable_set(:@store, [nil,8,nil,9,2,nil])
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'returns the stored value at the given row and column' do
|
179
|
+
expect(grid.get(0,0)).to be_nil
|
180
|
+
expect(grid.get(0,1)).to be 8
|
181
|
+
expect(grid.get(0,2)).to be_nil
|
182
|
+
expect(grid.get(1,0)).to be 9
|
183
|
+
expect(grid.get(1,1)).to be 2
|
184
|
+
expect(grid.get(1,2)).to be_nil
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe '#row' do
|
190
|
+
before(:each) do
|
191
|
+
grid.instance_variable_set(:@store, [nil,8,nil,9,2,nil])
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'returns a selector' do
|
195
|
+
expect(grid.row(0)).to be_kind_of(GridStruct::Selector)
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'retrieves a selector of the requested row' do
|
199
|
+
expect(grid.row(0).to_a).to eq [nil,8,nil]
|
200
|
+
expect(grid.row(1).to_a).to eq [9,2,nil]
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe '#column' do
|
205
|
+
before(:each) do
|
206
|
+
grid.instance_variable_set(:@store, [nil,8,nil,9,2,nil])
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'returns a selector' do
|
210
|
+
expect(grid.column(0)).to be_kind_of(GridStruct::Selector)
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'retrieves a selector of the requested column' do
|
214
|
+
expect(grid.column(0).to_a).to eq [nil,9]
|
215
|
+
expect(grid.column(1).to_a).to eq [8,2]
|
216
|
+
expect(grid.column(2).to_a).to eq [nil,nil]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe '#diagonals' do
|
221
|
+
it 'returns an array' do
|
222
|
+
expect(grid.diagonals(0,0)).to be_kind_of Array
|
223
|
+
end
|
224
|
+
|
225
|
+
context 'when fetching diagonals not from a corner' do
|
226
|
+
it 'returns 2 selectors' do
|
227
|
+
diagonals = sudoku_grid.diagonals(4,4)
|
228
|
+
expect(diagonals.size).to be 2
|
229
|
+
expect(diagonals.first).to be_kind_of(GridStruct::Selector)
|
230
|
+
expect(diagonals.last).to be_kind_of(GridStruct::Selector)
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'returns the diagonals crossing the given coordinates' do
|
234
|
+
diagonals = sudoku_grid.diagonals(4,4)
|
235
|
+
expect(diagonals.first.to_a).to eq [0,10,20,30,40,50,60,70,80]
|
236
|
+
expect(diagonals.last.to_a).to eq [8,16,24,32,40,48,56,64,72]
|
237
|
+
end
|
238
|
+
|
239
|
+
context 'the returned selectors' do
|
240
|
+
it 'approprietly modify its matching element' do
|
241
|
+
diagonals = sudoku_grid.diagonals(4,4)
|
242
|
+
diagonals.first[4] = -100
|
243
|
+
expect(sudoku_grid.get(4,4))
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'when fetching diagonals from a corner' do
|
249
|
+
it 'only returns 1 diagonal selector' do
|
250
|
+
expect(sudoku_grid.diagonals(0,0).size).to be 1
|
251
|
+
expect(sudoku_grid.diagonals(0,sudoku_grid.columns - 1).size).to be 1
|
252
|
+
expect(sudoku_grid.diagonals(sudoku_grid.rows - 1,0).size).to be 1
|
253
|
+
expect(sudoku_grid.diagonals(sudoku_grid.rows - 1, sudoku_grid.columns - 1).size).to be 1
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe '#slice' do
|
259
|
+
it 'returns a selector' do
|
260
|
+
expect(sudoku_grid.slice(0, rows: 3, columns: 3)).to be_kind_of(GridStruct::Selector)
|
261
|
+
end
|
262
|
+
|
263
|
+
context 'the returned selector' do
|
264
|
+
it 'modifies its matching element' do
|
265
|
+
slice = sudoku_grid.slice(0, rows: 3, columns: 3)
|
266
|
+
slice[4] = -100
|
267
|
+
expect(sudoku_grid.get(1,1)).to eq -100
|
268
|
+
end
|
269
|
+
|
270
|
+
context 'when slice goes out of bound' do
|
271
|
+
it 'adds extras when converting to grid' do
|
272
|
+
slice = sudoku_grid.slice(2, rows: 2, columns: 4)
|
273
|
+
expect(slice.to_grid.to_a).to eq [8,nil,nil,nil,17,nil,nil,nil]
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
describe '#to_a' do
|
280
|
+
it 'returns an array matching size of the grid' do
|
281
|
+
expect(grid.to_a.size).to be grid.size
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'returns content of grid store' do
|
285
|
+
grid.instance_variable_set(:@store, [0,1,2,3,4,5])
|
286
|
+
expect(grid.to_a).to eq [0,1,2,3,4,5]
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'returns a copy' do
|
290
|
+
grid.instance_variable_set(:@store, [0,1,2,3,4,5])
|
291
|
+
array = grid.to_a
|
292
|
+
array[0] = 100
|
293
|
+
expect(grid.get(0,0)).to be 0
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: grid_struct
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Samuel Molinari
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-17 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.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '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: guard
|
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-rspec
|
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
|
+
description: Grid data structure
|
84
|
+
email:
|
85
|
+
- samuel@molinari.me
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- .rspec
|
92
|
+
- Gemfile
|
93
|
+
- Guardfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- grid_struct.gemspec
|
98
|
+
- lib/grid_struct.rb
|
99
|
+
- lib/grid_struct/selector.rb
|
100
|
+
- lib/grid_struct/version.rb
|
101
|
+
- spec/lib/grid_struct/selector_spec.rb
|
102
|
+
- spec/lib/grid_struct_spec.rb
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
homepage: ''
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.0.6
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Handle a grid data structure
|
128
|
+
test_files:
|
129
|
+
- spec/lib/grid_struct/selector_spec.rb
|
130
|
+
- spec/lib/grid_struct_spec.rb
|
131
|
+
- spec/spec_helper.rb
|