Add solution to day 16.
This commit is contained in:
parent
6ff1d97c91
commit
edfd7a1ecb
101
day16.cr
Normal file
101
day16.cr
Normal file
|
@ -0,0 +1,101 @@
|
|||
require "./common.cr"
|
||||
|
||||
lines = File.read("day16_input").split "\n"
|
||||
lines.pop
|
||||
count = 0
|
||||
end_index = 0
|
||||
start_index = 0
|
||||
|
||||
lines.each_with_index do |line, i|
|
||||
if line.size == 0
|
||||
count += 1
|
||||
else
|
||||
count = 0
|
||||
end
|
||||
|
||||
if count == 3
|
||||
end_index = i - 3
|
||||
start_index = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
registers = Array(Int32).new(4, 0)
|
||||
OPCODES = {
|
||||
"addr" => ->(regs : Array(Int32), a : Int32, b : Int32) { regs[a] + regs[b] },
|
||||
"addi" => ->(regs : Array(Int32), a : Int32, b : Int32) { regs[a] + b },
|
||||
"mulr" => ->(regs : Array(Int32), a : Int32, b : Int32) { regs[a] * regs[b] },
|
||||
"muli" => ->(regs : Array(Int32), a : Int32, b : Int32) { regs[a] * b },
|
||||
"banr" => ->(regs : Array(Int32), a : Int32, b : Int32) { regs[a] & regs[b] },
|
||||
"bani" => ->(regs : Array(Int32), a : Int32, b : Int32) { regs[a] & b },
|
||||
"borr" => ->(regs : Array(Int32), a : Int32, b : Int32) { regs[a] | regs[b] },
|
||||
"bori" => ->(regs : Array(Int32), a : Int32, b : Int32) { regs[a] | b },
|
||||
"setr" => ->(regs : Array(Int32), a : Int32, b : Int32) { regs[a] },
|
||||
"seti" => ->(regs : Array(Int32), a : Int32, b : Int32) { a },
|
||||
"gtir" => ->(regs : Array(Int32), a : Int32, b : Int32) { (a > regs[b]) ? 1 : 0 },
|
||||
"gtri" => ->(regs : Array(Int32), a : Int32, b : Int32) { (regs[a] > b) ? 1 : 0 },
|
||||
"gtrr" => ->(regs : Array(Int32), a : Int32, b : Int32) { (regs[a] > regs[b]) ? 1 : 0 },
|
||||
"eqir" => ->(regs : Array(Int32), a : Int32, b : Int32) { (a == regs[b]) ? 1 : 0 },
|
||||
"eqri" => ->(regs : Array(Int32), a : Int32, b : Int32) { (regs[a] == b) ? 1 : 0 },
|
||||
"eqrr" => ->(regs : Array(Int32), a : Int32, b : Int32) { (regs[a] == regs[b]) ? 1 : 0 },
|
||||
}
|
||||
|
||||
def find_possible(instr, before, after)
|
||||
OPCODES.select do |name, code|
|
||||
sample = before.dup
|
||||
sample[instr[3]] = code.call(sample, instr[1], instr[2])
|
||||
sample == after
|
||||
end
|
||||
end
|
||||
|
||||
ARRAY_REGEX = /[^:]+:\s*\[([^\]]*)\]/
|
||||
|
||||
class String
|
||||
def extract_array
|
||||
self.match(ARRAY_REGEX).not_nil![1].split(", ").map &.to_i32
|
||||
end
|
||||
end
|
||||
|
||||
index = 0
|
||||
count_more_three = 0
|
||||
possibilities = Array(Set(String)).new(16) { Set(String).new }
|
||||
while index < end_index
|
||||
start_array = lines[index].extract_array
|
||||
end_array = lines[index + 2].extract_array
|
||||
instruction = lines[index + 1].split(" ").map &.to_i32
|
||||
|
||||
possible = find_possible(instruction, start_array, end_array)
|
||||
count_more_three += 1 if possible.keys.size >= 3
|
||||
|
||||
opcode = instruction[0]
|
||||
old_set = possibilities[opcode]
|
||||
if old_set.empty?
|
||||
old_set.concat possible.keys
|
||||
else
|
||||
old_set.each do |it|
|
||||
old_set.delete it unless possible.has_key? it
|
||||
end
|
||||
end
|
||||
|
||||
index += 4
|
||||
end
|
||||
puts count_more_three
|
||||
|
||||
sure_possibilities = {} of Int32 => Proc(Array(Int32), Int32, Int32, Int32)
|
||||
while sure_possibilities.keys.size != 16
|
||||
possibilities.each_with_index do |set, index|
|
||||
next unless set.size == 1
|
||||
first = set.first
|
||||
sure_possibilities[index] = OPCODES[first]
|
||||
possibilities.each &.delete(first)
|
||||
end
|
||||
end
|
||||
|
||||
registers = [0, 0, 0, 0]
|
||||
index = start_index
|
||||
while index < lines.size
|
||||
instruction = lines[index].split(" ").map &.to_i32
|
||||
registers[instruction[3]] = sure_possibilities[instruction[0]].call(registers, instruction[1], instruction[2])
|
||||
index += 1
|
||||
end
|
||||
puts registers[0]
|
||||
# opcodes = {} of Int32 => Proc(Int32, Int32, Int32) # 0 => ->(x : Int32, y : Int32) { x + y }
|
Loading…
Reference in New Issue
Block a user