cem 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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
+