1
0
Fork 0
advent-of-code-2024/17/main.rb

114 lines
2.5 KiB
Ruby
Raw Normal View History

2024-12-17 01:13:47 -05:00
#!/usr/bin/env ruby
require "debug"
2024-12-17 12:05:03 -05:00
DEBUG = false
2024-12-17 01:13:47 -05:00
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 },
]
2024-12-17 01:25:41 -05:00
def execute(registers, program)
2024-12-17 08:52:46 -05:00
stdout, commands = Array.new, Array.new
2024-12-17 01:13:47 -05:00
2024-12-17 12:05:03 -05:00
ic = 0
while ic < program.size
opcode = program[ic]
literal_operand = program[ic+1]
2024-12-17 01:25:41 -05:00
combo_operand = OPERANDS[literal_operand].call
2024-12-17 01:13:47 -05:00
2024-12-17 12:05:03 -05:00
ic += 2
2024-12-17 01:13:47 -05:00
2024-12-17 01:25:41 -05:00
case opcode
when 0
numerator = registers[:A]
denominator = 2 ** combo_operand
registers[:A] = numerator / denominator
2024-12-17 08:52:46 -05:00
commands << [:adv, numerator, denominator]
2024-12-17 01:25:41 -05:00
when 1
registers[:B] = registers[:B] ^ literal_operand
2024-12-17 08:52:46 -05:00
commands << [:bxl, literal_operand]
2024-12-17 01:25:41 -05:00
when 2
registers[:B] = combo_operand % 8
2024-12-17 08:52:46 -05:00
commands << [:bst, combo_operand % 8]
2024-12-17 01:25:41 -05:00
when 3
if registers[:A] == 0
2024-12-17 08:52:46 -05:00
commands << [:noop]
2024-12-17 01:25:41 -05:00
else
2024-12-17 12:05:03 -05:00
ic = literal_operand
2024-12-17 08:52:46 -05:00
commands << [:jnz, literal_operand]
2024-12-17 01:25:41 -05:00
end
when 4
registers[:B] = registers[:B] ^ registers[:C]
2024-12-17 08:52:46 -05:00
commands << [:bxc, registers[:B], registers[:C]]
2024-12-17 01:25:41 -05:00
when 5
stdout << combo_operand % 8
2024-12-17 08:52:46 -05:00
commands << [:out, combo_operand % 8]
2024-12-17 01:25:41 -05:00
when 6
numerator = registers[:A]
denominator = 2 ** combo_operand
registers[:B] = numerator / denominator
2024-12-17 08:52:46 -05:00
commands << [:bdv, numerator, denominator]
2024-12-17 01:25:41 -05:00
when 7
numerator = registers[:A]
denominator = 2 ** combo_operand
registers[:C] = numerator / denominator
2024-12-17 08:52:46 -05:00
commands << [:cdv, numerator, denominator]
2024-12-17 01:13:47 -05:00
end
end
2024-12-17 01:25:41 -05:00
2024-12-17 12:05:03 -05:00
if DEBUG
commands.each { puts _1.join(" ") }
end
2024-12-17 08:52:46 -05:00
2024-12-17 01:25:41 -05:00
[registers, program, stdout.join(",")]
2024-12-17 01:13:47 -05:00
end
2024-12-17 12:05:03 -05:00
part_2 = registers[:A].dup
2024-12-17 01:25:41 -05:00
_, _, part_1 = execute(registers, program)
p part_1
2024-12-17 01:13:47 -05:00
2024-12-17 12:05:03 -05:00
while true
part_2 += 100_00
registers = {A: part_2, B: 0, C: 0}
_, _, output = execute(registers, program)
p "#{part_2} (a): #{output}"
break if output.match?(/4,1,5,5,0,3,3,0$/)
end
while part_2 <<= 3
registers = {A: part_2, B: 0, C: 0}
_, _, output = execute(registers, program)
next if output.size < 31
p "#{part_2} (b): #{output}"
raise if output.size > 31
end
2024-12-17 01:13:47 -05:00
__END__
2024-12-17 01:25:41 -05:00
Register A: 2024
2024-12-17 01:13:47 -05:00
Register B: 0
Register C: 0
2024-12-17 01:25:41 -05:00
Program: 0,3,5,4,3,0