Checking in Day 17 even though I haven't figured out part 2 yet. I\'m coming back to it
parent
791d6d9c69
commit
cadb944182
@ -0,0 +1,180 @@
|
||||
defmodule Day17 do
|
||||
def run do
|
||||
[registers, program] =
|
||||
File.read!("data.txt")
|
||||
|> String.trim()
|
||||
|> String.split("\n\n")
|
||||
|> Enum.with_index()
|
||||
|> Enum.map(fn {lines, idx} ->
|
||||
if idx == 0, do: parseRegisters(lines), else: parseProgram(lines)
|
||||
end)
|
||||
|
||||
# registers = %{A: 2024, B: 0, C: 0}
|
||||
# program = [0, 1, 5, 4, 3, 0]
|
||||
|
||||
initial_state = %{
|
||||
program: program,
|
||||
registers: registers,
|
||||
pointer: 0,
|
||||
output: []
|
||||
}
|
||||
|
||||
dbg(initial_state)
|
||||
|
||||
state = run(initial_state)
|
||||
output = Enum.reverse(state.output)
|
||||
dbg(output)
|
||||
|
||||
# part 2
|
||||
# target is [2, 4, 1, 6, 7, 5, 4, 4, 1, 7, 0, 3, 5, 5, 3, 0]
|
||||
# noticing every power of 8 it adds a digit
|
||||
# the new big digit goes [1], 0, 3, 2, 4, 4, 1, 5
|
||||
# when there's 1 digit, the biggest digit changes every 1
|
||||
# when there are 2 digits, the biggest digit changes every 8
|
||||
# when there are 3 digits, the biggest digit changes every 8 * 8
|
||||
# etc.
|
||||
# when there are 16 digits, the biggest digit changes every 8 ^ 15
|
||||
# if the first digit is 2, that's the 3rd in the sequence, so 3x that
|
||||
#
|
||||
# 1 0 3 2 4 4 1 5
|
||||
# when 2 digits, the smaller digit goes:
|
||||
# 0: 1 0 3 2 6 5 1 1
|
||||
# 3: 1 0 2 2 0 6 1 5
|
||||
# 2: 1 0 2 2 2 7 1 1
|
||||
# 4: 1 0 1 3 4 0 1 5
|
||||
# 4: 1 0 1 3 6 1 1 1
|
||||
# 1: 1 0 0 3 0 2 1 5
|
||||
# 5: 1 0 0 3 2 3 1 1
|
||||
#
|
||||
# when 3 digits, smallest digit goes
|
||||
# 0 0 7 0 4 4 1 5
|
||||
#
|
||||
# starter = 3 * 8 ** 15 + 6 * 8 ** 14 + 6 * 8 ** 13 # interesting, all ones
|
||||
starter = 2 * 8 ** 15
|
||||
increment = 8 ** 10
|
||||
|
||||
try(starter, initial_state, increment)
|
||||
end
|
||||
|
||||
defp try(a, state, increment) do
|
||||
# IO.gets("")
|
||||
new_state = %{state | registers: %{state.registers | A: a}}
|
||||
val = run(new_state)
|
||||
|
||||
# if Integer.mod(a, 1000) == 0 do
|
||||
IO.puts(a)
|
||||
dbg(a)
|
||||
dbg(val)
|
||||
# end
|
||||
|
||||
if Enum.reverse(val.output) == state.program do
|
||||
a
|
||||
else
|
||||
try(a + increment, state, increment)
|
||||
end
|
||||
end
|
||||
|
||||
defp run(
|
||||
%{
|
||||
program: program,
|
||||
registers: registers,
|
||||
pointer: pointer,
|
||||
output: output
|
||||
} = state
|
||||
) do
|
||||
opcode = Enum.at(program, pointer)
|
||||
operand = Enum.at(program, pointer + 1)
|
||||
# dbg({"run", state})
|
||||
|
||||
if is_nil(opcode) do
|
||||
state
|
||||
else
|
||||
new_state =
|
||||
case opcode do
|
||||
# adv
|
||||
0 ->
|
||||
num = registers[:A]
|
||||
den = Integer.pow(2, getComboOperandValue(operand, registers))
|
||||
new_regs = %{registers | A: trunc(num / den)}
|
||||
|
||||
%{state | registers: new_regs, pointer: pointer + 2}
|
||||
|
||||
# bxl
|
||||
1 ->
|
||||
new_regs = %{registers | B: Bitwise.bxor(registers[:B], operand)}
|
||||
%{state | registers: new_regs, pointer: pointer + 2}
|
||||
|
||||
# bst
|
||||
2 ->
|
||||
new_regs = %{
|
||||
registers
|
||||
| B: Integer.mod(getComboOperandValue(operand, registers), 8)
|
||||
}
|
||||
|
||||
%{state | registers: new_regs, pointer: pointer + 2}
|
||||
|
||||
# jnz
|
||||
3 ->
|
||||
if registers[:A] == 0 do
|
||||
%{state | pointer: pointer + 2}
|
||||
else
|
||||
%{state | pointer: operand}
|
||||
end
|
||||
|
||||
# bxc
|
||||
4 ->
|
||||
new_regs = %{registers | B: Bitwise.bxor(registers[:B], registers[:C])}
|
||||
%{state | registers: new_regs, pointer: pointer + 2}
|
||||
|
||||
# out
|
||||
5 ->
|
||||
val = Integer.mod(getComboOperandValue(operand, registers), 8)
|
||||
%{state | pointer: pointer + 2, output: [val | output]}
|
||||
|
||||
# bdv
|
||||
6 ->
|
||||
num = registers[:A]
|
||||
den = Integer.pow(2, getComboOperandValue(operand, registers))
|
||||
new_regs = %{registers | B: trunc(num / den)}
|
||||
|
||||
%{state | registers: new_regs, pointer: pointer + 2}
|
||||
|
||||
# cdv
|
||||
7 ->
|
||||
num = registers[:A]
|
||||
den = Integer.pow(2, getComboOperandValue(operand, registers))
|
||||
new_regs = %{registers | C: trunc(num / den)}
|
||||
|
||||
%{state | registers: new_regs, pointer: pointer + 2}
|
||||
end
|
||||
|
||||
run(new_state)
|
||||
end
|
||||
end
|
||||
|
||||
defp parseProgram(line) do
|
||||
[_header, digits] = String.split(line, " ")
|
||||
digits |> String.split(",") |> Enum.map(&String.to_integer/1)
|
||||
end
|
||||
|
||||
defp getComboOperandValue(op, registers) do
|
||||
case op do
|
||||
o when o <= 3 -> op
|
||||
4 -> registers[:A]
|
||||
5 -> registers[:B]
|
||||
6 -> registers[:C]
|
||||
end
|
||||
end
|
||||
|
||||
defp parseRegisters(lines) do
|
||||
lines
|
||||
|> String.split("\n")
|
||||
|> Enum.map(&String.split(&1, " "))
|
||||
|> Enum.reduce(%{}, fn [_header, label, value], acc ->
|
||||
atom = String.trim(label, ":") |> String.to_atom()
|
||||
Map.put(acc, atom, String.to_integer(value))
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
Day17.run()
|
Loading…
Reference in New Issue