diff options
author | Nat Lasseter <user@4574.co.uk> | 2019-12-19 17:39:29 +0000 |
---|---|---|
committer | Nat Lasseter <user@4574.co.uk> | 2019-12-19 17:39:29 +0000 |
commit | d3107bc313c1cf52e7df9eb9d8ec1fe402416e3c (patch) | |
tree | cd498f79c391dbdc732744b180f5ad955bab9a05 /day17/path | |
parent | e13f5c8cf9a0c6d1540de00fd128337c5ba02bea (diff) |
Day17
Diffstat (limited to 'day17/path')
-rwxr-xr-x | day17/path | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/day17/path b/day17/path new file mode 100755 index 0000000..b6a10c9 --- /dev/null +++ b/day17/path @@ -0,0 +1,233 @@ +#!/usr/bin/env ruby + +class Machine + def initialize(starting_memory = []) + @mem = starting_memory + @pc = 0 + @halt = false + @buffered_input = [] + @buffered_output = [] + @relative_base = 0 + end + + def mem(start = 0, len = @mem.length) + @mem[start...(start + len)] + end + + def halt! + @halt = true + end + + def halt? + @halt + end + + def buffer_input(x) + if x.is_a?(Array) then + @buffered_input += x + else + @buffered_input.push(x) + end + end + + def buffered_output(flush = false) + t = @buffered_output + @buffered_output = [] if flush + t + end + + def step + return if halt? + + opcode = @mem[@pc] % 100 + + if opcode == 99 then + halt! + @pc += 1 + return + end + + p3, p2, p1 = ("%03d" % (@mem[@pc] / 100)).chars + + l1w, l1r = get(p1, 1) + l2w, l2r = get(p2, 2) if [1,2,5,6,7,8].include?(opcode) + l3w, l3r = get(p3, 3) if [1,2,7,8].include?(opcode) + + case opcode + when 1 + @mem[l3w] = l1r + l2r + @pc += 4 + when 2 + @mem[l3w] = l1r * l2r + @pc += 4 + when 3 + @mem[l1w] = @buffered_input.shift + @pc += 2 + when 4 + @buffered_output.push(l1r) + @pc += 2 + when 5 + @pc = (l1r != 0 ? l2r : @pc + 3) + when 6 + @pc = (l1r == 0 ? l2r : @pc + 3) + when 7 + @mem[l3w] = (l1r < l2r ? 1 : 0) + @pc += 4 + when 8 + @mem[l3w] = (l1r == l2r ? 1 : 0) + @pc += 4 + when 9 + @relative_base += l1r + @pc += 2 + end + end + + def run + until halt? do + step + end + end + + private + + def get(p, a) + w = case p + when "0" + @mem[@pc + a] + when "2" + @relative_base + @mem[@pc + a] + end + r = case p + when "0" + @mem[@mem[@pc + a]] + when "1" + @mem[@pc + a] + when "2" + @mem[@relative_base + @mem[@pc + a]] + end + [w, r || 0] + end +end + +input = $stdin.readlines[0].strip.split(",").map(&:to_i) + +m = Machine.new(input) +m.run +grid = m.buffered_output.map(&:chr).join.lines.map(&:strip).map(&:chars).reject(&:empty?) + +scaffs = [] +x = 0 +y = 0 +d = 0 + +grid.length.times do |r| + grid[0].length.times do |c| + scaffs << [c, r] unless grid[r][c] == "." + if %w(< ^ > v).include?(grid[r][c]) then + x = c + y = r + d = %w(< ^ > v).index(grid[r][c]) + end + end +end + +def path_end?(x, y, scaffs) + c = 0 + c += 1 if scaffs.include?([x-1, y]) + c += 1 if scaffs.include?([x+1, y]) + c += 1 if scaffs.include?([x, y-1]) + c += 1 if scaffs.include?([x, y+1]) + return c == 1 +end + +def count(x, y, d, scaffs) + c = 0 + + case d + when 0 + loop do + break unless scaffs.include?([x-1, y]) + c += 1 + x -= 1 + end + when 1 + loop do + break unless scaffs.include?([x, y-1]) + c += 1 + y -= 1 + end + when 2 + loop do + break unless scaffs.include?([x+1, y]) + c += 1 + x += 1 + end + when 3 + loop do + break unless scaffs.include?([x, y+1]) + c += 1 + y += 1 + end + end + + return x, y, c +end + +def turn(x, y, d, scaffs) + d = (d + 1) % 4 + + case d + when 0 + return d, "R" if scaffs.include?([x-1, y]) + when 1 + return d, "R" if scaffs.include?([x, y-1]) + when 2 + return d, "R" if scaffs.include?([x+1, y]) + when 3 + return d, "R" if scaffs.include?([x, y+1]) + end + + d = (d + 2) % 4 + return d, "L" +end + +def find_start(x, y, d, scaffs) + t = 0 + loop do + case d + when 0 + return d, t if scaffs.include?([x-1, y]) + when 1 + return d, t if scaffs.include?([x, y-1]) + when 2 + return d, t if scaffs.include?([x+1, y]) + when 3 + return d, t if scaffs.include?([x, y+1]) + end + d = (d + 1) % 4 + t += 1 + end +end + +path = [] + +d, t = find_start(x, y, d, scaffs) +case t +when 1 + path << "R" +when 2 + path << "R" + path << "R" +when 3 + path << "L" +end + +loop do + x, y, c = count(x, y, d, scaffs) + path << c + break if path_end?(x, y, scaffs) + d, t = turn(x, y, d, scaffs) + path << t +end + +p path |