# Advent of Code 2021 - Day 3

This topic is about Day 3 of the Advent of Code 2021.

We have a private leaderboard (shared with users of the elixir forum):

The entry code is:
`370884-a6a71927`

5 Likes

After cleaning up code a bit I came up with solution like that :

``````main(File) ->
Data = [ binary_to_list(N) || N <- binary:split(RawData, <<"\n">>, [global, trim]) ],
io:format("part 1: ~p~n", [solve1(Data)]),
io:format("part 2: ~p~n", [solve2(Data)]),
ok.

solve1(Data) ->
Counts = lists:foldl(fun bit_count/2, lists:duplicate(length(hd(Data)), 0), Data),
bit_count_to_integer(fun most/1, Counts)
* bit_count_to_integer(fun least/1, Counts).

bit_count(Bits, Acc) ->
[ inc(Bit) + A || {Bit, A} <- lists:zip(Bits, Acc) ].

bit_count_to_integer(BitFun, Counts) ->
list_to_integer([ BitFun(X) || X <- Counts ], 2).

most(V)  when V >= 0 -> \$1;
most(_)              -> \$0.

least(V) when V >= 0 -> \$0;
least(_)             -> \$1.

inc(\$0) -> -1;
inc(\$1) ->  1.

solve2(Data) ->
bits_filter(fun most/1, Data)
* bits_filter(fun least/1, Data).

bits_filter(BitFun, BitsList) ->
bits_filter(1, BitFun, BitsList).

bits_filter(_, _, [Bits]) ->
list_to_integer(Bits, 2);
bits_filter(N, BitFun, Data) ->
V = BitFun(lists:sum([ inc(lists:nth(N, D)) || D <- Data ])),
bits_filter(N + 1, BitFun, [ D || D <- Data, lists:nth(N, D) =:= V ]).
``````
6 Likes
7 Likes

'Twas a step up today I felt. Maybe because my knowledge of the Erlang binary functions is [even] rustier than my general Erlang knowledge.

4 Likes

Wow never heard of Sesterl before â€“ the syntax looks awesome.

5 Likes

My code is ugly but it produces the desired result.

4 Likes

@danilagamma, Do you have any idea why your code works on the input provided by AoC, but when I run it with a shorter file (see below), part 2 goes into an infinite loop?

101000001100
011111100111
111100001110
110000011001
001001001011
010011101000
011001110011
010100010000
101110110111

3 Likes

# Solving Advent of Code 2021 in Erlang - Day 3 - Binary Diagnostic

4 Likes

Dropping the puzzle at 6 in the morning sucks

5 Likes

Part 1:

``````part1() ->
Text = <<"00100\n11110\n10110\n10111\n10101\n01111\n00111\n11100\n10000\n11001\n00010\n01010\n">>,
[H|_] = Input = [X || X <- re:split(Text, "\n"), X /= <<>>],
part1(size(H), size(H), Input, {<<>>, <<>>}).

part1(_, 0, _, {Gamma, Epsilon}) ->
binary_to_integer(Gamma, 2) * binary_to_integer(Epsilon, 2);
part1(Size, Index, Inputs, {Gamma, Epsilon}) ->
{Zero, One} = loop(Inputs, Size, Index, {<<>>, <<>>}),
part1(Size, Index - 1, Inputs, {bit(size(Zero) < size(One), Gamma), bit(size(Zero) > size(One), Epsilon)}).

loop([], _, _, Acc) -> Acc;
loop([H|T], Size, Index, {Zero, One}) ->
<<X, _/binary>> = binary:part(H, {Size, -Index}),
Acc = case X of
48 -> {<<X/integer, Zero/binary>>, One};
49 -> {Zero, <<X/integer, One/binary>>}
end,
loop(T, Size, Index, Acc).

bit(true, Acc) -> <<Acc/binary, 49/integer>>;
bit(false, Acc) -> <<Acc/binary, 48/integer>>.
``````

Part2:

``````part2() ->
Text = <<"00100\n11110\n10110\n10111\n10101\n01111\n00111\n11100\n10000\n11001\n00010\n01010\n">>,
[H|_] = Input = [X || X <- re:split(Text, "\n"), X /= <<>>],
O = oxygen(size(H), size(H), Input),
C = co2(size(H), size(H), Input),
binary_to_integer(O, 2) * binary_to_integer(C, 2).

oxygen(_, 0, [H]) -> H;
oxygen(_, _, [H]) -> H;
oxygen(Size, Index, Inputs) ->
{O, C} = loop2(Inputs, Size, Index, {[], []}),
case length(O) > length(C) of
true -> oxygen(Size, Index - 1, lists:reverse(O));
false ->
case length(O) == length(C) of
true -> oxygen(Size, Index - 1, lists:reverse(O));
false -> oxygen(Size, Index - 1, lists:reverse(C))
end
end.

co2(_, 0, [H]) -> H;
co2(_, _, [H]) -> H;
co2(Size, Index, Inputs) ->
{O, C} = loop2(Inputs, Size, Index, {[], []}),
case length(O) > length(C) of
true -> co2(Size, Index - 1, lists:reverse(C));
false ->
case length(O) == length(C) of
true -> co2(Size, Index - 1, lists:reverse(C));
false -> co2(Size, Index - 1, lists:reverse(O))
end
end.

loop2(_, _, 0, Acc) -> Acc;
loop2([], _, _, Acc) -> Acc;
loop2([H|T], Size, Index, {Oxygen, CO2}) ->
<<X, _/binary>> = binary:part(H, {Size, -Index}),
Acc = case X of
49 -> {[H | Oxygen], CO2};
48 -> {Oxygen, [H|CO2]}
end,
loop2(T, Size, Index, Acc).
``````

It is possible to implement more beautifully, but I did not have enough patience for this

5 Likes

So maybe advent of code is a kind of bad influence? It somehow forces us to write bad code?

5 Likes

I gotta admit this one was one hell of a challenge in Awk (which canâ€™t even return arrays from functions). Erlang would have been a much better time

Iâ€™m pretty sure Iâ€™ll ragequit this one faster than the Erlang ones by now.

6 Likes

Ahh but you can return strings, and you can encode and decode stuff into/from strings, can stringly type it all! ^.^

Iâ€™ve been doing mine in rust this year, posted over at the devtalk side of the forums along with others there if anyone is curious in more solutions in other languages:

3 Likes

@adolfont, my code assumes only 1 bitline would â€świnâ€ť in:

``````bits_filter(_, _, [Bits]) ->
...
``````

changing it to:

``````bits_filter(_, _, [Bits|_]) ->
...
``````

makes it work

4 Likes

After some experience, I can say that bad code does not exist in nature . The code either works or it doesnâ€™t. If it doesnâ€™t work, you need to make it work. If the code works but does not look nice, it should be optimized if possible. Another question is the willingness and patience to do it. In my case, I didnâ€™t have the patience .

4 Likes

Thanks. Then I learned something about Advent of Code: the solution requires a specific type of input.

3 Likes