]> fbox.kageds.com Git - adventofcode.git/blob - 2021/day18/day18.erl
day02
[adventofcode.git] / 2021 / day18 / day18.erl
1 -module(day18).
2
3 -export ([solve/0, solve/1]).
4 -compile ([export_all]).
5
6 solve() ->
7 solve(['1']),
8 solve(['2']),
9 init:stop().
10
11 solve(['1']) ->
12 io:format("The solution to ~p puzzle1 is: ~p~n", [?MODULE, solve(1)]);
13 solve(1) ->
14 solution1();
15 solve(['2']) ->
16 io:format("The solution to ~p puzzle2 is: ~p~n", [?MODULE, solve(2)]);
17 solve(2) ->
18 solution2().
19
20 solution1() ->
21 {ok, IO} = file:open("input.txt", 'read'),
22 Ans = maybe_reduce(read_line(IO), IO),
23 file:close(IO),
24 magnitude(Ans).
25
26 solution2() ->
27 {ok, IO} = file:open("input.txt", 'read'),
28 Numbers = read_all_lines(read_line(IO), IO, []),
29 file:close(IO),
30 io:format("total:~p lines: ~p~n", [length(Numbers), Numbers]),
31 max_magnitude(Numbers).
32
33 read_all_lines('eof', _IO, Acc) ->
34 Acc;
35 read_all_lines(Line, IO, Acc) ->
36 read_all_lines(read_line(IO), IO, [Line|Acc]).
37
38 read_line(IO) ->
39 case file:read_line(IO) of
40 {ok, Line} ->
41 {ok, Tokens, _} = erl_scan:string(Line ++ "."),
42 {ok, Term} = erl_parse:parse_term(Tokens),
43 Term;
44 'eof' -> 'eof'
45 end.
46
47 max_magnitude(Numbers) when is_list(Numbers) ->
48 lists:max([ max_magnitude(lists:split(I, Numbers)) || I <- lists:seq(1, length(Numbers))]);
49 max_magnitude({List1, List2}) ->
50 [H|T] = lists:reverse(List1),
51 max_magnitude(H, T ++ List2).
52
53 max_magnitude(Number, Rest) ->
54 lists:foldl(fun(N, MaxMag) ->
55 case magnitude(reduce([Number, N])) of
56 Mag when Mag > MaxMag -> Mag;
57 _ -> MaxMag
58 end
59 end, 0, Rest).
60
61
62 magnitude(A) when is_integer(A) -> A;
63 magnitude([A,B]) ->
64 (3 * magnitude(A)) + (2 * magnitude(B)).
65
66 maybe_reduce(A, IO) ->
67 case read_line(IO) of
68 'eof' -> A;
69 B ->
70 maybe_reduce(reduce([A,B]), IO)
71 end.
72
73 reduce(N) ->
74 case maybe_explode(N, 0) of
75 {true, New, _, _} ->
76 reduce(New);
77 false ->
78 case maybe_split(N) of
79 {true, New} ->
80 reduce(New);
81 false ->
82 N
83 end
84 end.
85
86 maybe_explode([A,B], Depth) when Depth >= 4, is_integer(A), is_integer(B) ->
87 {true, 0, A, B};
88 maybe_explode([A,B], Depth) ->
89 case maybe_explode(A, Depth+1) of
90 {true, New, AddA, AddB} ->
91 {true, [New, add_explode({b, AddB}, B)], AddA, 0};
92 false ->
93 case maybe_explode(B, Depth+1) of
94 {true, New, AddA, AddB} ->
95 {true, [add_explode({a, AddA}, A), New], 0, AddB};
96 false ->
97 false
98 end
99 end;
100 maybe_explode(N, _) when is_integer(N) ->
101 false.
102
103 add_explode({_, Add}, Num) when is_integer(Num) ->
104 Add + Num;
105 add_explode({b, Add}, [A,B]) ->
106 [add_explode({b, Add}, A), B];
107 add_explode({a, Add}, [A,B]) ->
108 [A, add_explode({a,Add}, B)].
109
110 maybe_split(N) when is_integer(N) ->
111 case N > 9 of
112 true ->
113 Left = N div 2,
114 Right = case Left*2 == N of true -> Left; false -> Left+1 end,
115 {true, [Left, Right]};
116 false ->
117 false
118 end;
119 maybe_split([A, B]) ->
120 case maybe_split(A) of
121 {true, NewA} ->
122 {true, [NewA, B]};
123 false ->
124 case maybe_split(B) of
125 {true, NewB} ->
126 {true, [A, NewB]};
127 false ->
128 false
129 end
130 end.