]> fbox.kageds.com Git - adventofcode.git/blob - 2021/day16/day16.erl
20223 day1
[adventofcode.git] / 2021 / day16 / day16.erl
1 %% to compile: erlc day3A.erl
2 %% to run: erl -noshell -s day5 solve
3 %%
4 -module(day16).
5
6 -compile(export_all).
7
8 -export ([solve/0, solve/1, solve/2]).
9 -export ([read_input/0]).
10
11 solve() ->
12 solve(['1']),
13 solve(['2']),
14 init:stop().
15
16 solve(A) ->
17 solve(A, read_input()).
18
19 solve(['1'], D) ->
20 io:format("The solution to ~p puzzle1 is: ~p~n", [?MODULE, solve(1, D)]);
21 solve(1, D) ->
22 solution1(D);
23 solve(['2'], D) ->
24 io:format("The solution to ~p puzzle2 is: ~p~n", [?MODULE, solve(2, D)]);
25 solve(2, D) ->
26 solution2(D).
27
28 read_input() ->
29 {ok, IO} = file:open("input.txt", 'read'),
30 {ok, Line} = file:read_line(IO),
31 file:close(IO),
32 hexstr_to_bin(string:strip(Line, 'both', $\n)).
33
34 hexstr_to_bin(S) ->
35 hexstr_to_bin(S, []).
36 hexstr_to_bin([], Acc) ->
37 list_to_binary(lists:reverse(Acc));
38 hexstr_to_bin([X,Y|T], Acc) ->
39 {ok, [V], []} = io_lib:fread("~16u", [X,Y]),
40 hexstr_to_bin(T, [V | Acc]);
41 hexstr_to_bin([X|T], Acc) ->
42 {ok, [V], []} = io_lib:fread("~16u", lists:flatten([X,"0"])),
43 hexstr_to_bin(T, [V | Acc]).
44
45 bin_to_hexstr(Bin) ->
46 lists:flatten([io_lib:format("~2.16.0B", [X]) ||
47 X <- binary_to_list(Bin)]).
48
49 solution1(Input) ->
50 D = unpack(Input, [], not is_zero_bitstring(Input)),
51 io:format("Pkt: ~p~n", [D]),
52 count_versions(D, 0).
53
54 solution2(Input) ->
55 D = unpack(Input, [], not is_zero_bitstring(Input)),
56 io:format("Pkt: ~p~n", [D]),
57 calc(D).
58
59 calc({_,literal, V}) ->
60 V;
61 calc({_,Op, V}) ->
62 ?MODULE:Op(V);
63 calc([{_,Op, V}]) ->
64 ?MODULE:Op(V).
65
66 sum(Args) ->
67 io:format("sum: ~p~n", [Args]),
68 lists:foldl(fun(X, Acc) -> calc(X) + Acc end, 0, Args).
69
70 product(Args) ->
71 io:format("product: ~p~n", [Args]),
72 lists:foldl(fun(X, Acc) -> calc(X) * Acc end, 1, Args).
73
74 min(Args) ->
75 io:format("min: ~p~n", [Args]),
76 lists:min([calc(X) || X <- Args]).
77
78 max(Args) ->
79 io:format("max: ~p~n", [Args]),
80 lists:max([calc(X) || X <- Args]).
81
82 lt([A,B] = Args) ->
83 io:format("lt: ~p~n", [Args]),
84 case calc(A) < calc(B) of
85 'true' -> 1;
86 'false' -> 0
87 end.
88
89 gt([A,B] = Args) ->
90 io:format("gt: ~p~n", [Args]),
91 case calc(A) > calc(B) of
92 'true' -> 1;
93 'false' -> 0
94 end.
95
96 eq([A,B] = Args) ->
97 io:format("eq: ~p~n", [Args]),
98 case calc(A) == calc(B) of
99 'true' -> 1;
100 'false' -> 0
101 end.
102
103 count_versions([{Ver, Type, Rest}|T], Acc) ->
104 count_versions(T, count_versions(Rest, Acc) + Ver);
105 count_versions(_, Acc) ->
106 Acc.
107
108 is_zero_bitstring(BitString) ->
109 Size = erlang:bit_size(BitString),
110 <<0:Size>> =:= BitString.
111
112 unpack(Data, [], 'false') ->
113 Data;
114 unpack(Input, Acc, 'false') ->
115 Acc;
116
117 unpack(Input, Acc, 'true') ->
118 {{Ver, Type, Data}, Rest} = unpack(Input),
119 io:format("unpacking data: ~p~n", [Data]),
120 lists:reverse(unpack(Rest, Acc ++ [{Ver, Type, unpack(Data, [], is_bitstring(Data) andalso not is_zero_bitstring(Data))}], not is_zero_bitstring(Rest))).
121
122 %% Literal
123 unpack(<<V:3, 4:3, Rest/bitstring>>) ->
124 io:format("V:~p, T:literal~n", [V]),
125 unpack_literal(V, Rest);
126
127 %% Operator length type id 0
128 unpack(<<V:3, T:3, 0:1, Rest/bitstring>>) ->
129 io:format("V:~p, T:operator I:0~n", [V]),
130 unpack_operator_0(V, T, Rest);
131
132 %% Operator length type id 1
133 unpack(<<V:3, T:3, 1:1, Rest/bitstring>>) ->
134 io:format("V:~p, T:operator I:1~n", [V]),
135 unpack_operator_1(V, T, Rest).
136
137 unpack_literal(V, Pkt) ->
138 unpack_literal(V, Pkt, <<>>, 0).
139
140 unpack_literal(V, <<1:1, Value:4, Rest/bitstring>>, Acc, Count) ->
141 unpack_literal(V, Rest, <<Acc/bitstring, Value:4>>, Count + 1);
142 unpack_literal(V, <<0:1, Value:4, Rest/bitstring>>, Acc, Count) ->
143 L = <<Acc/bitstring, Value:4>>,
144 Size = (Count + 1) * 4,
145 io:format("unpack_literal value: ~p size:~p rest:~p~n", [Value, Size, Rest]),
146 <<X:(Size)>> = L,
147 {{V, literal, X}, Rest}.
148
149 unpack_operator_0(V, T, <<Length:15, Rest0/bitstring>>) ->
150 io:format("operator0 length:~p~n", [Length]),
151 <<Pkt:(Length)/bitstring, Rest/bitstring>> = Rest0,
152 {Rest1, Decoded} = unpack_len(Length, Rest0, []),
153 {{V, operator_type(T), Decoded}, Rest1}.
154
155 unpack_operator_1(V, T, <<Num:11, Rest/bitstring>>) ->
156 {Rest1, Decoded} = unpack_count(Num, Rest, []),
157 io:format("operator1 num of packets:~p Decoded:~p, Rest:~p~n", [Num,Decoded,Rest1]),
158 {{V, operator_type(T), Decoded}, Rest1}.
159
160 unpack_len(0, Pkt, Acc) ->
161 {Pkt, Acc};
162 unpack_len(Length, Pkt, Acc) ->
163 {L, R} = unpack(Pkt),
164 io:format("unpack_len: length:before ~p after: ~p~n", [Length, Length - bit_size(Pkt) + bit_size(R)]),
165 unpack_len(Length - bit_size(Pkt) + bit_size(R), R, Acc ++ [L]).
166
167 unpack_count(0, Pkt, Acc) ->
168 {Pkt, Acc};
169 unpack_count(Num, Pkt, Acc) ->
170 {L, R} = unpack(Pkt),
171 unpack_count(Num - 1, R, Acc ++ [L]).
172
173 operator_type(0) -> 'sum';
174 operator_type(1) -> 'product';
175 operator_type(2) -> 'min';
176 operator_type(3) -> 'max';
177 operator_type(5) -> 'gt';
178 operator_type(6) -> 'lt';
179 operator_type(7) -> 'eq'.