From cadb944182439e478e87bc49a05aa3968c8fe851 Mon Sep 17 00:00:00 2001 From: Dustin Swan Date: Sun, 29 Dec 2024 17:51:09 -0700 Subject: [PATCH] Checking in Day 17 even though I haven't figured out part 2 yet. I\'m coming back to it --- day17/main.exs | 180 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 day17/main.exs diff --git a/day17/main.exs b/day17/main.exs new file mode 100644 index 0000000..07c9bc4 --- /dev/null +++ b/day17/main.exs @@ -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()