Checking in Day 17 even though I haven't figured out part 2 yet. I\'m coming back to it

master
Dustin Swan 4 days ago
parent 791d6d9c69
commit cadb944182
Signed by: dustinswan
GPG Key ID: AB49BD6B2B3A6377

@ -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…
Cancel
Save