parent
73ca0bca60
commit
8d30b0713c
@ -1,55 +1,55 @@
|
|||||||
require "set"
|
require "set"
|
||||||
|
|
||||||
class Program
|
execute = ->(r, op, arg) {
|
||||||
attr_reader :accumulator
|
delta = case op
|
||||||
|
when :acc
|
||||||
def initialize(instructions)
|
{ acc: arg, pc: 1 }
|
||||||
@instructions = instructions
|
when :jmp
|
||||||
@accumulator = 0
|
{ pc: arg }
|
||||||
@pc = 0
|
when :nop
|
||||||
|
{ pc: 1 }
|
||||||
|
else
|
||||||
|
fail
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
r.merge(delta) {|_, old, new| old + new }
|
||||||
|
}
|
||||||
|
|
||||||
|
# part 1
|
||||||
seen = Set.new
|
seen = Set.new
|
||||||
|
detect_loop = ->(r, op, arg) {
|
||||||
|
throw :halt if seen.include?(r[:pc])
|
||||||
|
seen << r[:pc]
|
||||||
|
|
||||||
loop do
|
execute[r, op, arg]
|
||||||
break if @pc == @instructions.size
|
}
|
||||||
|
|
||||||
fail if seen.include?(@pc)
|
instructions = ARGF.read.scan(/(\w+) ([-+]\d+)/).map {|op,arg| [op.to_sym, arg.to_i] }
|
||||||
seen << @pc
|
registers = Hash.new(0)
|
||||||
|
|
||||||
op, arg = @instructions.fetch(@pc)
|
swaps = { nop: :jmp, jmp: :nop }
|
||||||
case op
|
candidates = instructions.filter_map.with_index {|(op, arg), i|
|
||||||
when :acc
|
swap = swaps[op]
|
||||||
@accumulator += arg
|
if swap.nil?
|
||||||
@pc += 1
|
nil
|
||||||
when :jmp
|
|
||||||
@pc += arg
|
|
||||||
when :nop
|
|
||||||
@pc += 1
|
|
||||||
else
|
else
|
||||||
fail
|
[i, [swap, arg]]
|
||||||
end
|
end
|
||||||
|
}.map {|i, swap|
|
||||||
|
candidate = instructions.clone
|
||||||
|
candidate[i] = swap
|
||||||
|
candidate
|
||||||
|
}
|
||||||
|
|
||||||
|
candidates.each do |candidate|
|
||||||
|
seen = Set.new
|
||||||
|
registers = Hash.new(0)
|
||||||
|
catch(:halt) do
|
||||||
|
while instruction = candidate[registers[:pc]]
|
||||||
|
registers = detect_loop[registers, *instruction]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
break if registers[:pc] == candidate.size
|
||||||
end
|
end
|
||||||
|
|
||||||
instructions = ARGF.read.scan(/(\w+) ([-+]\d+)/).map {|op,arg| [op.to_sym, arg.to_i] }
|
p registers[:acc]
|
||||||
uncorrupt = { nop: :jmp, jmp: :nop }
|
|
||||||
(0...instructions.size).select {|i|
|
|
||||||
op, _ = instructions.fetch(i)
|
|
||||||
uncorrupt.has_key?(op)
|
|
||||||
}.map {|i|
|
|
||||||
attempt = instructions.clone
|
|
||||||
instruction = attempt.fetch(i)
|
|
||||||
attempt[i] = [uncorrupt.fetch(instruction[0]), instruction[1]]
|
|
||||||
attempt
|
|
||||||
}.each do |i|
|
|
||||||
program = Program.new(i)
|
|
||||||
begin
|
|
||||||
program.run
|
|
||||||
rescue
|
|
||||||
next
|
|
||||||
end
|
|
||||||
puts "accumulator: #{program.accumulator}"
|
|
||||||
end
|
|
||||||
|
Loading…
Reference in new issue