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,141 @@
1
+ #
2
+ # https://adventofcode.com/2018/day/21 part 1 and part 2
3
+ #
4
+ # Does not use any 'cem' functions
5
+ #
6
+ # Rev 4: Replace the register array access with local variables => Double speed up.
7
+ #
8
+ require 'cem'
9
+ require 'set'
10
+
11
+ lines = File.readlines("inputs/day21_input.txt", chomp: true)
12
+
13
+ commandQueue = []
14
+
15
+ r0 = r1 = r2 = r3 = r4 = r5 = 0
16
+ @s = Set.new
17
+ @last = nil
18
+
19
+ def command(verb, v1, v2, v3)
20
+
21
+ case verb
22
+ when "addr"
23
+ # addr (add @register) stores into @register C the result of adding @register A and @register B.
24
+ " r#{v3} = r#{v1} + r#{v2} "
25
+
26
+ when "addi"
27
+ # addi (add immediate) stores into @register C the result of adding @register A and value B.
28
+ " r#{v3} = r#{v1} + #{v2} "
29
+
30
+ when "mulr"
31
+ # mulr (multiply @register) stores into @register C the result of multiplying @register A and @register B.
32
+ " r#{v3} = r#{v1} * r#{v2} "
33
+
34
+ when "muli"
35
+ # muli (multiply immediate) stores into @register C the result of multiplying @register A and value B.
36
+ " r#{v3} = r#{v1} * #{v2} "
37
+
38
+ when "banr"
39
+ # banr (bitwise AND @register) stores into @register C the result of the bitwise AND of @register A and @register B.
40
+ " r#{v3} = r#{v1} & r#{v2} "
41
+
42
+ when "bani"
43
+ # bani (bitwise AND immediate) stores into @register C the result of the bitwise AND of @register A and value B.
44
+ " r#{v3} = r#{v1} & #{v2} "
45
+
46
+ when "borr"
47
+ # borr (bitwise OR @register) stores into @register C the result of the bitwise OR of @register A and @register B.
48
+ " r#{v3} = r#{v1} | r#{v2} "
49
+
50
+ when "bori"
51
+ # bori (bitwise OR immediate) stores into @register C the result of the bitwise OR of @register A and value B.
52
+ " r#{v3} = r#{v1} | #{v2} "
53
+
54
+ when "setr"
55
+ # setr (set @register) copies the contents of @register A into @register C. (Input B is ignored.)
56
+ " r#{v3} = r#{v1} "
57
+
58
+ when "seti"
59
+ # seti (set immediate) stores value A into @register C. (Input B is ignored.)
60
+ " r#{v3} = #{v1} "
61
+
62
+ when "gtir"
63
+ # gtir (greater-than immediate/@register) sets @register C to 1 if value A is greater than @register B. Otherwise, @register C is set to 0.
64
+ " r#{v3} = #{v1} > r#{v2} ? 1 : 0 "
65
+
66
+ when "gtri"
67
+ # gtri (greater-than @register/immediate) sets @register C to 1 if @register A is greater than value B. Otherwise, @register C is set to 0.
68
+ " r#{v3} = r#{v1} > #{v2} ? 1 : 0 "
69
+
70
+ when "gtrr"
71
+ # gtrr (greater-than @register/@register) sets @register C to 1 if @register A is greater than @register B. Otherwise, @register C is set to 0.
72
+ " r#{v3} = r#{v1} > r#{v2} ? 1 : 0 "
73
+
74
+ when "eqir"
75
+ # eqir (equal immediate/register) sets register C to 1 if value A is equal to register B. Otherwise, register C is set to 0.
76
+ " r#{v3} = #{v1} == r#{v2} ? 1 : 0 "
77
+
78
+ when "eqri"
79
+ # eqri (equal register/immediate) sets register C to 1 if register A is equal to value B. Otherwise, register C is set to 0.
80
+ " r#{v3} = r#{v1} == #{v2} ? 1 : 0 "
81
+
82
+ when "eqrr"
83
+ # eqrr (equal register/register) sets register C to 1 if register A is equal to register B. Otherwise, register C is set to 0.
84
+ " r#{v3} = r#{v1} == r#{v2} ? 1 : 0
85
+
86
+ if #{v2} == 0
87
+ if @s.size == 0
88
+ puts \"Part 1: \#{r#{v1}}\"
89
+ end
90
+
91
+ puts \"\#{@s.size.to_s.rjust(10)} - \#{r#{v1}}\" if @s.size % 64 == 0
92
+
93
+ if @s.include?(r#{v1})
94
+ puts \"Part 2: \#{@last}\"
95
+ exit
96
+ end
97
+ @s.add r#{v1}
98
+ @last = r#{v1}
99
+ end
100
+ "
101
+ else
102
+ puts "error" # raise "Error"
103
+ end
104
+ end
105
+
106
+
107
+ ip = nil
108
+ lines.each { |line|
109
+
110
+ if line =~ /^#ip ([+-]?\d+)$/
111
+ ip = $1.to_i
112
+ end
113
+
114
+ if line =~ /^(\w+) ([+-]?\d+) ([+-]?\d+) ([+-]?\d+)$/
115
+ verb = $1
116
+ v1 = $2.to_i
117
+ v2 = $3.to_i
118
+ v3 = $4.to_i
119
+
120
+ commandQueue << command(verb, v1, v2, v3)
121
+ end
122
+ }
123
+
124
+ ndigits = commandQueue.size.digits.size
125
+
126
+ commandQueue = <<~EOS
127
+ while
128
+
129
+ case r#{ip}
130
+ #{commandQueue.each_with_index.map { |v, i| "when #{i.to_s.rjust(ndigits)} then #{v}"}.join("\n")}
131
+ else
132
+ raise
133
+ end
134
+
135
+ r#{ip} += 1
136
+
137
+ end
138
+ EOS
139
+
140
+ puts commandQueue
141
+ eval(commandQueue)
@@ -0,0 +1,212 @@
1
+ #
2
+ # https://adventofcode.com/2018/day/22 part 1 and 2
3
+ #
4
+ # Demonstrates some use of Grid and Point2D
5
+ #
6
+ # Why this was hard: Did not read spec precisely!
7
+
8
+ require 'set'
9
+ require 'cem'
10
+
11
+ EXTRAX = 10
12
+ EXTRAY = 10
13
+
14
+ verbose = false
15
+
16
+ lines = File.readlines("inputs/day22_input.txt", chomp: true)
17
+
18
+ depth = nil
19
+ target = nil
20
+
21
+ lines.each { |line|
22
+
23
+ if line =~ /^depth: ([+-]?\d+)$/
24
+ depth = $1.to_i
25
+ end
26
+
27
+ if line =~ /^target: ([+-]?\d+),([+-]?\d+)$/
28
+ target = Point2D.new($1.to_i, $2.to_i)
29
+ end
30
+ }
31
+
32
+ @depth = depth
33
+ @target = target
34
+
35
+ def erode(x)
36
+ return (x + @depth) % 20183
37
+ end
38
+
39
+ grid = Grid.new(target.x + EXTRAX + 1, target.y + EXTRAY + 1)
40
+ grid[0,0] = 0
41
+
42
+ (1..target.x + EXTRAX).each { |x|
43
+ grid[0,x] = erode(x * 16807)
44
+ }
45
+ (1..target.y + EXTRAY).each { |y|
46
+ grid[y,0] = erode(y * 48271)
47
+ }
48
+
49
+ (1..target.y + EXTRAY).each { |y|
50
+ (1..target.x + EXTRAX).each { |x|
51
+ if target.x == x && target.y == y
52
+ grid[y,x] = erode(0)
53
+ else
54
+ grid[y,x] = erode(grid[y-1,x] * grid[y,x-1])
55
+ end
56
+ }
57
+ }
58
+
59
+ puts "Part 1: #{grid[0..target.y, 0..target.x].flatten.sum { |g| g % 3 }}"
60
+
61
+ if verbose
62
+ grid[0..target.y, 0..target.x].each { |y|
63
+ y.each { |c|
64
+ case c % 3
65
+ when 0
66
+ print '.'
67
+ when 1
68
+ print '='
69
+ when 2
70
+ print '|'
71
+ end
72
+ }
73
+ puts
74
+ }
75
+ end
76
+
77
+ #
78
+ # Part 2
79
+ #
80
+
81
+ neighter = 0
82
+ torch = 1
83
+ gear = 2
84
+
85
+ toolGrid = [0,1,2,4].map { |t| Grid.new(target.x + EXTRAX + 1, target.y + EXTRAY + 1, -1)}
86
+
87
+ toolGrid[torch][0,0] = 0
88
+
89
+ define_method :toChar do |p|
90
+ case grid[p] % 3
91
+ when 0
92
+ '.'
93
+ when 1
94
+ '='
95
+ when 2
96
+ '|'
97
+ end
98
+ end
99
+
100
+ define_method :supportedTools do |p|
101
+
102
+ case grid[p] % 3
103
+ when 0 # rocky
104
+ [gear, torch]
105
+ when 1 # wet
106
+ [neighter, gear]
107
+ when 2 # narrow
108
+ [neighter, torch]
109
+ else
110
+ raise
111
+ end
112
+ end
113
+
114
+ q = [[Point2D.new(0,0), torch]]
115
+ while q.size > 0
116
+
117
+ p, tool = q.shift
118
+
119
+ #puts "#{p.inspect} - #{tool} - #{toolGrid[tool][p]} - #{supportedTools(p)}"
120
+
121
+ sTools = supportedTools(p)
122
+ otherTools = ([0,1,2] - [tool]) & supportedTools(p)
123
+
124
+ otherTools.each { |t|
125
+ raise if t == tool
126
+ raise if !sTools.any? { |t2| t == t2 }
127
+ }
128
+
129
+ raise if toolGrid[tool][p] == -1
130
+
131
+ otherTools.each { |other|
132
+ if (toolGrid[other][p] == -1) || toolGrid[tool][p] + 7 < toolGrid[other][p]
133
+ toolGrid[other][p] = toolGrid[tool][p] + 7
134
+ q << [p, other]
135
+ end
136
+ }
137
+
138
+ grid.nsew_index(p).each { |p2|
139
+ # puts "#{p2.inspect} is adjacent to #{p} and supports the following tools #{supportedTools(p2)}"
140
+
141
+ if supportedTools(p2).include?(tool) && (toolGrid[tool][p2] == -1 || toolGrid[tool][p] + 1 < toolGrid[tool][p2])
142
+ toolGrid[tool][p2] = toolGrid[tool][p] + 1
143
+ q << [p2, tool]
144
+ end
145
+ }
146
+
147
+ q.sort_by! { |n|
148
+ p, tool = n
149
+ toolGrid[tool][p]
150
+ }
151
+
152
+ end
153
+
154
+ puts "Part 2: #{[toolGrid[torch][target], toolGrid[gear][target] + 7].min}"
155
+
156
+ if 0 == 1
157
+ (0..target.y + EXTRAY).each { |y|
158
+ (0..target.x + EXTRAX).each { |x|
159
+
160
+ case grid[y,x] % 3
161
+
162
+ when 0
163
+ print '.'
164
+ when 1
165
+ print '='
166
+ when 2
167
+ print '|'
168
+
169
+ end
170
+
171
+ print (toolGrid[torch][y,x].to_s + "," + toolGrid[neighter][y,x].to_s + "," +toolGrid[gear][y,x].to_s).rjust(8)
172
+ }
173
+ puts ""
174
+ } if DEBUG
175
+
176
+ reversePath = [[target, toolGrid[torch][target], torch]]
177
+ p = target
178
+ curTool = torch
179
+ while !(p.x == 0 && p.y == 0)
180
+
181
+ moves = grid.nsew_index(p).select { |p2| supportedTools(p2).include?(curTool) }.map { |p2| [p2, toolGrid[curTool][p2], curTool]} +
182
+ (supportedTools(p) - [curTool]).map { |t| [p, toolGrid[t][p], t, :toolChange] }
183
+
184
+ p moves
185
+ bestMove = moves.min_by { |x| x[1] }
186
+
187
+ reversePath.unshift bestMove
188
+
189
+ # puts p.inspect
190
+
191
+ p = bestMove[0]
192
+ curTool = bestMove[2]
193
+ end
194
+
195
+ reversePath.each { |x|
196
+ puts "[#{x[0].x}, #{x[0].y}, #{x[2]}] #{toChar(x[0])} #{x[1]} #{x.size > 3 ? x[3] : ""}"
197
+ }
198
+ end
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
@@ -0,0 +1,148 @@
1
+ #
2
+ # https://adventofcode.com/2018/day/23 part 1 and part 2
3
+ #
4
+ # Uses Point3D. I probably need to revisit how to subclass Point3D, Point2D.
5
+ #
6
+ require 'cem'
7
+
8
+ Bot = Struct.new("Bot", :x, :y, :z, :r) {
9
+
10
+ def [](i)
11
+ case i
12
+ when 0
13
+ x
14
+ when 1
15
+ y
16
+ when 2
17
+ z
18
+ when 3
19
+ r
20
+ else
21
+ raise
22
+ end
23
+ end
24
+
25
+ }
26
+
27
+ def manhattan(other, bot)
28
+ (other.z - bot.z).abs + (other.y - bot.y).abs + (other.x - bot.x).abs
29
+ end
30
+
31
+ def manhattan_box(bot, min, max)
32
+
33
+ result = (0..2).sum { |i|
34
+ if bot[i] >= min[i] && bot[i] <= max[i]
35
+ 0
36
+ elsif bot[i] < min[i]
37
+ min[i] - bot[i]
38
+ else
39
+ bot[i] - max[i]
40
+ end
41
+ }
42
+
43
+ #puts "#{bot.inspect} - #{min} - #{max} - #{result}"
44
+ return result
45
+
46
+ end
47
+
48
+ lines = File.readlines("inputs/day23_input.txt", chomp: true)
49
+
50
+ input = []
51
+
52
+ lines.each { |line|
53
+
54
+ if line =~ /^pos=<([+-]?\d+),([+-]?\d+),([+-]?\d+)>, r=([+-]?\d+)$/
55
+ v1 = $1.to_i
56
+ v2 = $2.to_i
57
+ v3 = $3.to_i
58
+ v4 = $4.to_i
59
+
60
+ input << Bot.new(v1,v2,v3,v4)
61
+ end
62
+
63
+ }
64
+
65
+ #
66
+ # Part I
67
+ #
68
+ bot = input.max_by { |bot| bot.r }
69
+
70
+ strength = 0
71
+ input.each { |other|
72
+
73
+ if manhattan(bot, other) <= bot.r
74
+ strength += 1
75
+ end
76
+ }
77
+
78
+ puts "Part I: #{strength}"
79
+
80
+ #
81
+ # Part II
82
+ #
83
+
84
+ # Start with the largest group we can trivially find
85
+ best = []
86
+ bestScore = -1
87
+
88
+ min = Point3D.new(*[0,1,2].map { |i| input.map { |b| b[i] }.min })
89
+ max = Point3D.new(*[0,1,2].map { |i| input.map { |b| b[i] }.max })
90
+
91
+ todo = []
92
+
93
+ # todo == [ queue of [Box min, Box max, number of elements fully covering box, number of elements still under considerations] ]
94
+ todo << [min, max, 0, input]
95
+
96
+ i = 0
97
+ while todo.size > 0
98
+
99
+ mi, ma, covered, bots = todo.shift
100
+
101
+ puts "Iteration #{i} - Still todo: #{todo.size} - Cover: #{covered} Bots: #{bots.size} Cur Size: #{(ma-mi).manhattan} - BestScore: #{bestScore}" if i % 128 == 0
102
+ i += 1
103
+
104
+ if mi == ma
105
+ hit, miss = bots.partition { |bot| manhattan(bot, mi) <= bot.r }
106
+
107
+ if bestScore < covered + hit.size
108
+ bestScore = covered + hit.size
109
+ best = [mi]
110
+ elsif bestScore == covered + hit.size
111
+ best << mi
112
+ end
113
+
114
+ next
115
+ end
116
+
117
+ # Which bots do touch the current min-max box
118
+ hit, miss = bots.partition { |bot| manhattan_box(bot, mi, ma) <= bot.r }
119
+ next if covered + hit.size < bestScore # We don't have to dig in, if we have a better high score anyway
120
+
121
+ # Which bots do completely cover the entire box and which don't? Check 8 corners to find out
122
+ corners = (0..7).map { |i| Point3D.new(i & 4 == 0 ? mi.x : ma.x, i & 2 == 0 ? mi.y : ma.y, i & 1 == 0 ? mi.z : ma.z) }
123
+ total, partial = hit.partition { |bot| corners.count { |c| manhattan(bot, c) <= bot.r } == 8 }
124
+
125
+ # Split the largest dimension of the box in half (mi to midI, midA to ma)
126
+ minDim = [0,1,2].max_by { |i| ma[i] - mi[i] }
127
+
128
+ midI = ma.clone
129
+ midI[minDim] = mi[minDim] + (ma[minDim] - mi[minDim]) / 2
130
+
131
+ midA = mi.clone
132
+ midA[minDim] = mi[minDim] + (ma[minDim] - mi[minDim]) / 2 + 1
133
+
134
+ todo << [mi, midI, covered + total.size, partial]
135
+ todo << [midA, ma, covered + total.size, partial]
136
+
137
+ todo.sort_by! { |t| -(t[2] + t[3].size) * (max-min).manhattan + manhattan(t[0], t[1]) } if i % 4 == 0
138
+ end
139
+
140
+ puts "Best Positions: " + best.to_s
141
+ puts "Number of Bots In Range: #{bestScore}"
142
+ puts "Lowest Manhattan Distance to 0,0,0: #{best.map { |b| b.manhattan }.min}"
143
+
144
+
145
+
146
+
147
+
148
+