this repo has no description
1<!-- livebook:{"persist_outputs":true} -->
2
3# Day 17
4
5```elixir
6Mix.install([:kino_aoc])
7```
8
9## Section
10
11<!-- livebook:{"attrs":"eyJhc3NpZ25fdG8iOiJwdXp6bGVfaW5wdXQiLCJkYXkiOiIxNyIsInNlc3Npb25fc2VjcmV0IjoiQURWRU5UX09GX0NPREVfU0VTU0lPTiIsInllYXIiOiIyMDI0In0","chunks":null,"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
12
13```elixir
14{:ok, puzzle_input} =
15 KinoAOC.download_puzzle("2024", "17", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
16```
17
18<!-- livebook:{"output":true} -->
19
20```
21{:ok,
22 "Register A: 66245665\nRegister B: 0\nRegister C: 0\n\nProgram: 2,4,1,7,7,5,1,7,4,6,0,3,5,5,3,0"}
23```
24
25```elixir
26defmodule Computer do
27 @instructions ~w[adv bxl bst jnz bxc out bdv cdv]a
28 |> Enum.with_index()
29 |> Map.new(fn {name, ins} -> {ins, name} end)
30
31 def load(opcodes) do
32 opcodes
33 |> Enum.chunk_every(2)
34 |> Enum.map(fn [opcode, op] ->
35 {@instructions[opcode], op}
36 end)
37 |> List.to_tuple()
38 end
39
40 def process(program, reg) do
41 reg = Map.merge(%{a: 0, b: 0, c: 0}, Map.new(reg))
42 do_process(program, 0, reg, [])
43 end
44
45 defp do_process(program, idx, _reg, out) when idx >= tuple_size(program) do
46 Enum.reverse(out)
47 end
48
49 defp do_process(program, idx, reg, out) do
50 ins = elem(program, idx)
51
52 case compute(ins, reg) do
53 new_reg when is_map(new_reg) ->
54 do_process(program, idx + 1, new_reg, out)
55
56 {:out, op} ->
57 do_process(program, idx + 1, reg, [op | out])
58
59 {:jump, op} ->
60 do_process(program, op, reg, out)
61 end
62 end
63
64 def compute({:adv, op}, reg),
65 do: %{reg | a: div(reg.a, 2 ** combo(op, reg))}
66
67 def compute({:bdv, op}, reg),
68 do: %{reg | b: div(reg.a, 2 ** combo(op, reg))}
69
70 def compute({:cdv, op}, reg),
71 do: %{reg | c: div(reg.a, 2 ** combo(op, reg))}
72
73 def compute({:bxl, op}, reg),
74 do: %{reg | b: Bitwise.bxor(reg.b, op)}
75
76 def compute({:bxc, _op}, reg),
77 do: %{reg | b: Bitwise.bxor(reg.b, reg.c)}
78
79 def compute({:bst, op}, reg),
80 do: %{reg | b: Bitwise.band(combo(op, reg), 0b111)}
81
82 def compute({:out, op}, reg),
83 do: {:out, Bitwise.band(combo(op, reg), 0b111)}
84
85 def compute({:jnz, op}, reg) do
86 if reg.a != 0 do
87 {:jump, op}
88 else
89 reg
90 end
91 end
92
93 defp combo(v, _) when v in 0..3, do: v
94 defp combo(4, %{a: a}), do: a
95 defp combo(5, %{b: b}), do: b
96 defp combo(6, %{c: c}), do: c
97end
98```
99
100<!-- livebook:{"output":true} -->
101
102```
103{:module, Computer, <<70, 79, 82, 49, 0, 0, 21, ...>>, {:combo, 2}}
104```
105
106```elixir
107[
108 "Register A: " <> a,
109 "Register B: " <> b,
110 "Register C: " <> c,
111 "Program: " <> raw_code
112] = String.split(puzzle_input, "\n", trim: true)
113
114reg = %{
115 a: String.to_integer(a),
116 b: String.to_integer(b),
117 c: String.to_integer(c)
118} |> dbg()
119
120code =
121 raw_code
122 |> String.split(",")
123 |> Enum.map(&String.to_integer/1)
124
125program = Computer.load(code)
126```
127
128<!-- livebook:{"output":true} -->
129
130```
131%{a: 66245665, b: 0, c: 0}
132```
133
134<!-- livebook:{"output":true} -->
135
136```
137{{:bst, 4}, {:bxl, 7}, {:cdv, 5}, {:bxl, 7}, {:bxc, 6}, {:adv, 3}, {:out, 5}, {:jnz, 0}}
138```
139
140## Part 1
141
142```elixir
143out = Computer.process(program, reg)
144```
145
146<!-- livebook:{"output":true} -->
147
148```
149[1, 4, 6, 1, 6, 4, 3, 0, 3]
150```
151
152```elixir
153IO.puts(Enum.join(out, ","))
154```
155
156<!-- livebook:{"output":true} -->
157
158```
1591,4,6,1,6,4,3,0,3
160```
161
162<!-- livebook:{"output":true} -->
163
164```
165:ok
166```
167
168## Part 2
169
170```elixir
171defmodule Quine do
172 def find(program, target) do
173 do_find(program, Enum.reverse(target), Enum.to_list(0..7))
174 end
175
176 def do_find(_program, [], out), do: out
177
178 def do_find(program, [n | rest], out) do
179 potential =
180 for a <- out,
181 i <- 0..7,
182 hd(Computer.process(program, a: a * 8 + i)) == n,
183 do: a * 8 + i
184
185 do_find(program, rest, potential)
186 end
187end
188```
189
190<!-- livebook:{"output":true} -->
191
192```
193{:module, Quine, <<70, 79, 82, 49, 0, 0, 10, ...>>, {:do_find, 3}}
194```
195
196```elixir
197Quine.find(program, code) |> Enum.min()
198```
199
200<!-- livebook:{"output":true} -->
201
202```
203265061364597659
204```
205
206<!-- livebook:{"offset":4021,"stamp":{"token":"XCP.PwUWTErrjClVJj6ZS87ZLrfbzleELwxqD__HBvfB1y_Yc633Wj72_Jigo2Z3T7V2ONi1nVguQ_AE_NSyLCF5sjSmWldUKuW294o_wsQqiM_gKhXOjSLzJOnslN9iIEFIEww","version":2}} -->