#!/usr/bin/env ruby require "debug" DEBUG = true input = (ARGV.first.nil? ? DATA : ARGF) .readlines(chomp: true) split = input.index("") registers = input[...split] .map { _1.split(": ") } .map(&:last) .map(&:to_i) .zip(%i[A B C]) .map(&:reverse) .to_h program = input[split+1] .split(" ") .last .split(",") .map(&:to_i) OPERANDS = [ ->() { 0 }, ->() { 1 }, ->() { 2 }, ->() { 3 }, ->() { registers[:A] }, ->() { registers[:B] }, ->() { registers[:C] }, ->() { :noop }, ] def execute(registers, program) stdout, commands = Array.new, Array.new i = 0 while i < program.size opcode = program[i] literal_operand = program[i+1] combo_operand = OPERANDS[literal_operand].call i += 2 case opcode when 0 numerator = registers[:A] denominator = 2 ** combo_operand registers[:A] = numerator / denominator commands << [:adv, numerator, denominator] when 1 registers[:B] = registers[:B] ^ literal_operand commands << [:bxl, literal_operand] when 2 registers[:B] = combo_operand % 8 commands << [:bst, combo_operand % 8] when 3 if registers[:A] == 0 commands << [:noop] else i = literal_operand commands << [:jnz, literal_operand] end when 4 registers[:B] = registers[:B] ^ registers[:C] commands << [:bxc, registers[:B], registers[:C]] when 5 stdout << combo_operand % 8 commands << [:out, combo_operand % 8] when 6 numerator = registers[:A] denominator = 2 ** combo_operand registers[:B] = numerator / denominator commands << [:bdv, numerator, denominator] when 7 numerator = registers[:A] denominator = 2 ** combo_operand registers[:C] = numerator / denominator commands << [:cdv, numerator, denominator] end end p commands if DEBUG [registers, program, stdout.join(",")] end original_registers = registers.dup _, _, part_1 = execute(registers, program) p part_1 registers = original_registers.dup _, _, part_2 = execute(registers, program) p program.join(",") p part_2 p part_2 == program.join(",") ? "Correct!" : "Not correct!" __END__ Register A: 2024 Register B: 0 Register C: 0 Program: 0,3,5,4,3,0