You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
2.3 KiB
121 lines
2.3 KiB
registers, program = DATA.read.split("\n\n")
|
|
|
|
def run(a, b, c, program)
|
|
return enum_for(__method__, a, b, c, program) unless block_given?
|
|
|
|
combo = ->(operand) {
|
|
case operand
|
|
when 0, 1, 2, 3 then operand
|
|
when 4 then a
|
|
when 5 then b
|
|
when 6 then c
|
|
else
|
|
fail
|
|
end
|
|
}
|
|
|
|
ip = 0
|
|
while (0...program.size).cover?(ip)
|
|
opcode = program.fetch(ip)
|
|
operand = program.fetch(ip+1)
|
|
case opcode
|
|
when 0
|
|
a = (a / 2**combo[operand]).to_i
|
|
ip += 2
|
|
when 1
|
|
b = b ^ operand
|
|
ip += 2
|
|
when 2
|
|
b = combo[operand] % 8
|
|
ip += 2
|
|
when 3
|
|
if a.zero?
|
|
ip += 2
|
|
else
|
|
ip = operand
|
|
end
|
|
when 4
|
|
b = b ^ c
|
|
ip += 2
|
|
when 5
|
|
yield combo[operand] % 8
|
|
ip += 2
|
|
when 6
|
|
b = (a / 2**combo[operand]).to_i
|
|
ip += 2
|
|
when 7
|
|
c = (a / 2**combo[operand]).to_i
|
|
ip += 2
|
|
else
|
|
fail
|
|
end
|
|
end
|
|
end
|
|
|
|
a, b, c = registers.scan(/\d+/).map(&:to_i)
|
|
program = program.scan(/\d+/).map(&:to_i)
|
|
|
|
# puts (211000000..).find {|a|
|
|
# pp a if a % 100_000 == 0
|
|
# program.each.lazy.zip(run(a, b, c, program)).all? { _1 == _2 }
|
|
# }
|
|
|
|
def run(a)
|
|
return enum_for(__method__, a) unless block_given?
|
|
|
|
# 14: 3 0 # jnz
|
|
until a.zero?
|
|
# 0: 2 4 # bst
|
|
# 2: 1 2 # bxl
|
|
# b = ((a & 0b111) ^ 0b010)
|
|
|
|
# 4: 7 5 # cdv
|
|
# c = a >> ((a & 0b111) ^ 0b010)
|
|
|
|
# 8: 1 7 # bxl
|
|
# 10: 4 1 # bxc
|
|
# b = ((a & 0b111) ^ 0b010) ^ c ^ 0b111
|
|
# b = ((a & 0b111) ^ 0b010) ^ (a >> ((a & 0b111) ^ 0b010)) ^ 0b111
|
|
b = (a & 0b111) ^ 0b101 ^ (a >> ((a & 0b111) ^ 0b010))
|
|
|
|
# 12: 5 5 # out
|
|
yield b & 0b111
|
|
|
|
# 6: 0 3 # adv
|
|
a >>= 3
|
|
end
|
|
end
|
|
|
|
def run(a)
|
|
return enum_for(__method__, a) unless block_given?
|
|
|
|
a.to_s(8).chars.map(&:to_i).reverse.map.with_index {|x,i|
|
|
yield (x ^ 0b101 ^ (a >> 3*i >> (x ^ 0b010))) & 0b111
|
|
}
|
|
end
|
|
|
|
pp run(27334280).to_a.join(?,)
|
|
|
|
def solve(a, target)
|
|
return [a] if a.size == 16
|
|
|
|
(0..7)
|
|
.map { a + [_1] }
|
|
.select {|a|
|
|
target.reverse[0,a.size].zip(
|
|
run(a.join.ljust(14, ?0).to_i(8)).to_a.reverse
|
|
).all? { _1 == _2 }
|
|
}.flat_map { solve(_1, target) }
|
|
end
|
|
|
|
a = solve([], program).map(&:join).map { _1.to_i(8) }.min
|
|
pp a
|
|
pp run(a).to_a == program
|
|
|
|
__END__
|
|
Register A: 27334280
|
|
Register B: 0
|
|
Register C: 0
|
|
|
|
Program: 2,4,1,2,7,5,0,3,1,7,4,1,5,5,3,0
|