[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 }
seen = Set.new }
loop do # part 1
break if @pc == @instructions.size seen = Set.new
detect_loop = ->(r, op, arg) {
throw :halt if seen.include?(r[:pc])
seen << r[:pc]
fail if seen.include?(@pc) execute[r, op, arg]
seen << @pc }
op, arg = @instructions.fetch(@pc) instructions = ARGF.read.scan(/(\w+) ([-+]\d+)/).map {|op,arg| [op.to_sym, arg.to_i] }
case op registers = Hash.new(0)
when :acc
@accumulator += arg swaps = { nop: :jmp, jmp: :nop }
@pc += 1 candidates = instructions.filter_map.with_index {|(op, arg), i|
when :jmp swap = swaps[op]
@pc += arg if swap.nil?
when :nop nil
@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