diff --git a/17/input b/17/input new file mode 100644 index 0000000..a12959d --- /dev/null +++ b/17/input @@ -0,0 +1,5 @@ +Register A: 17323786 +Register B: 0 +Register C: 0 + +Program: 2,4,1,1,7,5,1,5,4,1,5,5,0,3,3,0 diff --git a/17/main.rb b/17/main.rb new file mode 100755 index 0000000..e9d47b6 --- /dev/null +++ b/17/main.rb @@ -0,0 +1,80 @@ +#!/usr/bin/env ruby + +input = (ARGV.first.nil? ? DATA : ARGF) + .readlines(chomp: true) +split = input.index("") + +registers = input[...split] + .map { _1.split(": ").last.to_i } + .zip(%i[A B C]).map(&:reverse) + .to_h +program = input[split+1].split(" ").last.split(",").map(&:to_i) + +def execute(registers, program) + stdout, ic = Array.new, 0 + + combo = ->(operand) { operand < 4 ? operand : registers.values[operand - 4] } + + while ic < program.size + opcode, operand = program[ic], program[ic + 1] + ic += 2 + + case opcode + when 0 then registers[:A] = registers[:A] / 2 ** combo.(operand) + when 1 then registers[:B] = registers[:B] ^ operand + when 2 then registers[:B] = combo.(operand) % 8 + when 3 then registers[:A] == 0 || ic = operand + when 4 then registers[:B] = registers[:B] ^ registers[:C] + when 5 then stdout << combo.(operand) % 8 + when 6 then registers[:B] = registers[:A] / 2 ** combo.(operand) + when 7 then registers[:C] = registers[:A] / 2 ** combo.(operand) + end + end + + stdout +end + +part_1 = execute(registers.dup, program).join(",") +p part_1 + +def reverse_engineer(program, slot, candidate) + return candidate if slot < 0 + + candidate <<= 3 unless slot == program.size - 1 + + (0..7) + .map { [candidate + _1, execute({A: candidate + _1, B: 0, C: 0}, program)] } + .select { _1.last == program[slot..] } + .flat_map { reverse_engineer(program, slot - 1, _1.first) } +end + +p reverse_engineer(program, program.size - 1, 0).sort.first + +# part_2 = 0 +# (program.size - 1).downto(0) do |slot| +# candidates = [] +# (0..8).each do |i| +# candidate = part_2 + i +# _, _, output = execute({A: candidate, B: 0, C: 0}, program) +# new_program = output.split(",").map(&:to_i) +# +# if new_program == program[slot..] +# candidates << candidate +# unless [301,2566855701950, 20534845615581, 20534845615573, 20534845615583].include?(candidate) +# part_2 = candidate +# end +# end +# end +# p candidates +# if slot == 0 +# p candidates.first +# end +# part_2 <<= 3 +# end + +__END__ +Register A: 117440 +Register B: 0 +Register C: 0 + +Program: 0,3,5,4,3,0