aoc_rb_helpers 0.0.4 → 0.0.6
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 +4 -4
- data/CHANGELOG.md +25 -1
- data/lib/aoc_rb_helpers/aoc_input.rb +37 -0
- data/lib/aoc_rb_helpers/grid.rb +138 -1
- data/lib/aoc_rb_helpers/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be89f829468b5e0144844944ec0bd8a96973e45d9200cf32b8b23de30f3a0a4b
|
4
|
+
data.tar.gz: 2619c91954216ba37620673a97bdd3f27b74e47e8094a418444fa317363b5270
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd7f615183ca42cd9bc8fcc2febe8a2d688c781dde3cdff9819aae9cd2157e22ac0943c1076c647750ceb1cdd6aee303d80aa86abdf446f7bcc74fdddd3ef9c8
|
7
|
+
data.tar.gz: c0d45da087522c0a1ce92c43b946674c36e79bf1c2cc6d6e1aa65679b5c32b8141235b3dfe663f8c849ef065936725ccbb288fd3745557e432efa09b2087278d
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7
7
|
## [Unreleased]
|
8
8
|
- No unreleased changes!
|
9
9
|
|
10
|
+
## [0.0.6]
|
11
|
+
### Added
|
12
|
+
- AocInput#single_line - Strips newline characters from single line puzzle inputs
|
13
|
+
|
14
|
+
## [0.0.5]
|
15
|
+
### Added
|
16
|
+
- AocInput#process_each_line - Processes each line of the input data using the provided block
|
17
|
+
- Grid#includes_coords? - Returns `true` if the provided coordinates exist within the bounds of the grid
|
18
|
+
- Grid#beyond_grid? - Returns `true` if the provided coordinates exceed the bounds of the grid
|
19
|
+
- Grid#locate(value) - Returns the first coordinates within the grid containing the given value
|
20
|
+
- Grid#locate_all(value) - Returns an array of coordinates for any location within the grid containing the given value
|
21
|
+
- Grid#each_cell - Iterates over each cell in the grid
|
22
|
+
|
23
|
+
### Changed
|
24
|
+
- Grid#cell now returns `nil` if the provided coordinates to not exist within the grid
|
25
|
+
- Grid#set_cell nwo returns `nil` if the provided coordinates to not exist within the grid
|
26
|
+
|
27
|
+
### Fixed
|
28
|
+
- Grid#dup previously returned a new `Grid` instance with the same instance of the `@grid` array within it. Now `@grid` is a unique copy.
|
29
|
+
|
10
30
|
## [0.0.4]
|
11
31
|
### Added
|
12
32
|
- Grid class for working with two-dimensional arrays of data
|
@@ -29,6 +49,10 @@ Initial release.
|
|
29
49
|
### Added
|
30
50
|
- Created `AocInput` class with initial helper methods
|
31
51
|
|
32
|
-
[Unreleased]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.
|
52
|
+
[Unreleased]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.6...HEAD
|
53
|
+
[0.0.6]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.5...v0.0.6
|
54
|
+
[0.0.5]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.4...v0.0.5
|
55
|
+
[0.0.4]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.3...v0.0.4
|
56
|
+
[0.0.3]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.2...v0.0.3
|
33
57
|
[0.0.2]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.1...v0.0.2
|
34
58
|
[0.0.1]: https://github.com/pacso/aoc_rb_helpers
|
@@ -22,6 +22,17 @@ class AocInput
|
|
22
22
|
@data ||= @raw_input
|
23
23
|
end
|
24
24
|
|
25
|
+
# Strips newline characters from the data, leaving a single line of input.
|
26
|
+
#
|
27
|
+
# @return [AocInput] self
|
28
|
+
def single_line
|
29
|
+
can_call?(:single_line)
|
30
|
+
@data = data.chomp('')
|
31
|
+
revoke(:multiple_lines)
|
32
|
+
revoke(:single_line)
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
25
36
|
# Splits the input string into an array of lines.
|
26
37
|
#
|
27
38
|
# This method processes +@data+ by splitting the input string into multiple lines,
|
@@ -30,9 +41,33 @@ class AocInput
|
|
30
41
|
#
|
31
42
|
# @return [AocInput] self
|
32
43
|
def multiple_lines
|
44
|
+
can_call?(:multiple_lines)
|
33
45
|
@data = data.lines(chomp: true)
|
34
46
|
allow(:columns_of_numbers)
|
47
|
+
allow(:process_each_line)
|
35
48
|
revoke(:multiple_lines)
|
49
|
+
revoke(:single_line)
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
# Processes each line of the data using the provided block.
|
54
|
+
#
|
55
|
+
# This method applies the given block to each line in the +@data+ array,
|
56
|
+
# replacing the original +@data+ with the results of the block. The method
|
57
|
+
# returns +self+ to allow method chaining.
|
58
|
+
#
|
59
|
+
# Returns an enumerator if no block is given.
|
60
|
+
#
|
61
|
+
# @yieldparam line [Object, Array<Object>] a single line of the data being processed
|
62
|
+
# @yieldreturn [Object, Array<Object>] the result of processing the line
|
63
|
+
# @return [self] the instance itself, for method chaining
|
64
|
+
# @return [Enumerator] if no block is given
|
65
|
+
def process_each_line
|
66
|
+
can_call?(:process_each_line, "call .multiple_lines first")
|
67
|
+
return to_enum(__callee__) unless block_given?
|
68
|
+
@data = @data.map do |line|
|
69
|
+
yield line
|
70
|
+
end
|
36
71
|
self
|
37
72
|
end
|
38
73
|
|
@@ -98,6 +133,8 @@ class AocInput
|
|
98
133
|
@can_call = {
|
99
134
|
columns_of_numbers: false,
|
100
135
|
multiple_lines: true,
|
136
|
+
process_each_line: false,
|
137
|
+
single_line: true,
|
101
138
|
sort_arrays: false,
|
102
139
|
transpose: false
|
103
140
|
}
|
data/lib/aoc_rb_helpers/grid.rb
CHANGED
@@ -16,23 +16,55 @@ class Grid
|
|
16
16
|
@grid = grid
|
17
17
|
end
|
18
18
|
|
19
|
+
# Returns +true+ if the provided coordinates exceed the bounds of the grid; +false+ otherwise.
|
20
|
+
#
|
21
|
+
# @param row [Integer] the row index to test
|
22
|
+
# @param column [Integer] the column index to test
|
23
|
+
# @return [Boolean]
|
24
|
+
# @see #includes_coords?
|
25
|
+
def beyond_grid?(row, column)
|
26
|
+
!includes_coords?(row, column)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns +true+ if the provided coordinates exist within the bounds of the grid; +false+ otherwise.
|
30
|
+
#
|
31
|
+
# @param row [Integer] the row index to test
|
32
|
+
# @param column [Integer] the column index to test
|
33
|
+
# @return [Boolean]
|
34
|
+
# @see #beyond_grid?
|
35
|
+
def includes_coords?(row, column)
|
36
|
+
row >= 0 && column >= 0 && row < @grid.length && column < @grid.first.length
|
37
|
+
end
|
38
|
+
alias_method(:within_grid?, :includes_coords?)
|
39
|
+
|
19
40
|
# Returns the value stored at coordinates +(row, column)+ within the grid.
|
20
41
|
#
|
42
|
+
# Returns +nil+ if the provided coordinates do not exist within the grid.
|
43
|
+
#
|
21
44
|
# Row and column numbers are zero-indexed.
|
22
45
|
#
|
23
46
|
# @param row [Integer] the row index of the desired cell
|
24
47
|
# @param column [Integer] the column index of the desired cell
|
48
|
+
# @return [Object] the value at the given coordinates within the grid
|
49
|
+
# @return [nil] if the given coordinates do not exist within the grid
|
50
|
+
# @see #set_cell
|
25
51
|
def cell(row, column)
|
52
|
+
return nil unless includes_coords?(row, column)
|
26
53
|
@grid[row][column]
|
27
54
|
end
|
28
55
|
|
29
56
|
# Updates the cell at coordinates +(row, column)+ with the object provided in +value+; returns the given object.
|
30
57
|
#
|
58
|
+
# Returns +nil+ if the provided coordinates do not exist within the grid.
|
59
|
+
#
|
31
60
|
# @param row [Integer] the row index of the cell you wish to update
|
32
61
|
# @param column [Integer] the column index of the cell you wish to update
|
33
62
|
# @param value [Object] the object to assign to the selected grid cell
|
34
63
|
# @return [Object] the given +value+
|
64
|
+
# @return [nil] if the provided coordinates do not exist within the grid
|
65
|
+
# @see #cell
|
35
66
|
def set_cell(row, column, value)
|
67
|
+
return nil unless includes_coords?(row, column)
|
36
68
|
@grid[row][column] = value
|
37
69
|
end
|
38
70
|
|
@@ -80,7 +112,7 @@ class Grid
|
|
80
112
|
# Returns a new {Grid} as a copy of self.
|
81
113
|
# @return [Grid] a copy of +self+
|
82
114
|
def dup
|
83
|
-
|
115
|
+
self.class.new(@grid.map { |row| row.map { |cell| cell } })
|
84
116
|
end
|
85
117
|
|
86
118
|
# Updates +self+ with a rotated grid and returns +self+.
|
@@ -126,4 +158,109 @@ class Grid
|
|
126
158
|
raise ArgumentError unless columns.is_a?(Integer) && columns > 0 && columns <= @grid.first.length
|
127
159
|
each_subgrid(rows, columns).to_a
|
128
160
|
end
|
161
|
+
|
162
|
+
# Returns the first coordinates within the grid containing the given value. Returns +nil+ if not found.
|
163
|
+
#
|
164
|
+
# If given an array of values, the first coordinate matching any of the given values will be returned.
|
165
|
+
#
|
166
|
+
# Searches the grid from top left (+[0, 0]+) to bottom right, by scanning each row.
|
167
|
+
#
|
168
|
+
# @param value [Object, Array<Object>] the value, or array of values, to search for.
|
169
|
+
# @return [Array<Integer>] if the value was located, its coordinates are returned in a 2-item array where:
|
170
|
+
# - The first item is the row index.
|
171
|
+
# - The second item is the column index.
|
172
|
+
# @return [nil] if the value was not located
|
173
|
+
def locate(value)
|
174
|
+
result = nil
|
175
|
+
if value.is_a? Array
|
176
|
+
value.each do |e|
|
177
|
+
result = locate(e)
|
178
|
+
break unless result.nil?
|
179
|
+
end
|
180
|
+
else
|
181
|
+
result = locate_value value
|
182
|
+
end
|
183
|
+
result
|
184
|
+
end
|
185
|
+
|
186
|
+
# Returns an array of coordinates for any location within the grid containing the given value.
|
187
|
+
#
|
188
|
+
# If given an array of values, the coordinates of any cell matching any of the given values will be returned.
|
189
|
+
#
|
190
|
+
# @param value [Object, Array<Object>] the value, or array of values, to search for.
|
191
|
+
# @return [Array<Array<Integer>>] an array of coordinates. Each coordinate is a 2-item array where:
|
192
|
+
# - The first item is the row index.
|
193
|
+
# - The second item is the column index.
|
194
|
+
def locate_all(value)
|
195
|
+
locations = []
|
196
|
+
|
197
|
+
if value.is_a? Array
|
198
|
+
@grid.each_with_index.select { |row, _r_index| value.any? { |el| row.include?(el) } }.each do |row, r_index|
|
199
|
+
row.each_with_index do |cell, c_index|
|
200
|
+
locations << [r_index, c_index] if value.include?(cell)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
else
|
204
|
+
@grid.each_with_index.select { |row, _r_index| row.include?(value) }.each do |row, r_index|
|
205
|
+
row.each_with_index do |cell, c_index|
|
206
|
+
locations << [r_index, c_index] if cell == value
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
locations
|
212
|
+
end
|
213
|
+
|
214
|
+
# Iterates over each cell in the grid.
|
215
|
+
#
|
216
|
+
# When a block is given, passes the coordinates and value of each cell to the block; returns +self+:
|
217
|
+
# g = Grid.new([
|
218
|
+
# ["a", "b"],
|
219
|
+
# ["c", "d"]
|
220
|
+
# ])
|
221
|
+
# g.each_cell { |coords, value| puts "#{coords.inspect} => #{value}" }
|
222
|
+
#
|
223
|
+
# Output:
|
224
|
+
# [0, 0] => a
|
225
|
+
# [0, 1] => b
|
226
|
+
# [1, 0] => c
|
227
|
+
# [1, 1] => d
|
228
|
+
#
|
229
|
+
# When no block is given, returns a new Enumerator:
|
230
|
+
# g = Grid.new([
|
231
|
+
# [:a, "b"],
|
232
|
+
# [3, true]
|
233
|
+
# ])
|
234
|
+
# e = g.each_cell
|
235
|
+
# e # => #<Enumerator: #<Grid: @grid=[[\"a\", \"b\"], [\"c\", \"d\"]]>:each_cell>
|
236
|
+
# g1 = e.each { |coords, value| puts "#{coords.inspect} => #{value.class}: #{value}" }
|
237
|
+
#
|
238
|
+
# Output:
|
239
|
+
# [0, 0] => Symbol: a
|
240
|
+
# [0, 1] => String: b
|
241
|
+
# [1, 0] => Integer: 3
|
242
|
+
# [1, 1] => TrueClass: true
|
243
|
+
# @yieldparam coords [Array<Integer>] the coordinates of the cell in a 2-item array where:
|
244
|
+
# # - The first item is the row index.
|
245
|
+
# # - The second item is the column index.
|
246
|
+
# @yieldparam value [Object] the value stored within the cell
|
247
|
+
# @return [self]
|
248
|
+
def each_cell
|
249
|
+
return to_enum(__callee__) unless block_given?
|
250
|
+
@grid.each_with_index do |row, r_index|
|
251
|
+
row.each_with_index do |cell, c_index|
|
252
|
+
yield [[r_index, c_index], cell]
|
253
|
+
end
|
254
|
+
end
|
255
|
+
self
|
256
|
+
end
|
257
|
+
|
258
|
+
private
|
259
|
+
|
260
|
+
def locate_value(element)
|
261
|
+
row = @grid.index { |row| row.include?(element) }
|
262
|
+
return nil if row.nil?
|
263
|
+
column = @grid[row].index(element)
|
264
|
+
[row, column]
|
265
|
+
end
|
129
266
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aoc_rb_helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Pascoe
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aoc_rb
|