this repo has no description
1<!-- livebook:{"persist_outputs":true} -->
2
3# Day 19
4
5```elixir
6Mix.install([
7 {:kino_aoc, git: "https://github.com/ljgago/kino_aoc"}
8])
9```
10
11<!-- livebook:{"output":true} -->
12
13```
14:ok
15```
16
17## Section
18
19<!-- livebook:{"attrs":{"day":"19","session_secret":"ADVENT_OF_CODE_SESSION","variable":"puzzle_input","year":"2022"},"kind":"Elixir.KinoAOC.HelperCell","livebook_object":"smart_cell"} -->
20
21```elixir
22{:ok, puzzle_input} =
23 KinoAOC.download_puzzle("2022", "19", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
24```
25
26<!-- livebook:{"output":true} -->
27
28```
29{:ok,
30 "Blueprint 1: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 2 ore and 8 obsidian.\nBlueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 3 ore and 10 obsidian.\nBlueprint 3: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 14 obsidian.\nBlueprint 4: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 15 obsidian.\nBlueprint 5: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 3 ore and 15 obsidian.\nBlueprint 6: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 2 ore and 7 obsidian.\nBlueprint 7: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 9 clay. Each geode robot costs 3 ore and 7 obsidian.\nBlueprint 8: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 8 obsidian.\nBlueprint 9: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 4 ore and 18 obsidian.\nBlueprint 10: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 2 ore and 19 obsidian.\nBlueprint 11: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 3 ore and 10 obsidian.\nBlueprint 12: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 11 clay. Each geode robot costs 2 ore and 16 obsidian.\nBlueprint 13: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 16 clay. Each geode robot costs 3 ore and 15 obsidian.\nBlueprint 14: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 13 obsidian.\nBlueprint 15: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 2 ore and 20 obsidian.\nBlueprint 16: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 4 ore and 10 obsidian.\nBlueprint 17: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 16 obsidian.\nBlueprint 18: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 2 ore and 17 obsidian.\nBlueprint 19: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 4 ore and 12 obsidian.\nBlueprint 20: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 16 clay. Each geode robot costs 3 ore and 20 obsidian.\nBlueprint 21: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 12 obsidian.\nBlueprint 22: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 3 ore and 19 obsidian.\nBlueprint 23: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 8 obsidian.\nBlueprint 24: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 2 ore and 9 obsidian.\nBlueprint 25: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 15 obsidian.\nBlueprint 26: Each ore robot costs 4 ore. Each clay robot costs " <> ...}
31```
32
33```elixir
34puzzle_input = """
35Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.
36Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.
37"""
38```
39
40<!-- livebook:{"output":true} -->
41
42```
43"Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.\nBlueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.\n"
44```
45
46```elixir
47regex =
48 ~r/ore robot.*(?<ore_ore>\d+) ore.*clay robot.*(?<clay_ore>\d+) ore.*obsidian robot.*(?<obsidian_ore>\d+) ore and (?<obsidian_clay>\d+) clay.*geode robot.*(?<geode_ore>\d+) ore and (?<geode_obsidian>\d+) obsidian/
49
50plans =
51 puzzle_input
52 |> String.split("\n", trim: true)
53 |> Kino.render()
54 |> Enum.map(fn line ->
55 blueprint =
56 Regex.named_captures(regex, line)
57 |> Map.new(fn {k, v} ->
58 {String.to_atom(k), String.to_integer(v)}
59 end)
60
61 %{
62 ore: %{ore: blueprint.ore_ore},
63 clay: %{ore: blueprint.clay_ore},
64 obsidian: %{ore: blueprint.obsidian_ore, clay: blueprint.obsidian_clay},
65 geode: %{ore: blueprint.geode_ore, obsidian: blueprint.geode_obsidian},
66 max: %{
67 ore:
68 Enum.max([
69 blueprint.ore_ore,
70 blueprint.clay_ore,
71 blueprint.obsidian_ore,
72 blueprint.geode_ore
73 ]),
74 clay: blueprint.obsidian_clay,
75 obsidian: blueprint.geode_obsidian
76 }
77 }
78 end)
79```
80
81<!-- livebook:{"output":true} -->
82
83```
84["Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.",
85 "Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian."]
86```
87
88<!-- livebook:{"output":true} -->
89
90```
91[
92 %{
93 clay: %{ore: 2},
94 geode: %{obsidian: 7, ore: 2},
95 max: %{clay: 14, obsidian: 7, ore: 4},
96 obsidian: %{clay: 14, ore: 3},
97 ore: %{ore: 4}
98 },
99 %{
100 clay: %{ore: 3},
101 geode: %{obsidian: 12, ore: 3},
102 max: %{clay: 8, obsidian: 12, ore: 3},
103 obsidian: %{clay: 8, ore: 3},
104 ore: %{ore: 2}
105 }
106]
107```
108
109```elixir
110defmodule Blueprint do
111 def produce(plan, time, machines) do
112 produce(plan, time, machines, %{ore: 0, clay: 0, obsidian: 0, geode: 0})
113 end
114
115 def produce(_plan, 0, machines, stash) do
116 %{machines: machines, stash: stash}
117 end
118
119 def produce(plan, time_left, machines, stash) do
120 do_shopping(plan, stash)
121 |> Enum.filter(fn {k, _} -> (machines[k] || 0) < plan.max[k] end)
122 |> Enum.flat_map(fn {machine, new_stash} ->
123 # if machine in [:obsidian, :geode], do: IO.inspect(new_stash)
124 [
125 produce(
126 plan,
127 time_left - 1,
128 add_machine(machine, machines),
129 update_stash(machines, new_stash)
130 )
131 ]
132 end)
133 # |> tap(fn list ->
134 # Enum.filter(list, & &1.obsidian > 0)
135 # |> Enum.map(&IO.inspect/1)
136 # end)
137 |> Enum.max_by(& &1.stash.geode)
138 end
139
140 defp add_machine(nil, machines), do: machines
141 defp add_machine(name, machines), do: Map.update(machines, name, 1, &(&1 + 1))
142
143 defp update_stash(machines, stash) do
144 Enum.reduce(machines, stash, fn {k, v}, acc ->
145 Map.update(acc, k, v, &(&1 + v))
146 end)
147 end
148
149 def do_shopping(plan, stash)
150 when stash.ore >= plan.geode.ore and stash.obsidian >= plan.geode.obsidian,
151 do: [{:geode, buy(plan.geode, stash)}]
152
153 def do_shopping(plan, stash)
154 when stash.ore >= plan.obsidian.ore and stash.clay >= plan.obsidian.clay,
155 do: [{:obsidian, buy(plan.obsidian, stash)}, {nil, stash}]
156
157 def do_shopping(plan, stash) do
158 [
159 {nil, stash}
160 | Enum.flat_map([:ore, :clay], fn k ->
161 if stash.ore >= plan[k].ore do
162 [{k, %{stash | ore: stash.ore - plan[k].ore}}]
163 else
164 []
165 end
166 end)
167 ]
168 end
169
170 defp buy(price, stash) do
171 Map.merge(stash, price, fn _k, v1, v2 -> v1 - v2 end)
172 end
173end
174```
175
176<!-- livebook:{"output":true} -->
177
178```
179{:module, Blueprint, <<70, 79, 82, 49, 0, 0, 22, ...>>, {:buy, 2}}
180```
181
182```elixir
183plan = hd(plans) |> Kino.inspect()
184stash = %{clay: 35, geode: 0, obsidian: 0, ore: 4}
185
186Blueprint.do_shopping(plan, stash)
187```
188
189<!-- livebook:{"output":true} -->
190
191```
192%{
193 clay: %{ore: 2},
194 geode: %{obsidian: 7, ore: 2},
195 max: %{clay: 14, obsidian: 7, ore: 4},
196 obsidian: %{clay: 14, ore: 3},
197 ore: %{ore: 4}
198}
199```
200
201<!-- livebook:{"output":true} -->
202
203```
204[
205 obsidian: %{clay: 21, geode: 0, obsidian: 0, ore: 1},
206 nil: %{clay: 35, geode: 0, obsidian: 0, ore: 4}
207]
208```
209
210```elixir
211plans
212# |> Enum.drop(1)
213|> Enum.take(1)
214|> Kino.inspect()
215|> Enum.map(fn plan -> Blueprint.produce(plan, 24, %{ore: 1}) end)
216```
217
218<!-- livebook:{"output":true} -->
219
220```
221[
222 %{
223 clay: %{ore: 2},
224 geode: %{obsidian: 7, ore: 2},
225 max: %{clay: 14, obsidian: 7, ore: 4},
226 obsidian: %{clay: 14, ore: 3},
227 ore: %{ore: 4}
228 }
229]
230```