this repo has no description
1<!-- vim:ft=markdown -->
2
3<!-- livebook:{"persist_outputs":true} -->
4
5# Day 21
6
7## Section
8
9```elixir
10input = File.read!("day21.txt")
11
12[[_, p1], [_, p2]] = Regex.scan(~r/: (\d)/, input)
13
14p1 = String.to_integer(p1)
15p2 = String.to_integer(p2)
16
17{p1, p2}
18```
19
20<!-- livebook:{"output":true} -->
21
22```
23{3, 5}
24```
25
26```elixir
27round =
28 Stream.unfold(0, &{&1, &1 + 1})
29 |> Stream.scan({{0, p1}, {0, p2}}, fn n, {{s, p}, other} ->
30 p = rem(p - 1 + 6 + n * 9, 10) + 1
31
32 {other, {s + p, p}}
33 end)
34 |> Enum.take_while(fn {{s, _}, {_, _}} -> s < 1000 end)
35
36{rounds, {{loser, _}, _}} = {length(round), List.last(round)}
37
38rounds * 3 * loser
39```
40
41<!-- livebook:{"output":true} -->
42
43```
44720750
45```
46
47```elixir
48defmodule Day21.Task2 do
49 def play(p1, p2) do
50 tid = :ets.new(__MODULE__, [])
51 {a, b} = cached_round({p1 - 1, 0}, {p2 - 1, 0}, tid)
52 :ets.delete(tid)
53 max(a, b)
54 end
55
56 defp cached_round(a, b, tid) do
57 case :ets.lookup(tid, {a, b}) do
58 [{_, v}] ->
59 v
60
61 [] ->
62 value = round(a, b, tid)
63
64 :ets.insert(tid, {{a, b}, value})
65
66 value
67 end
68 end
69
70 defp round({_, s}, _, _) when s >= 21, do: {1, 0}
71 defp round(_, {_, s}, _) when s >= 21, do: {0, 1}
72
73 defp round({pos, score}, p2, tid) do
74 for a <- 1..3, b <- 1..3, c <- 1..3, reduce: {0, 0} do
75 {wins1, wins2} ->
76 next = rem(pos + a + b + c, 10)
77
78 {nscore2, nscore1} =
79 cached_round(
80 p2,
81 {next, score + next + 1},
82 tid
83 )
84
85 {wins1 + nscore1, wins2 + nscore2}
86 end
87 end
88end
89```
90
91<!-- livebook:{"output":true} -->
92
93```
94{:module, Day21.Task2, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:round, 3}}
95```
96
97```elixir
98Day21.Task2.play(p1, p2)
99```
100
101<!-- livebook:{"output":true} -->
102
103```
104275067741811212
105```