aoc_rb_helpers 0.0.1 → 0.0.2
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 +6 -1
- data/Gemfile +2 -0
- data/aoc_rb_helpers.gemspec +1 -2
- data/lib/aoc_rb_helpers/aoc_input.rb +53 -4
- data/lib/aoc_rb_helpers/dot_matrix.rb +234 -0
- data/lib/aoc_rb_helpers/version.rb +1 -1
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15a53c3fd46773e8f18a1e5d0e9d76ba14a42f908c244b5628fd9c913f199739
|
4
|
+
data.tar.gz: c500c60c483e56f472b5b254428c805d44aec5d253f03377c7e65e2592e38d07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 117da557cc26d663671fa7ff39b4557e730da2d57484c573631750ad5d7d8733c96d8c3a6841d6aa48db3eecbdcaa1800d1244bd3b3587175a08745bc93ad912
|
7
|
+
data.tar.gz: a6bdd6ae05609d22bb1d486ea73aa5b62ffa246a6677e76573e4b1957cf5df2f9db896a4b3ab7ec31116aa0e696b6065fbc399816c5b213d9d9d06ebdebdbbf9
|
data/CHANGELOG.md
CHANGED
@@ -7,11 +7,16 @@ 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.2]
|
11
|
+
### Added
|
12
|
+
- DotMatrix class for decoding printed puzzle output
|
13
|
+
|
10
14
|
## [0.0.1]
|
11
15
|
Initial release.
|
12
16
|
|
13
17
|
### Added
|
14
18
|
- Created `AocInput` class with initial helper methods
|
15
19
|
|
16
|
-
[Unreleased]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.
|
20
|
+
[Unreleased]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.2...HEAD
|
21
|
+
[0.0.2]: https://github.com/pacso/aoc_rb_helpers/compare/v0.0.1...v0.0.2
|
17
22
|
[0.0.1]: https://github.com/pacso/aoc_rb_helpers
|
data/Gemfile
CHANGED
data/aoc_rb_helpers.gemspec
CHANGED
@@ -13,7 +13,6 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.required_ruby_version = Gem::Requirement.new("~> 3.1", ">= 3.1.0")
|
14
14
|
|
15
15
|
spec.metadata["homepage_uri"] = spec.homepage
|
16
|
-
spec.metadata["source_code_uri"] = "https://github.com/pacso/aoc_rb_helpers"
|
17
16
|
spec.metadata["changelog_uri"] = "https://github.com/pacso/aoc_rb_helpers/blob/main/CHANGELOG"
|
18
17
|
|
19
18
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
@@ -24,5 +23,5 @@ Gem::Specification.new do |spec|
|
|
24
23
|
spec.require_paths = ["lib"]
|
25
24
|
|
26
25
|
spec.add_dependency "aoc_rb", "~> 0.2", ">= 0.2.6"
|
27
|
-
spec.add_dependency "puts_debuggerer"
|
26
|
+
spec.add_dependency "puts_debuggerer", '~> 1.0', '>= 1.0.1'
|
28
27
|
end
|
@@ -1,35 +1,79 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Provides input manipulation helper methods.
|
4
|
+
# Methods are chainable, and directly modify the parsed view of the input data within the @data instance variable.
|
5
|
+
#
|
6
|
+
# Once manipulated as required, the input is accessable from #data
|
3
7
|
class AocInput
|
4
|
-
|
5
|
-
|
8
|
+
# Returns a new AocInput initialized with the given puzzle input.
|
9
|
+
#
|
10
|
+
# @param puzzle_input [String] the puzzle input as a single string with embedded newline characters
|
11
|
+
def initialize(puzzle_input)
|
12
|
+
@raw_input = puzzle_input
|
6
13
|
configure_method_access
|
7
14
|
end
|
8
15
|
|
16
|
+
# Returns the parsed puzzle input.
|
17
|
+
#
|
18
|
+
# If the data has not been parsed yet, it defaults to the raw input provided in {initialize}.
|
19
|
+
#
|
20
|
+
# @return [Object] the parsed puzzle input
|
9
21
|
def data
|
10
22
|
@data ||= @raw_input
|
11
23
|
end
|
12
24
|
|
25
|
+
# Splits the input string into an array of lines.
|
26
|
+
#
|
27
|
+
# This method processes `@data` by splitting the input string into multiple lines,
|
28
|
+
# removing trailing newline characters. It modifies `@data` directly and returns `self`
|
29
|
+
# to enable method chaining.
|
30
|
+
#
|
31
|
+
# @return [AocInput] self
|
13
32
|
def multiple_lines
|
14
33
|
@data = data.lines(chomp: true)
|
15
34
|
allow(:columns_of_numbers)
|
35
|
+
revoke(:multiple_lines)
|
16
36
|
self
|
17
37
|
end
|
18
38
|
|
19
|
-
|
39
|
+
# Splits each string in the data array into an array of numbers.
|
40
|
+
#
|
41
|
+
# This method processes `@data` by splitting each string in the array using the specified delimiter,
|
42
|
+
# then converting each resulting element to an integer. It modifies `@data` directly and enables
|
43
|
+
# chaining by returning `self`.
|
44
|
+
#
|
45
|
+
# @param delimiter [String, nil] the delimiter to be passed to `String#split`
|
46
|
+
# @raise [RuntimeError] if {#multiple_lines} has not been called
|
47
|
+
# @return [AocInput] self
|
48
|
+
def columns_of_numbers(delimiter = nil)
|
20
49
|
can_call?(:columns_of_numbers, "call .multiple_lines first")
|
21
|
-
@data = data.map { |line| line.split(
|
50
|
+
@data = data.map { |line| line.split(delimiter).map(&:to_i) }
|
22
51
|
allow(:sort_arrays)
|
23
52
|
allow(:transpose)
|
53
|
+
revoke(:columns_of_numbers)
|
24
54
|
self
|
25
55
|
end
|
26
56
|
|
57
|
+
# Transposes the data array.
|
58
|
+
#
|
59
|
+
# This method can only be called after {columns_of_numbers}.
|
60
|
+
# It directly modifies `@data` by transposing it and returns `self` to allow method chaining.
|
61
|
+
#
|
62
|
+
# @raise [RuntimeError] if {columns_of_numbers} has not been called.
|
63
|
+
# @return [AocInput] self
|
27
64
|
def transpose
|
28
65
|
can_call?(:transpose, "call .columns_of_numbers first")
|
29
66
|
@data = data.transpose
|
30
67
|
self
|
31
68
|
end
|
32
69
|
|
70
|
+
# Sorts each array within the `@data` array.
|
71
|
+
#
|
72
|
+
# This method processes `@data` by sorting each nested array in ascending order.
|
73
|
+
# It directly modifies `@data` and returns `self` to enable method chaining.
|
74
|
+
#
|
75
|
+
# @raise [RuntimeError] if {#columns_of_numbers} has not been called
|
76
|
+
# @return [AocInput] self
|
33
77
|
def sort_arrays
|
34
78
|
can_call?(:sort_arrays, "call .columns_of_numbers first")
|
35
79
|
@data = data.map { |ary| ary.sort }
|
@@ -40,6 +84,7 @@ class AocInput
|
|
40
84
|
def configure_method_access
|
41
85
|
@can_call = {
|
42
86
|
columns_of_numbers: false,
|
87
|
+
multiple_lines: true,
|
43
88
|
sort_arrays: false,
|
44
89
|
transpose: false
|
45
90
|
}
|
@@ -49,6 +94,10 @@ class AocInput
|
|
49
94
|
@can_call[method_name.to_sym] = true
|
50
95
|
end
|
51
96
|
|
97
|
+
def revoke(method_name)
|
98
|
+
@can_call[method_name.to_sym] = false
|
99
|
+
end
|
100
|
+
|
52
101
|
def can_call?(method_name, msg = "operation not permitted")
|
53
102
|
raise RuntimeError, msg unless @can_call[method_name.to_sym]
|
54
103
|
end
|
@@ -0,0 +1,234 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class DotMatrix
|
4
|
+
CHAR_WIDTH = 5
|
5
|
+
DICTIONARY = {
|
6
|
+
a: [
|
7
|
+
" XX ",
|
8
|
+
"X X ",
|
9
|
+
"X X ",
|
10
|
+
"XXXX ",
|
11
|
+
"X X ",
|
12
|
+
"X X "
|
13
|
+
],
|
14
|
+
b: [
|
15
|
+
"XXX ",
|
16
|
+
"X X ",
|
17
|
+
"XXX ",
|
18
|
+
"X X ",
|
19
|
+
"X X ",
|
20
|
+
"XXX "
|
21
|
+
],
|
22
|
+
c: [
|
23
|
+
" XX ",
|
24
|
+
"X X ",
|
25
|
+
"X ",
|
26
|
+
"X ",
|
27
|
+
"X X ",
|
28
|
+
" XX "
|
29
|
+
],
|
30
|
+
e: [
|
31
|
+
"XXXX ",
|
32
|
+
"X ",
|
33
|
+
"XXX ",
|
34
|
+
"X ",
|
35
|
+
"X ",
|
36
|
+
"XXXX "
|
37
|
+
],
|
38
|
+
f: [
|
39
|
+
"XXXX ",
|
40
|
+
"X ",
|
41
|
+
"XXX ",
|
42
|
+
"X ",
|
43
|
+
"X ",
|
44
|
+
"X "
|
45
|
+
],
|
46
|
+
g: [
|
47
|
+
" XX ",
|
48
|
+
"X X ",
|
49
|
+
"X ",
|
50
|
+
"X XX ",
|
51
|
+
"X X ",
|
52
|
+
" XXX "
|
53
|
+
],
|
54
|
+
h: [
|
55
|
+
"X X ",
|
56
|
+
"X X ",
|
57
|
+
"XXXX ",
|
58
|
+
"X X ",
|
59
|
+
"X X ",
|
60
|
+
"X X ",
|
61
|
+
],
|
62
|
+
j: [
|
63
|
+
" XX ",
|
64
|
+
" X ",
|
65
|
+
" X ",
|
66
|
+
" X ",
|
67
|
+
"X X ",
|
68
|
+
" XX ",
|
69
|
+
],
|
70
|
+
k: [
|
71
|
+
"X X ",
|
72
|
+
"X X ",
|
73
|
+
"XX ",
|
74
|
+
"X X ",
|
75
|
+
"X X ",
|
76
|
+
"X X ",
|
77
|
+
],
|
78
|
+
l: [
|
79
|
+
"X ",
|
80
|
+
"X ",
|
81
|
+
"X ",
|
82
|
+
"X ",
|
83
|
+
"X ",
|
84
|
+
"XXXX ",
|
85
|
+
],
|
86
|
+
o: [
|
87
|
+
" XX ",
|
88
|
+
"X X ",
|
89
|
+
"X X ",
|
90
|
+
"X X ",
|
91
|
+
"X X ",
|
92
|
+
" XX "
|
93
|
+
],
|
94
|
+
p: [
|
95
|
+
"XXX ",
|
96
|
+
"X X ",
|
97
|
+
"X X ",
|
98
|
+
"XXX ",
|
99
|
+
"X ",
|
100
|
+
"X ",
|
101
|
+
],
|
102
|
+
r: [
|
103
|
+
"XXX ",
|
104
|
+
"X X ",
|
105
|
+
"X X ",
|
106
|
+
"XXX ",
|
107
|
+
"X X ",
|
108
|
+
"X X ",
|
109
|
+
],
|
110
|
+
s: [
|
111
|
+
" XXX ",
|
112
|
+
"X ",
|
113
|
+
"X ",
|
114
|
+
" XX ",
|
115
|
+
" X ",
|
116
|
+
"XXX ",
|
117
|
+
],
|
118
|
+
u: [
|
119
|
+
"X X ",
|
120
|
+
"X X ",
|
121
|
+
"X X ",
|
122
|
+
"X X ",
|
123
|
+
"X X ",
|
124
|
+
" XX ",
|
125
|
+
],
|
126
|
+
y: [
|
127
|
+
"X X",
|
128
|
+
"X X",
|
129
|
+
" X X ",
|
130
|
+
" X ",
|
131
|
+
" X ",
|
132
|
+
" X "
|
133
|
+
],
|
134
|
+
z: [
|
135
|
+
"XXXX ",
|
136
|
+
" X ",
|
137
|
+
" X ",
|
138
|
+
" X ",
|
139
|
+
"X ",
|
140
|
+
"XXXX ",
|
141
|
+
]
|
142
|
+
}
|
143
|
+
|
144
|
+
# Returns the decoded input using the specified characters for printed text (on) and whitespace (off).
|
145
|
+
# @param [Array<Array<String>>] input a two-dimensional array of characters
|
146
|
+
# @param on [String] specifies the character representing the "on" state, or printed text
|
147
|
+
# @param off [String] specifies the character representing the "off" state, or whitespace
|
148
|
+
# @return [String] the decoded string
|
149
|
+
def self.decode(input, on: "X", off: " ")
|
150
|
+
new(input, on, off).to_s
|
151
|
+
end
|
152
|
+
|
153
|
+
# @param [Array<Array<String>>] input a two-dimensional array of characters
|
154
|
+
# @param on [String] specifies the character representing the "on" state, or printed text
|
155
|
+
# @param off [String] specifies the character representing the "off" state, or whitespace
|
156
|
+
def initialize(input, on = "X", off = " ")
|
157
|
+
@input = input
|
158
|
+
@on = on
|
159
|
+
@off = off
|
160
|
+
end
|
161
|
+
|
162
|
+
# Prints the input array to STDOUT and returns self.
|
163
|
+
# @return [DotMatrix] self
|
164
|
+
def print(input = @input)
|
165
|
+
input.each do |row|
|
166
|
+
puts row.is_a?(String) ? row : row.join
|
167
|
+
end
|
168
|
+
self
|
169
|
+
end
|
170
|
+
|
171
|
+
# Prints the decoded input to STDOUT and returns self.
|
172
|
+
# @return [DotMatrix] self
|
173
|
+
def print_decoded
|
174
|
+
puts to_s
|
175
|
+
self
|
176
|
+
end
|
177
|
+
|
178
|
+
# Returns the decoded input.
|
179
|
+
# @return [String] the decoded input
|
180
|
+
def to_s
|
181
|
+
(0...max_chars).map do |char_index|
|
182
|
+
begin
|
183
|
+
char_map = printable_content.map do |row|
|
184
|
+
row[char_offset(char_index)...char_offset(char_index + 1)].join
|
185
|
+
end
|
186
|
+
|
187
|
+
unless @on == "X" && @off == " "
|
188
|
+
new_map = []
|
189
|
+
char_map.each do |row|
|
190
|
+
row_chars = []
|
191
|
+
row.chars.each do |cell|
|
192
|
+
row_chars.push(cell == @on ? "X" : " ")
|
193
|
+
end
|
194
|
+
new_map.push(row_chars.join)
|
195
|
+
end
|
196
|
+
char_map = new_map
|
197
|
+
end
|
198
|
+
|
199
|
+
DICTIONARY.find { |_, map| map == char_map }[0].to_s.upcase
|
200
|
+
rescue NoMethodError
|
201
|
+
puts "ERROR: Missing character in dictionary:\n\n"
|
202
|
+
print(char_map)
|
203
|
+
puts "\nReverting to ASCII:\n\n"
|
204
|
+
print
|
205
|
+
break
|
206
|
+
end
|
207
|
+
end.join
|
208
|
+
end
|
209
|
+
|
210
|
+
private
|
211
|
+
def char_offset(index)
|
212
|
+
index * CHAR_WIDTH
|
213
|
+
end
|
214
|
+
|
215
|
+
def printable_range(row)
|
216
|
+
row[first_position..last_position]
|
217
|
+
end
|
218
|
+
|
219
|
+
def printable_content
|
220
|
+
@input.map { |row| printable_range(row) }
|
221
|
+
end
|
222
|
+
|
223
|
+
def first_position
|
224
|
+
@input.map { |row| row.index { |dot| dot != ' ' } }.min
|
225
|
+
end
|
226
|
+
|
227
|
+
def last_position
|
228
|
+
@input.map { |row| row.rindex { |dot| dot != ' ' } }.max + 1
|
229
|
+
end
|
230
|
+
|
231
|
+
def max_chars
|
232
|
+
printable_content.first.length / CHAR_WIDTH
|
233
|
+
end
|
234
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Pascoe
|
@@ -34,16 +34,22 @@ dependencies:
|
|
34
34
|
name: puts_debuggerer
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.0'
|
37
40
|
- - ">="
|
38
41
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
42
|
+
version: 1.0.1
|
40
43
|
type: :runtime
|
41
44
|
prerelease: false
|
42
45
|
version_requirements: !ruby/object:Gem::Requirement
|
43
46
|
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.0'
|
44
50
|
- - ">="
|
45
51
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
52
|
+
version: 1.0.1
|
47
53
|
description: Enhances the aoc_rb gem with tools for parsing puzzle input, and handling
|
48
54
|
various data manipulations within Advent of Code puzzle solutions.
|
49
55
|
email:
|
@@ -63,6 +69,7 @@ files:
|
|
63
69
|
- aoc_rb_helpers.gemspec
|
64
70
|
- lib/aoc_rb_helpers.rb
|
65
71
|
- lib/aoc_rb_helpers/aoc_input.rb
|
72
|
+
- lib/aoc_rb_helpers/dot_matrix.rb
|
66
73
|
- lib/aoc_rb_helpers/solution/input_handling.rb
|
67
74
|
- lib/aoc_rb_helpers/version.rb
|
68
75
|
homepage: https://github.com/pacso/aoc_rb_helpers
|
@@ -70,7 +77,6 @@ licenses:
|
|
70
77
|
- MIT
|
71
78
|
metadata:
|
72
79
|
homepage_uri: https://github.com/pacso/aoc_rb_helpers
|
73
|
-
source_code_uri: https://github.com/pacso/aoc_rb_helpers
|
74
80
|
changelog_uri: https://github.com/pacso/aoc_rb_helpers/blob/main/CHANGELOG
|
75
81
|
post_install_message:
|
76
82
|
rdoc_options: []
|