aoc_rb_helpers 0.0.5 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1990cde2622df33946ce6131918c215ac548d3b013ed36b57fd980fd0ba7c0ab
4
- data.tar.gz: 7070a8add7b5f3bf0b4fa033959ce30624edeac87329a95964e2bade9dbb5741
3
+ metadata.gz: 11c49beae72029532e7eff52f8b47b7a6d0c1f795b7d265403302d42345dedd2
4
+ data.tar.gz: 8fd94aa2f8998aa9a56523da3296feba48ce667ea44d71758e3c5b7176c68107
5
5
  SHA512:
6
- metadata.gz: 402844433642a9dcfd4bcded006ec9eca2d3cc8b18a0016b7d3cc45631b24e54e37315af3cff1d895c511233a167b9cc82ed21f7f942f721cafe016f8ea552d6
7
- data.tar.gz: 34f664b1de9a6fd751241afc34445c46cc16ab6cce24f246476799d7915ce4f519f4ac67d22a42b72780c673d5c21fe693c19c42786a23f6b529c19beffa53f8
6
+ metadata.gz: c9d8349d2f94ac316262f630ce90629a34cb6e0ca59b44382bd1b8b065dea5132ef7edb7ebca44d8e4e39d3653e5b9382952fcb5927b3e20c8f0beeee212b369
7
+ data.tar.gz: 98f8005d31c022ecd2064b976a39bfd601ae40a566b77f449f3e4e6654ea362deb67eeb07d196c0a58839645805d593cdf6d4ef6bf49b20bf4a4ad69e2c57ae4
data/CHANGELOG.md CHANGED
@@ -7,6 +7,15 @@ 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.7]
11
+ ### Added
12
+ - Grid#each_cell! - Iterates over each cell in the grid, calling the provided block with each cell and updating the cell with the returned value
13
+ - Grid#neighbours - Accessor method to easily fetch the coordinates of cardinal and/or ordinal locations from the given coordinates
14
+
15
+ ## [0.0.6]
16
+ ### Added
17
+ - AocInput#single_line - Strips newline characters from single line puzzle inputs
18
+
10
19
  ## [0.0.5]
11
20
  ### Added
12
21
  - AocInput#process_each_line - Processes each line of the input data using the provided block
@@ -45,7 +54,9 @@ Initial release.
45
54
  ### Added
46
55
  - Created `AocInput` class with initial helper methods
47
56
 
48
- [Unreleased]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.5...HEAD
57
+ [Unreleased]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.7...HEAD
58
+ [0.0.7]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.6...v0.0.7
59
+ [0.0.6]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.5...v0.0.6
49
60
  [0.0.5]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.4...v0.0.5
50
61
  [0.0.4]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.3...v0.0.4
51
62
  [0.0.3]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.2...v0.0.3
@@ -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,12 @@ 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)
36
50
  self
37
51
  end
38
52
 
@@ -49,6 +63,7 @@ class AocInput
49
63
  # @return [self] the instance itself, for method chaining
50
64
  # @return [Enumerator] if no block is given
51
65
  def process_each_line
66
+ can_call?(:process_each_line, "call .multiple_lines first")
52
67
  return to_enum(__callee__) unless block_given?
53
68
  @data = @data.map do |line|
54
69
  yield line
@@ -118,6 +133,8 @@ class AocInput
118
133
  @can_call = {
119
134
  columns_of_numbers: false,
120
135
  multiple_lines: true,
136
+ process_each_line: false,
137
+ single_line: true,
121
138
  sort_arrays: false,
122
139
  transpose: false
123
140
  }
@@ -35,6 +35,7 @@ class Grid
35
35
  def includes_coords?(row, column)
36
36
  row >= 0 && column >= 0 && row < @grid.length && column < @grid.first.length
37
37
  end
38
+
38
39
  alias_method(:within_grid?, :includes_coords?)
39
40
 
40
41
  # Returns the value stored at coordinates +(row, column)+ within the grid.
@@ -99,11 +100,11 @@ class Grid
99
100
  # @return [Array<Grid>] an array containing four {Grid} objects, one in each possible rotation
100
101
  def all_rotations
101
102
  rotations = []
102
- current_grid = self.dup
103
+ grid = self.dup
103
104
 
104
105
  4.times do
105
- rotations << current_grid.dup
106
- current_grid.rotate!
106
+ rotations << grid.dup
107
+ grid.rotate!
107
108
  end
108
109
 
109
110
  rotations
@@ -112,7 +113,7 @@ class Grid
112
113
  # Returns a new {Grid} as a copy of self.
113
114
  # @return [Grid] a copy of +self+
114
115
  def dup
115
- self.class.new(@grid.map { |row| row.map { |cell| cell } })
116
+ self.class.new Marshal.load(Marshal.dump(@grid))
116
117
  end
117
118
 
118
119
  # Updates +self+ with a rotated grid and returns +self+.
@@ -131,8 +132,8 @@ class Grid
131
132
  #
132
133
  # Returns an enumerator if no block is given
133
134
  #
135
+ # @return [Grid] if given a block, returns +self+ after calling block for each subgrid
134
136
  # @return [Enumerator] if no block is given.
135
- # @return [self] after processing the provided block
136
137
  # @yield [subgrid] calls the provided block with each subgrid as a new {Grid} object
137
138
  # @yieldparam subgrid [Grid] a new {Grid} object containing a subgrid from the main grid
138
139
  def each_subgrid(rows, columns)
@@ -244,7 +245,8 @@ class Grid
244
245
  # # - The first item is the row index.
245
246
  # # - The second item is the column index.
246
247
  # @yieldparam value [Object] the value stored within the cell
247
- # @return [self]
248
+ # @return [Grid] if given a block, returns +self+ after calling block for each cell
249
+ # @return [Enumerator] if no block is given
248
250
  def each_cell
249
251
  return to_enum(__callee__) unless block_given?
250
252
  @grid.each_with_index do |row, r_index|
@@ -255,6 +257,79 @@ class Grid
255
257
  self
256
258
  end
257
259
 
260
+ # Calls the block, if given, with each cell value; replaces the cell in the grid with the block's return value:
261
+ #
262
+ # Returns a new Enumerator if no block given
263
+ # @yieldparam value [Object] the value stored within the cell
264
+ # @yieldreturn new_value [Object] the updated value to replace cell with
265
+ # @return [Grid] if given a block, returns +self+ after calling block for each cell
266
+ # @return [Enumerator] if no block is given
267
+ def each_cell!
268
+ return to_enum(__callee__) unless block_given?
269
+ @grid.each_with_index do |row, r_index|
270
+ row.each_with_index do |cell, c_index|
271
+ @grid[r_index][c_index] = yield cell
272
+ end
273
+ end
274
+ self
275
+ end
276
+ alias_method :format_cells, :each_cell!
277
+
278
+ # For the given position indicated by the +row+ and +column+ provided, returns
279
+ # an array of coordinates which are direct neighbours. The returned coordinates are in
280
+ # clockwise order starting directly above the given cell:
281
+ # g = Grid.new([
282
+ # [0, 1, 2, 3],
283
+ # [4, 5, 6, 7],
284
+ # [8, 9, 10, 11]
285
+ # ])
286
+ # g.neighbours(1, 1) # => [[0, 1], [1, 2], [2, 1], [1, 0]]
287
+ #
288
+ # If the keyword argument +allow_diagonal: true+ is provided, diagonally accessible neighbours will also be included:
289
+ # g = Grid.new([
290
+ # [0, 1, 2, 3],
291
+ # [4, 5, 6, 7],
292
+ # [8, 9, 10, 11]
293
+ # ])
294
+ # g.neighbours(1, 1) # => [[0, 1], [0, 2], [1, 2], [2, 2], [2, 1], [2, 0], [1, 0], [0, 0]]
295
+ #
296
+ # If provided a block, each neighbour's cell value is yielded to the block, and only those neighbours for which the block
297
+ # returns a truthy value will be returned in the results:
298
+ # g = Grid.new([
299
+ # [0, 1, 2, 3],
300
+ # [4, 5, 6, 7],
301
+ # [8, 9, 10, 11]
302
+ # ])
303
+ # g.neighbours(1, 2) { |cell| cell.even? } # => [[0, 2], [2, 2]]
304
+ # g.neighbours(1, 2, allow_diagonal: true) { |cell| cell <= 5 } # => [[0, 2], [0, 3], [1, 1], [0, 1]]
305
+ #
306
+ # @param row [Integer] the row index of the starting cell
307
+ # @param column [Integer] the column index of the starting cell
308
+ # @param cardinal [Boolean] permits the direct north/east/south/west directions
309
+ # @param ordinal [Boolean] permits diagonal north-east/south-east/south-west/north-west directions
310
+ # @return [Array<Array<Integer>>] an array of coordinates. Each coordinate is a 2-item array where:
311
+ # - The first item is the row index.
312
+ # - The second item is the column index.
313
+ def neighbours(row, column, cardinal: true, ordinal: false)
314
+ possible_neighbours = []
315
+ possible_neighbours << [row - 1, column] if cardinal
316
+ possible_neighbours << [row - 1, column + 1] if ordinal
317
+ possible_neighbours << [row, column + 1] if cardinal
318
+ possible_neighbours << [row + 1, column + 1] if ordinal
319
+ possible_neighbours << [row + 1, column] if cardinal
320
+ possible_neighbours << [row + 1, column - 1] if ordinal
321
+ possible_neighbours << [row, column - 1] if cardinal
322
+ possible_neighbours << [row - 1, column - 1] if ordinal
323
+
324
+ valid_neighbours = possible_neighbours.select { |r, c| includes_coords?(r, c) }
325
+
326
+ if block_given?
327
+ valid_neighbours.select { |r, c| yield cell(r, c) }
328
+ else
329
+ valid_neighbours
330
+ end
331
+ end
332
+
258
333
  private
259
334
 
260
335
  def locate_value(element)
@@ -1,3 +1,3 @@
1
1
  module AocRbHelpers
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.7"
3
3
  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.5
4
+ version: 0.0.7
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-08 00:00:00.000000000 Z
11
+ date: 2024-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aoc_rb