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,271 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/15 part 1 and part 2
4
+ #
5
+ # Demonstrate use of Point2D and Grid
6
+ #
7
+ # This task took me a long time, because I did a array.sort instead of array.sort!
8
+ #
9
+
10
+ require 'cem'
11
+
12
+ Agent = Struct.new("Agent", :pos, :faction, :hp)
13
+
14
+ class Puzzle
15
+
16
+ attr_accessor :persons, :lines, :dirs
17
+
18
+ def initialize
19
+ @persons = []
20
+ @grid = []
21
+ @dirs = []
22
+ end
23
+
24
+ def others(o)
25
+ @persons.select { |p| p.faction != o.faction }
26
+ end
27
+
28
+ def adjacents(o)
29
+ @dirs.map {|dir| o.pos + dir if @grid[o.pos + dir] == '.'}.compact
30
+ end
31
+
32
+ def free(pos)
33
+ @grid[pos] == '.' && @persons.find { |p| p.pos == pos } == nil
34
+ end
35
+
36
+ def printBoard(overlay = nil)
37
+
38
+ @grid.data.each_with_index { |l, y|
39
+ l.each_with_index { |c, x|
40
+
41
+ pos = Point2D.new(x,y)
42
+
43
+ if overlay && overlay.has_key?(pos)
44
+ print overlay[pos]
45
+ else
46
+ p = @persons.find { |p| p.pos == pos }
47
+ if p
48
+ print p.faction
49
+ else
50
+ print c
51
+ end
52
+ end
53
+ }
54
+
55
+ puts " " + @persons.select{ |p| p.pos.y == y }.sort_by { |p| p.pos.x }.map {|p| "#{p.faction}(#{p.hp})"}.join(", ")
56
+ }
57
+ end
58
+
59
+ def run(inputFilename, debug, elvenPower=3)
60
+
61
+ # Crucial to sort the directions as given in the problem description
62
+ @dirs = Dirs2D.sort_by { |pos| pos.y * 10000 + pos.x }
63
+
64
+ lines = []
65
+ File.readlines(inputFilename, chomp: true).each { |line|
66
+ lines << line.rstrip.chars
67
+ }
68
+
69
+ @grid = Grid.new(lines.size, lines[0].size, ' ')
70
+ @grid.data = lines
71
+
72
+ # Read board
73
+ @grid.map_a! { |p, c|
74
+ case c
75
+ when 'E', 'G'
76
+ @persons << Agent.new(p, c, 200)
77
+ next '.'
78
+ end
79
+ }
80
+
81
+ generation = -1
82
+
83
+ loop do
84
+
85
+ system "cls" if debug
86
+
87
+ generation += 1
88
+
89
+ if generation == 0
90
+ puts "Initial Generation with power #{elvenPower}" if debug
91
+ else
92
+ puts "After Generation: #{generation} with power #{elvenPower}" if debug
93
+ end
94
+
95
+ printBoard if debug
96
+ #gets if debug && generation >= 70
97
+
98
+ @persons.sort_by { |cart| cart.pos.y * 10000 + cart.pos.x }.each { |p|
99
+
100
+ next if !@persons.include?(p)
101
+
102
+ if @persons.select {|p| p.faction == 'E' }.size == 0 || @persons.select {|p| p.faction == 'G' }.size == 0
103
+ system "cls" if debug
104
+ puts "Before Generation: #{generation} finishes" if debug
105
+ printBoard if debug
106
+
107
+ puts "#{generation} * #{@persons.sum {|p| p.hp }} = #{generation * @persons.sum {|p| p.hp }}"
108
+ return (@persons[0].faction == 'E' ? 1 : -1) * generation * @persons.sum {|p| p.hp }
109
+ end
110
+
111
+ # puts p.inspect
112
+
113
+ # Moving
114
+ nearby = @persons.select { |o| o.faction != p.faction && dirs.any? { |dir| p.pos + dir == o.pos } }.group_by { |o| o.hp }.min_by { |k,v| k }
115
+
116
+ if nearby == nil || nearby.size == 0
117
+ distancemap = Array.new(@grid.data.size) { Array.new(@grid[0].size)}
118
+
119
+ targets = Set.new(others(p).map {|o| adjacents(o)}.flatten)
120
+
121
+ s = p.pos
122
+ distancemap[s.y][s.x] = 0
123
+ bfs = []
124
+ bfsNG = [s]
125
+ found = []
126
+
127
+ target = []
128
+ while bfsNG.size > 0 && found.size == 0
129
+ bfs = bfsNG
130
+ bfsNG = []
131
+ while bfs.size > 0
132
+
133
+ s = bfs.shift
134
+
135
+ dirs.each { |dir|
136
+
137
+ s2 = s + dir
138
+
139
+ if free(s2)
140
+
141
+ if distancemap[s2.y][s2.x] == nil
142
+ bfsNG << s2
143
+ #puts " free " + s2.inspect + " - " + dir.to_s
144
+ distancemap[s2.y][s2.x] = dir.flip
145
+ end
146
+
147
+ if targets.include?(s2)
148
+ found << s2
149
+ end
150
+ end
151
+ }
152
+ end
153
+ end
154
+
155
+ if found.size > 0
156
+ found.sort_by! { |p| p.y * 10000 + p.x }
157
+
158
+ overlay = {}
159
+
160
+ if found.size > 1
161
+ found.each { |p| overlay[p] = '+' }
162
+ overlay[found[0]] = 'X'
163
+ end
164
+
165
+ target = found[0]
166
+ #puts " Target: #{target}"
167
+
168
+ lastMove = nil
169
+
170
+ while target && target != p.pos
171
+ lastMove = distancemap[target.y][target.x]
172
+ #puts target.inspect
173
+ overlay[target] = 'x'
174
+ target = target + lastMove
175
+ end
176
+
177
+ #if generation >= 77
178
+ # system('cls')
179
+ # printBoard(overlay)
180
+ # puts found.inspect
181
+ # gets
182
+ #end
183
+
184
+ p.pos = p.pos + lastMove.flip if lastMove
185
+ #puts " Moved to #{p.pos}"
186
+ end
187
+ end
188
+
189
+ # Fighting
190
+ nearby = @persons.select { |o| o.faction != p.faction && dirs.any? { |dir| p.pos + dir == o.pos } }.group_by { |o| o.hp }.min_by { |k,v| k }
191
+ if nearby && nearby.size > 0
192
+ nearby = nearby[1]
193
+
194
+ #puts "Fighting"
195
+ nearby.sort_by! { |cart| cart.pos.y * 10000 + cart.pos.x }
196
+
197
+ if p.faction == 'E'
198
+ nearby[0].hp -= elvenPower
199
+ else
200
+ nearby[0].hp -= 3
201
+ end
202
+
203
+ if (nearby[0].hp <= 0)
204
+ @persons -= [nearby[0]]
205
+
206
+ if nearby[0].faction == 'E' && elvenPower > 3
207
+ return -1
208
+ end
209
+ end
210
+ end
211
+
212
+ }
213
+
214
+
215
+ end
216
+ end
217
+
218
+ end
219
+
220
+ part1 = {
221
+ # "inputs/day15_input14.txt" => -248848,
222
+ # "inputs/day15_input13.txt" => -261855,
223
+ # "inputs/day15_input12.txt" => -189000,
224
+ # "inputs/day15_input11.txt" => '?',
225
+ # "inputs/day15_input10.txt" => -261855,
226
+ # "inputs/day15_input2.txt" => -27730,
227
+ # "inputs/day15_input3.txt" => -18740,
228
+ # "inputs/day15_input4.txt" => 36334,
229
+ # "inputs/day15_input5.txt" => 39514,
230
+ # "inputs/day15_input6.txt" => -27755,
231
+ # "inputs/day15_input7.txt" => -28944,
232
+ "inputs/day15_input.txt" => '?'
233
+ }
234
+
235
+ debug = false
236
+
237
+ part1.each_pair { |k,v|
238
+
239
+ power = 3
240
+ is = Puzzle.new.run(k, debug, power)
241
+
242
+ puts "Part 1: #{k} == #{is}"
243
+ if is != v && v != '?'
244
+ puts "#{k} should be #{v}, but is #{is}"
245
+ exit
246
+ end
247
+ }
248
+
249
+
250
+ part2 = {
251
+ "inputs/day15_input.txt" => '?'
252
+ }
253
+
254
+ part2.each_pair { |k,v|
255
+
256
+ power = 4
257
+ while true
258
+ # puts "Elven Power: #{power} "
259
+ is = Puzzle.new.run(k, debug, power)
260
+ power += 1
261
+ if is > 0
262
+ break;
263
+ end
264
+ end
265
+
266
+ puts "Part 2: #{k} == #{is}"
267
+ if is != v && v != '?'
268
+ puts "#{k} should be #{v}, but is #{is}"
269
+ exit
270
+ end
271
+ }
@@ -0,0 +1,158 @@
1
+ #
2
+ # https://adventofcode.com/2018/day/16 part 1 and part 2
3
+ #
4
+ # Does not use any 'cem' functions
5
+ #
6
+
7
+ input = File.readlines("inputs/day16_input.txt", chomp: true)
8
+
9
+ data = []
10
+ inputs = []
11
+
12
+ input.each { |line|
13
+
14
+ if line =~ /^Before\: \[([+-]?\d+), ([+-]?\d+), ([+-]?\d+), ([+-]?\d+)\]$/
15
+
16
+ v1 = $1.to_i
17
+ v2 = $2.to_i
18
+ v3 = $3.to_i
19
+ v4 = $4.to_i
20
+
21
+ data << [v1,v2,v3,v4]
22
+
23
+ end
24
+
25
+ if line =~ /^([+-]?\d+) ([+-]?\d+) ([+-]?\d+) ([+-]?\d+)$/
26
+
27
+
28
+ v1 = $1.to_i
29
+ v2 = $2.to_i
30
+ v3 = $3.to_i
31
+ v4 = $4.to_i
32
+
33
+ data << [v1,v2,v3,v4]
34
+ end
35
+
36
+ if line =~ /^After\: \[([+-]?\d+), ([+-]?\d+), ([+-]?\d+), ([+-]?\d+)\]$/
37
+ v1 = $1.to_i
38
+ v2 = $2.to_i
39
+ v3 = $3.to_i
40
+ v4 = $4.to_i
41
+
42
+ data << [v1,v2,v3,v4]
43
+
44
+ # puts data.inspect
45
+ inputs << data
46
+ data = []
47
+ end
48
+
49
+ if line =~ /^$/
50
+ # data << $1.to_i
51
+ end
52
+ }
53
+
54
+ mapping = {}
55
+
56
+ def op(op, reg, command)
57
+
58
+ case op
59
+
60
+ when 0 # addr
61
+ reg[command[1]] + reg[command[2]]
62
+
63
+ when 1 # addi
64
+ reg[command[1]] + command[2]
65
+
66
+ when 2 # mulr
67
+ reg[command[1]] * reg[command[2]]
68
+
69
+ when 3 #muli
70
+ reg[command[1]] * command[2]
71
+
72
+ when 4 # banr
73
+ reg[command[1]] & reg[command[2]]
74
+
75
+ when 5 # bani
76
+ reg[command[1]] & command[2]
77
+
78
+ when 6 # borr
79
+ reg[command[1]] | reg[command[2]]
80
+
81
+ when 7 # bori
82
+ reg[command[1]] | command[2]
83
+
84
+ when 8 # setr
85
+ reg[command[1]]
86
+
87
+ when 9 # seti
88
+ command[1]
89
+
90
+ when 10 # gtir
91
+ command[1] > reg[command[2]] ? 1 : 0
92
+
93
+ when 11 # gtri
94
+ reg[command[1]] > command[2] ? 1 : 0
95
+
96
+ when 12 # gtrr
97
+ reg[command[1]] > reg[command[2]] ? 1 : 0
98
+
99
+ when 13 # eqir
100
+ command[1] == reg[command[2]] ? 1 : 0
101
+
102
+ when 14 # eqri
103
+ reg[command[1]] == command[2] ? 1 : 0
104
+
105
+ when 15 # eqrr
106
+ reg[command[1]] == reg[command[2]] ? 1 : 0
107
+
108
+ else
109
+ raise
110
+ end
111
+ end
112
+
113
+ result = 0
114
+ inputs.each { |data|
115
+
116
+ # puts data.inspect
117
+
118
+ # puts "Before: " + data[0].inspect
119
+ # puts "OP : " + data[1].inspect
120
+ # puts "After : " + data[2].inspect
121
+
122
+ # puts data[1].inspect + ": Cmd #{data[1][0]} on reg#{data[1][1]} val=#{data[0][data[1][1]]} op? reg#{data[1][2]} val=#{data[0][data[1][2]]} (imm #{data[1][2]}) == #{data[2][data[1][3]]} (was #{data[0][data[1][3]]})"
123
+
124
+ command = data[1]
125
+ matches = []
126
+ (0..15).each { |i|
127
+
128
+ reg = data[0].dup
129
+
130
+ reg[command[3]] = op(i, reg, command)
131
+
132
+ if reg == data[2]
133
+ matches << i
134
+ end
135
+ }
136
+
137
+ result += 1 if matches.size >= 3
138
+
139
+ matches = matches.select { |m| !mapping.values.include?(m) }
140
+
141
+ if matches.size == 1
142
+ mapping[data[1][0]] = matches[0]
143
+ end
144
+
145
+ # puts matches.inspect
146
+ }
147
+
148
+ # puts mapping.inspect
149
+
150
+ puts "Part 1: #{result}"
151
+
152
+ reg = [0,0,0,0]
153
+
154
+ data.each { |command|
155
+ reg[command[3]] = op(mapping[command[0]], reg, command)
156
+ }
157
+
158
+ puts "Part 2: #{reg[0]}"
@@ -0,0 +1,203 @@
1
+
2
+ #
3
+ # https://adventofcode.com/2018/day/17 part 1 and 2
4
+ #
5
+ # Demonstrates Point2D and Dir2D in particular #left, #right, #down methods. Could use Grid!
6
+ #
7
+
8
+ require 'cem'
9
+ require 'set'
10
+
11
+ input = File.readlines("inputs/day17_input.txt", chomp: true)
12
+
13
+ @vert = []
14
+ @hori = []
15
+ @waterTiles = Set.new
16
+ @deepWater = Set.new
17
+
18
+ input.each { |line|
19
+
20
+ if line =~ /^y=([+-]?\d+), x=([+-]?\d+)..([+-]?\d+)$/
21
+ v1 = $1.to_i
22
+ v2 = $2.to_i
23
+ v3 = $3.to_i
24
+
25
+ @vert << [v1,v2,v3]
26
+ end
27
+
28
+ if line =~ /^x=([+-]?\d+), y=([+-]?\d+)..([+-]?\d+)$/
29
+ v1 = $1.to_i
30
+ v2 = $2.to_i
31
+ v3 = $3.to_i
32
+
33
+ @hori << [v1,v2,v3]
34
+ end
35
+ }
36
+
37
+ @minY = [@vert.map { |v| v[0] }.min, @hori.map { |h| h[1] }.min].min
38
+ @maxY = [@vert.map { |v| v[0] }.max, @hori.map { |h| h[2] }.max].max
39
+
40
+ @minX = [@hori.map { |v| v[0] }.min, @vert.map { |h| h[1] }.min].min
41
+ @maxX = [@hori.map { |v| v[0] }.max, @vert.map { |h| h[2] }.max].max
42
+
43
+ cursor = Point2D.new(500, @minY)
44
+
45
+ @map = []
46
+ (0..@maxY + 1).each { |y|
47
+ @map << []
48
+ (0..@maxX + 1).each { |x|
49
+ @map[y] << ' '
50
+ }
51
+ }
52
+
53
+ @vert.each { |v|
54
+ (v[1]..v[2]).each {|x| @map[v[0]][x] = 'x' }
55
+ }
56
+ @hori.each {|h|
57
+ (h[1]..h[2]).each {|y| @map[y][h[0]] = 'x' }
58
+ }
59
+
60
+ def free(cursor)
61
+ @map[cursor.y][cursor.x] == ' '
62
+ end
63
+
64
+ def printMap(filename, map, overlay, deepWater, cursor=nil, windowSizeY = 15, windowSizeX = 35)
65
+
66
+ file = File.open(filename, 'w') if filename
67
+
68
+ if !filename
69
+ system('cls')
70
+ puts cursor
71
+ end
72
+
73
+ rangeY = cursor ? ((cursor.y - windowSizeY)..(cursor.y + windowSizeY)) : 0...map.size
74
+ rangeX = cursor ? ((cursor.x - windowSizeX)..(cursor.x + windowSizeX)) : 0...map[0].size
75
+
76
+ rangeY.each { |y|
77
+ l = map[y]
78
+ line = ''
79
+ rangeX.each { |x|
80
+ if l != nil
81
+ c = l[x]
82
+ else
83
+ c = nil
84
+ end
85
+
86
+ if c == nil
87
+ c = '?'
88
+ end
89
+
90
+ pos = Point2D.new(x,y)
91
+ if deepWater && deepWater.include?(pos)
92
+ line += '~'
93
+ elsif overlay && overlay.include?(pos)
94
+ line += '|'
95
+ else
96
+ line += c
97
+ end
98
+ }
99
+ if filename
100
+ file.write(line + "\n")
101
+ else
102
+ puts line
103
+ end
104
+ }
105
+
106
+ if !filename
107
+ gets
108
+ else
109
+ file.close
110
+ end
111
+
112
+ end
113
+
114
+ #
115
+ # returns true if all available space has been filled
116
+ #
117
+ def cursorMove(cursor)
118
+
119
+ cursorStart = cursor
120
+
121
+ @waterTiles << cursor
122
+
123
+ # Traverse down from cursor position
124
+ while free(cursor.down) && cursor.y < @maxY && !@waterTiles.include?(cursor.down)
125
+ printMap(nil, @map, @waterTiles, @deepWater, cursor) if false
126
+
127
+ cursor = cursor.down
128
+ @waterTiles << cursor
129
+ end
130
+
131
+ if cursor.y == @maxY
132
+ return false # we moved out of the field - stop recursion
133
+ end
134
+
135
+ if @waterTiles.include?(cursor.down) && !@deepWater.include?(cursor.down)
136
+ return false # already been here
137
+ end
138
+
139
+ # Below us is rock
140
+ left = right = rowStart = cursor
141
+
142
+ row = Set.new
143
+ row << rowStart
144
+
145
+ while true
146
+
147
+ while free(left.left) && !@waterTiles.include?(left.left) && (!free(left.down) || @deepWater.include?(left.down))
148
+ left = left.left
149
+ row << left
150
+ @waterTiles << left
151
+ end
152
+
153
+ while free(right.right) && !@waterTiles.include?(right.right) && (!free(right.down) || @deepWater.include?(right.down))
154
+ right = right.right
155
+ row << right
156
+ @waterTiles << right
157
+ end
158
+
159
+ printMap(nil, @map, @waterTiles, @deepWater, cursor) if false # && cursor.y > 1300 && cursor.y < 1330
160
+
161
+ if !free(right.right) && (!free(right.down) || @deepWater.include?(right.down)) && !free(left.left) && (!free(left.down) || @deepWater.include?(left.down))
162
+
163
+ # Move up
164
+ rowStart = rowStart.up
165
+
166
+ @deepWater.merge row
167
+ row = Set.new
168
+ row << rowStart
169
+
170
+ if rowStart.y < cursorStart.y
171
+ return true # Return true, if we filled all available space
172
+ end
173
+
174
+ left = right = rowStart
175
+
176
+ # Fill again...
177
+
178
+ else
179
+
180
+ a = !@waterTiles.include?(right.right) && !@waterTiles.include?(left.left)
181
+ if free(right.down) && !(!free(right.down) || @deepWater.include?(right.down))
182
+ a &= cursorMove(right.down)
183
+ end
184
+
185
+ if free(left.left) && !(!free(left.down) || @deepWater.include?(left.down))
186
+ a &= cursorMove(left.down)
187
+ end
188
+
189
+ if !a
190
+ break
191
+ end
192
+ end
193
+ end
194
+
195
+ return false
196
+ end
197
+
198
+ cursorMove(cursor)
199
+
200
+ printMap("day17.out", @map, @waterTiles, @deepWater) if false
201
+
202
+ puts "Part 1: #{@waterTiles.size}"
203
+ puts "Part 2: #{@deepWater.size}"