[2020][ruby][8.x] refactor

pull/2/head
Alpha Chen 4 years ago
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…
Cancel
Save