Code for the Advent of Code event
aoc advent-of-code
at main 105 lines 1.9 kB view raw
1#!/usr/bin/env ruby 2# frozen_string_literal: true 3 4class CPU 5 attr_reader :recovered_frequency, :send_count 6 7 def initialize(send_queue = nil, recv_queue = nil) 8 @send_queue = send_queue 9 @recv_queue = recv_queue 10 @registers = Hash.new 0 11 @pc = 0 12 @send_count = 0 13 end 14 15 def load(program) 16 @program = program.map(&:split) 17 self 18 end 19 20 def run_part1 21 step while @pc >= 0 && @pc < @program.size && !recovered_frequency 22 self 23 end 24 25 def run_part2 26 @wait = false 27 step while @pc >= 0 && @pc < @program.size && !@wait 28 end 29 30 def step 31 instruction = @program[@pc] 32 send(*instruction) 33 @pc += 1 34 end 35 36 def snd(freq) 37 freq = resolve(freq) 38 @last_frequency = freq 39 return unless @send_queue 40 @send_queue.enq freq 41 @send_count += 1 42 end 43 44 def set(reg, value) 45 @registers[reg] = resolve(value) 46 end 47 48 def add(reg, value) 49 @registers[reg] += resolve(value) 50 end 51 52 def mul(reg, value) 53 @registers[reg] *= resolve(value) 54 end 55 56 def mod(reg, value) 57 @registers[reg] %= resolve(value) 58 end 59 60 def rcv(value) 61 @recovered_frequency = @last_frequency unless resolve(value) == 0 62 return if @recv_queue.nil? 63 if @recv_queue.empty? 64 @pc -= 1 65 @wait = true 66 return 67 end 68 @registers[value] = @recv_queue.deq 69 end 70 71 def jgz(value, offset) 72 return if resolve(value) <= 0 73 @pc += resolve(offset) - 1 74 end 75 76 private 77 78 def resolve(value) 79 n = value.to_i 80 n.to_s == value ? n : @registers[value] 81 end 82end 83 84PROGRAM = ARGF.readlines 85 86puts CPU.new.load(PROGRAM).run_part1.recovered_frequency 87 88a_to_b = Queue.new 89b_to_a = Queue.new 90 91a = CPU.new(a_to_b, b_to_a).load(PROGRAM) 92a.set 'p', '0' 93 94b = CPU.new(b_to_a, a_to_b).load(PROGRAM) 95b.set 'p', '1' 96 97a.run_part2 98b.run_part2 99 100while !a_to_b.empty? || !b_to_a.empty? 101 a.run_part2 102 b.run_part2 103end 104 105puts b.send_count