cem 0.1.4 → 0.1.5

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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/examples/aoc2018/.gitignore +2 -0
  3. data/examples/aoc2018/day10.rb +61 -0
  4. data/examples/aoc2018/day11.rb +66 -0
  5. data/examples/aoc2018/day12.rb +61 -0
  6. data/examples/aoc2018/day13.rb +167 -0
  7. data/examples/aoc2018/day14.rb +31 -0
  8. data/examples/aoc2018/day14_2.rb +71 -0
  9. data/examples/aoc2018/day15.rb +271 -0
  10. data/examples/aoc2018/day16.rb +158 -0
  11. data/examples/aoc2018/day17.rb +203 -0
  12. data/examples/aoc2018/day18.rb +113 -0
  13. data/examples/aoc2018/day18_rspec.rb +131 -0
  14. data/examples/aoc2018/day19.rb +145 -0
  15. data/examples/aoc2018/day20.rb +103 -0
  16. data/examples/aoc2018/day21.rb +158 -0
  17. data/examples/aoc2018/day21_v2.rb +137 -0
  18. data/examples/aoc2018/day21_v3.rb +157 -0
  19. data/examples/aoc2018/day21_v4.rb +141 -0
  20. data/examples/aoc2018/day22.rb +212 -0
  21. data/examples/aoc2018/day23.rb +148 -0
  22. data/examples/aoc2018/day24.rb +156 -0
  23. data/examples/aoc2018/day25.rb +52 -0
  24. data/examples/aoc2018/day9.rb +51 -0
  25. data/examples/aoc2018/day9_circular.rb +125 -0
  26. data/examples/aoc2018/inputs/day10_input.txt +395 -0
  27. data/examples/aoc2018/inputs/day11_input.txt +1 -0
  28. data/examples/aoc2018/inputs/day12_input.txt +34 -0
  29. data/examples/aoc2018/inputs/day12_input2.txt +16 -0
  30. data/examples/aoc2018/inputs/day13_input.txt +150 -0
  31. data/examples/aoc2018/inputs/day13_test.txt +6 -0
  32. data/examples/aoc2018/inputs/day14_input.txt +1 -0
  33. data/examples/aoc2018/inputs/day15_input.txt +32 -0
  34. data/examples/aoc2018/inputs/day15_input10.txt +32 -0
  35. data/examples/aoc2018/inputs/day15_input11.txt +32 -0
  36. data/examples/aoc2018/inputs/day15_input12.txt +32 -0
  37. data/examples/aoc2018/inputs/day15_input13.txt +32 -0
  38. data/examples/aoc2018/inputs/day15_input14.txt +32 -0
  39. data/examples/aoc2018/inputs/day15_input2.txt +7 -0
  40. data/examples/aoc2018/inputs/day15_input3.txt +9 -0
  41. data/examples/aoc2018/inputs/day15_input4.txt +7 -0
  42. data/examples/aoc2018/inputs/day15_input5.txt +7 -0
  43. data/examples/aoc2018/inputs/day15_input6.txt +7 -0
  44. data/examples/aoc2018/inputs/day15_input7.txt +7 -0
  45. data/examples/aoc2018/inputs/day15_input8.txt +5 -0
  46. data/examples/aoc2018/inputs/day15_input9.txt +7 -0
  47. data/examples/aoc2018/inputs/day15_test.txt +9 -0
  48. data/examples/aoc2018/inputs/day16_input.txt +3865 -0
  49. data/examples/aoc2018/inputs/day17_input.txt +2229 -0
  50. data/examples/aoc2018/inputs/day17_input_test.txt +8 -0
  51. data/examples/aoc2018/inputs/day18_input.txt +50 -0
  52. data/examples/aoc2018/inputs/day18_test.txt +10 -0
  53. data/examples/aoc2018/inputs/day19_input.txt +48 -0
  54. data/examples/aoc2018/inputs/day20_input.txt +1 -0
  55. data/examples/aoc2018/inputs/day21_input.txt +32 -0
  56. data/examples/aoc2018/inputs/day22_input.txt +2 -0
  57. data/examples/aoc2018/inputs/day23_input.txt +1000 -0
  58. data/examples/aoc2018/inputs/day23_input2.txt +9 -0
  59. data/examples/aoc2018/inputs/day24_input.txt +24 -0
  60. data/examples/aoc2018/inputs/day25_input.txt +1483 -0
  61. data/examples/aoc2018/inputs/day9_input.txt +1 -0
  62. data/lib/cem.rb +0 -6
  63. data/lib/cem/ccommon.rb +45 -0
  64. data/lib/cem/cruzzles.rb +93 -38
  65. data/lib/cem/version.rb +1 -1
  66. metadata +62 -2
@@ -0,0 +1 @@
1
+ 428 players; last marble is worth 70825 points
data/lib/cem.rb CHANGED
@@ -1,10 +1,4 @@
1
1
 
2
2
  require "cem/version"
3
3
  require "cem/ccommon"
4
- require "cem/cflame"
5
4
  require "cem/cruzzles"
6
-
7
- module Cem
8
- class Error < StandardError; end
9
- # Your code goes here...
10
- end
@@ -11,6 +11,28 @@ rescue LoadError
11
11
  require requireName
12
12
  end
13
13
 
14
+ #
15
+ # Puts+eql? == peql
16
+ # Performs a equal comparison and outputs the result to console in the form
17
+ #
18
+ # "#{msg}: Expected #{expected}, but got #{actual}"
19
+ #
20
+ # expected may be kept empty, in which case the msg is adjusted
21
+ #
22
+ def peql(actual, expected=:unknown_peql_token, msg=nil)
23
+
24
+ if expected == :unknown_peql_token
25
+ puts "#{msg}: Didn't know what to expect and got '#{actual}'"
26
+ else
27
+ if actual == expected
28
+ puts "#{msg}: Expected '#{expected}' and got it!"
29
+ else
30
+ puts "#{msg}: Expected '#{expected}', but got '#{actual}!"
31
+ end
32
+ end
33
+
34
+ end
35
+
14
36
  class File
15
37
 
16
38
  # Returns the first match of the given files
@@ -24,6 +46,29 @@ class File
24
46
  end
25
47
  end
26
48
 
49
+ class Module
50
+
51
+ # Append only the given methods from the given mod(ule)
52
+ # Adapted from: https://www.ruby-forum.com/t/partial-append-features/66728/12
53
+ # Why? Enumerable has too many methods to include at once.
54
+ def append_from( module_to_append_from, *methods_to_keep )
55
+ methods_to_keep.map! { |m| m.to_sym }
56
+
57
+ methods_to_remove = module_to_append_from.instance_methods(false) - methods_to_keep
58
+
59
+ new_mod = Module.new
60
+ new_mod.module_eval do
61
+ include module_to_append_from
62
+ methods_to_remove.each { |meth| undef_method meth }
63
+ end
64
+
65
+ # Sanity check:
66
+ check = methods_to_keep - new_mod.instance_methods(true)
67
+ raise "The following methods are not in the given module: #{check.inspect}" if !check.empty?
68
+
69
+ include new_mod
70
+ end
71
+ end
27
72
 
28
73
 
29
74
  class Array
@@ -128,29 +128,57 @@ Point2D = Struct.new("Point2D", :x, :y) {
128
128
  [array.reduce { |min, o| min.min(o) }, array.reduce { |max, o| max.max(o) } ]
129
129
  end
130
130
 
131
+ def add!(other)
132
+ self.x += other.x
133
+ self.y += other.y
134
+ return self
135
+ end
136
+
131
137
  def left
132
- return self + Dir2D.LEFT
138
+ self + Dir2D::LEFT
133
139
  end
134
140
 
135
141
  def left!
136
- x += Dir2D.LEFT.x
137
- y += Dir2D.LEFT.y
138
- return self
142
+ add!(Dir2D::LEFT)
139
143
  end
140
144
 
145
+ def right
146
+ self + Dir2D::RIGHT
147
+ end
148
+
149
+ def right!
150
+ add!(Dir2D::RIGHT)
151
+ end
152
+
153
+ def up
154
+ self + Dir2D::UP
155
+ end
156
+
157
+ def up!
158
+ add!(Dir2D::UP)
159
+ end
160
+
161
+ def down
162
+ self + Dir2D::DOWN
163
+ end
141
164
 
165
+ def down!
166
+ add!(Dir2D::DOWN)
167
+ end
168
+
142
169
  def to_dir_bitmask
143
170
 
144
- if x == 0 && y == -1
171
+ case self
172
+ when Dir2D::N
145
173
  return 1
146
- elsif x == 1 && y == 0
174
+ when Dir2D::E
147
175
  return 2
148
- elsif x == 0 && y == 1
176
+ when Dir2D::S
149
177
  return 4
150
- elsif x == -1 && y == 0
178
+ when Dir2D::W
151
179
  return 8
152
180
  else
153
- raise self.p
181
+ raise "Only Dir2Ds can be converted to direction bitmask: #{self.inspect}"
154
182
  end
155
183
  end
156
184
 
@@ -158,16 +186,16 @@ Point2D = Struct.new("Point2D", :x, :y) {
158
186
 
159
187
  result = []
160
188
  if v & 1 > 0
161
- result << Point2D.new(0, -1)
189
+ result << Dir2D::N
162
190
  end
163
191
  if v & 2 > 0
164
- result << Point2D.new(1, 0)
192
+ result << Dir2D::E
165
193
  end
166
194
  if v & 4 > 0
167
- result << Point2D.new(0, 1)
195
+ result << Dir2D::S
168
196
  end
169
197
  if v & 8 > 0
170
- result << Point2D.new(-1, 0)
198
+ result << Dir2D::W
171
199
  end
172
200
  return result
173
201
  end
@@ -205,14 +233,14 @@ Seg2D = Struct.new("Seg2D", :p1, :p2) {
205
233
 
206
234
  }
207
235
 
208
- Dirs2D = [Point2D.new(0, -1), Point2D.new(1, 0), Point2D.new(0, 1), Point2D.new(-1, 0)]
209
-
210
236
  class Dir2D < Point2D
211
237
 
212
- N = UP = Dir2D.new( 0, -1)
213
- E = RIGHT = Dir2D.new( 1, 0)
214
- S = DOWN = Dir2D.new( 0, 1)
215
- W = LEFT = Dir2D.new(-1, 0)
238
+ N = UP = Dir2D.new( 0, -1).freeze
239
+ E = RIGHT = Dir2D.new( 1, 0).freeze
240
+ S = DOWN = Dir2D.new( 0, 1).freeze
241
+ W = LEFT = Dir2D.new(-1, 0).freeze
242
+
243
+ All = [N, E, S, W]
216
244
 
217
245
  #
218
246
  # Dir2D * Range = array of Dir2D
@@ -237,13 +265,13 @@ class Dir2D < Point2D
237
265
  def self.x(length=1)
238
266
  return vert(length) + hori(length)
239
267
  end
240
-
241
268
  end
242
-
269
+
270
+ Dirs2D = Dir2D::All
243
271
 
244
272
  class Grid
245
273
 
246
- attr_reader :data
274
+ attr_accessor :data
247
275
 
248
276
  def initialize(x, y, default=0, &block)
249
277
 
@@ -323,6 +351,12 @@ class Grid
323
351
  return result
324
352
  end
325
353
 
354
+ # Mixin all methods which make sense:
355
+ # - Searching if all/any/none/one value matches something
356
+ append_from(Enumerable, :any?, :all?, :include?, :member?, :none?, :one?, :tally, :count)
357
+
358
+
359
+ # Finds the top-left (min), bottom-right (max) coordinates of this Grid using the given value 'null' as an indicator for an empty field.
326
360
  def minmax(null=nil)
327
361
  min = nil
328
362
  max = nil
@@ -374,10 +408,11 @@ class Grid
374
408
  return @data[y][x] = assign
375
409
  end
376
410
 
377
- def to_a
411
+ # Returns the underlying 2D array as a flattened array
412
+ def flatten
378
413
  return @data.flatten
379
- end
380
-
414
+ end
415
+
381
416
  #
382
417
  # Returns the Point2Ds in the directions NSEW as an array (no diagonals, see adja_index for this)
383
418
  #
@@ -437,7 +472,7 @@ class Grid
437
472
  result << Point2D.new(x-1,y-1)
438
473
  end
439
474
  result << Point2D.new(x-1,y)
440
- if y + 1 < @data.size - 1
475
+ if y + 1 < @data.size
441
476
  result << Point2D.new(x-1, y+1)
442
477
  end
443
478
  end
@@ -447,15 +482,15 @@ class Grid
447
482
 
448
483
  # result << Point2D.new(x,y)
449
484
 
450
- if y + 1 < @data.size - 1
485
+ if y + 1 < @data.size
451
486
  result << Point2D.new(x, y+1)
452
487
  end
453
- if x + 1 < @data[0].size - 1
488
+ if x + 1 < @data[0].size
454
489
  if y > 0
455
490
  result << Point2D.new(x+1,y-1)
456
491
  end
457
492
  result << Point2D.new(x+1,y)
458
- if y + 1 < @data.size - 1
493
+ if y + 1 < @data.size
459
494
  result << Point2D.new(x+1, y+1)
460
495
  end
461
496
  end
@@ -466,13 +501,13 @@ class Grid
466
501
  printBoard()
467
502
  end
468
503
 
469
- #
470
504
  # returns a copy of the underlying 2D array, with linking to the content (rather than dup the content also)
471
- #
472
505
  def to_a
473
506
  @data.map { |row| row.dup }
474
507
  end
475
508
 
509
+ # Returns access to the underlying 2D array.
510
+ # Caution: This is not a duplicate. Use to_a for this.
476
511
  def data
477
512
  @data
478
513
  end
@@ -482,24 +517,30 @@ class Grid
482
517
  #
483
518
  # If block has...
484
519
  # - one parameter, passes the cell value
485
- # - two parameters, passes y and x
520
+ # - two parameters, passes the coordinates as a Point2D and the cell value
486
521
  # - three parameteres, passes y, x and the cell value
487
522
  #
523
+ # If the block returns nil, the original value is kept.
524
+ #
488
525
  def map_a(&block)
489
526
 
490
527
  case block.arity
491
528
  when 1
492
- @data.map { |row| row.map { |value| block.call(value) } }
529
+ @data.map { |row| row.map { |value| block.call(value) || value } }
493
530
  when 2
494
- @data.each_with_index.map { |row, y| row.each_index.map { |x| block.call(y,x) } }
531
+ @data.each_with_index.map { |row, y| row.each_with_index.map { |value, x| block.call(Point2D.new(x, y), value) || value } }
495
532
  when 3
496
- @data.each_with_index.map { |row, y| row.each_with_index.map { |cell, x| block.call(y,x,cell) } }
533
+ @data.each_with_index.map { |row, y| row.each_with_index.map { |value, x| block.call(y, x, value) || value} }
497
534
  else
498
535
  raise
499
536
  end
500
537
 
501
538
  end
502
539
 
540
+ def map_a!(&block)
541
+ @data = map_a(&block)
542
+ end
543
+
503
544
  def each(&block)
504
545
  @data.each { |row|
505
546
  row.each { |cell|
@@ -603,7 +644,21 @@ Point3D = Struct.new("Point3D", :x, :y, :z) {
603
644
  end
604
645
  end
605
646
  }
606
-
607
-
608
647
 
609
-
648
+ Point4D = Struct.new("Point4D", :x, :y, :z, :w) {
649
+
650
+ def manhattan(other=nil)
651
+ if other != nil
652
+ return (self - other).manhattan
653
+ end
654
+ return x.abs + y.abs + z.abs + w.abs
655
+ end
656
+
657
+ def -(other)
658
+ Point4D.new(x - other.x, y - other.y, z - other.z, w - other.w)
659
+ end
660
+
661
+ def to_s
662
+ "#{x}, #{y}, #{z}, #{w}"
663
+ end
664
+ }
@@ -1,3 +1,3 @@
1
1
  module Cem
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Özbek
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-01 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -83,9 +83,31 @@ files:
83
83
  - bin/console
84
84
  - bin/setup
85
85
  - cem.gemspec
86
+ - examples/aoc2018/.gitignore
86
87
  - examples/aoc2018/day1.rb
88
+ - examples/aoc2018/day10.rb
89
+ - examples/aoc2018/day11.rb
90
+ - examples/aoc2018/day12.rb
91
+ - examples/aoc2018/day13.rb
92
+ - examples/aoc2018/day14.rb
93
+ - examples/aoc2018/day14_2.rb
94
+ - examples/aoc2018/day15.rb
95
+ - examples/aoc2018/day16.rb
96
+ - examples/aoc2018/day17.rb
97
+ - examples/aoc2018/day18.rb
98
+ - examples/aoc2018/day18_rspec.rb
99
+ - examples/aoc2018/day19.rb
87
100
  - examples/aoc2018/day1_part2.rb
88
101
  - examples/aoc2018/day2.rb
102
+ - examples/aoc2018/day20.rb
103
+ - examples/aoc2018/day21.rb
104
+ - examples/aoc2018/day21_v2.rb
105
+ - examples/aoc2018/day21_v3.rb
106
+ - examples/aoc2018/day21_v4.rb
107
+ - examples/aoc2018/day22.rb
108
+ - examples/aoc2018/day23.rb
109
+ - examples/aoc2018/day24.rb
110
+ - examples/aoc2018/day25.rb
89
111
  - examples/aoc2018/day2_2.rb
90
112
  - examples/aoc2018/day3.rb
91
113
  - examples/aoc2018/day4.rb
@@ -95,7 +117,44 @@ files:
95
117
  - examples/aoc2018/day7.rb
96
118
  - examples/aoc2018/day8.rb
97
119
  - examples/aoc2018/day8_part2.rb
120
+ - examples/aoc2018/day9.rb
121
+ - examples/aoc2018/day9_circular.rb
122
+ - examples/aoc2018/inputs/day10_input.txt
123
+ - examples/aoc2018/inputs/day11_input.txt
124
+ - examples/aoc2018/inputs/day12_input.txt
125
+ - examples/aoc2018/inputs/day12_input2.txt
126
+ - examples/aoc2018/inputs/day13_input.txt
127
+ - examples/aoc2018/inputs/day13_test.txt
128
+ - examples/aoc2018/inputs/day14_input.txt
129
+ - examples/aoc2018/inputs/day15_input.txt
130
+ - examples/aoc2018/inputs/day15_input10.txt
131
+ - examples/aoc2018/inputs/day15_input11.txt
132
+ - examples/aoc2018/inputs/day15_input12.txt
133
+ - examples/aoc2018/inputs/day15_input13.txt
134
+ - examples/aoc2018/inputs/day15_input14.txt
135
+ - examples/aoc2018/inputs/day15_input2.txt
136
+ - examples/aoc2018/inputs/day15_input3.txt
137
+ - examples/aoc2018/inputs/day15_input4.txt
138
+ - examples/aoc2018/inputs/day15_input5.txt
139
+ - examples/aoc2018/inputs/day15_input6.txt
140
+ - examples/aoc2018/inputs/day15_input7.txt
141
+ - examples/aoc2018/inputs/day15_input8.txt
142
+ - examples/aoc2018/inputs/day15_input9.txt
143
+ - examples/aoc2018/inputs/day15_test.txt
144
+ - examples/aoc2018/inputs/day16_input.txt
145
+ - examples/aoc2018/inputs/day17_input.txt
146
+ - examples/aoc2018/inputs/day17_input_test.txt
147
+ - examples/aoc2018/inputs/day18_input.txt
148
+ - examples/aoc2018/inputs/day18_test.txt
149
+ - examples/aoc2018/inputs/day19_input.txt
98
150
  - examples/aoc2018/inputs/day1_input.txt
151
+ - examples/aoc2018/inputs/day20_input.txt
152
+ - examples/aoc2018/inputs/day21_input.txt
153
+ - examples/aoc2018/inputs/day22_input.txt
154
+ - examples/aoc2018/inputs/day23_input.txt
155
+ - examples/aoc2018/inputs/day23_input2.txt
156
+ - examples/aoc2018/inputs/day24_input.txt
157
+ - examples/aoc2018/inputs/day25_input.txt
99
158
  - examples/aoc2018/inputs/day2_input.txt
100
159
  - examples/aoc2018/inputs/day3_input.txt
101
160
  - examples/aoc2018/inputs/day4_input.txt
@@ -103,6 +162,7 @@ files:
103
162
  - examples/aoc2018/inputs/day6_input.txt
104
163
  - examples/aoc2018/inputs/day7_input.txt
105
164
  - examples/aoc2018/inputs/day8_input.txt
165
+ - examples/aoc2018/inputs/day9_input.txt
106
166
  - lib/cem.rb
107
167
  - lib/cem/ccommon.rb
108
168
  - lib/cem/cflame.rb