This topic is about Day 3 of the Advent of Code 2021.
We have a private leaderboard (shared with users of the elixir forum):
https://adventofcode.com/2021/leaderboard/private/view/370884
The entry code is:
370884-a6a71927
This topic is about Day 3 of the Advent of Code 2021.
We have a private leaderboard (shared with users of the elixir forum):
https://adventofcode.com/2021/leaderboard/private/view/370884
The entry code is:
370884-a6a71927
After cleaning up code a bit I came up with solution like that :
main(File) ->
{ok, RawData} = file:read_file(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 ]).
Day 3 in Sesterl: adventofcode/main.sest at master · michallepicki/adventofcode · GitHub
'Twas a step up today I felt. Maybe because my knowledge of the Erlang binary functions is [even] rustier than my general Erlang knowledge.
Wow never heard of Sesterl before – the syntax looks awesome.
My code is ugly but it produces the desired result.
@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
Dropping the puzzle at 6 in the morning sucks
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
So maybe advent of code is a kind of bad influence? It somehow forces us to write bad code?
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.
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:
@adolfont, my code assumes only 1 bitline would “win” in:
bits_filter(_, _, [Bits]) ->
...
changing it to:
bits_filter(_, _, [Bits|_]) ->
...
makes it work
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
.
Thanks. Then I learned something about Advent of Code: the solution requires a specific type of input.