Advent of Code 2022 Day 13 - Discussion

This topic is about Day 13 of the Advent of Code 2022 .

Sorry for delaying this post.

Link to our leaderboard:

https://adventofcode.com/2022/leaderboard/private/view/370884

The entry code is:
370884-a6a71927

Good luck!

1 Like

Neat challenge, also got into top 1000 today :smile: (721/618):

main(File) ->
    {ok, RawData} = file:read_file(File),
    Data = [ [ parse_term(T) || T <- binary:split(X, <<"\n">>) ]
             || X <- binary:split(RawData, <<"\n\n">>, [global, trim]) ],
    io:format("part 1: ~p~n", [solve1(Data)]),
    io:format("part 2: ~p~n", [solve2(Data)]).

parse_term(Binary) ->
    {ok, Tokens, _} = erl_scan:string(binary_to_list(<<Binary/binary, ".">>)),
    {ok, Term} = erl_parse:parse_term(Tokens),
    Term.

enum(List) ->
    lists:zip(lists:seq(1, length(List)), List).

solve1(Data) ->
    lists:sum([ N || {N, [A, B]} <- enum(Data), compare(A, B) ]).

solve2(Data) ->
    Dividers = [[[2]], [[6]]],
    Result   = enum(lists:sort(fun compare/2, Dividers ++ [ Y || X <- Data, Y <- X ])),
    [F1, F2] = [ N || {N, V} <- Result, lists:member(V, Dividers) ],
    F1 * F2.

compare([],     [_|_])                                             -> true;
compare([_|_],  [])                                                -> false;
compare([],     [])                                                -> ok;
compare([A|_ ], [B|_ ]) when is_integer(A), is_integer(B), A >   B -> false;
compare([A|_ ], [B|_ ]) when is_integer(A), is_integer(B), A <   B -> true;
compare([A|Ax], [B|Bx]) when is_integer(A), is_integer(B), A =:= B -> compare(Ax, Bx);
compare(A,      B)      when is_integer(A), is_list(B)             -> compare([A], B);
compare(A,      B)      when is_list(A),    is_integer(B)          -> compare(A, [B]);
compare([A|Ax], [B|Bx]) when is_list(A);    is_list(B) ->
    case compare(A, B) of
        ok    -> compare(Ax, Bx);
        Other -> Other
    end.
3 Likes

I did it the same way. Though in Elixir. But it took me awhile to understand the sorting mechanism here. Started questioning my reading skills.

2 Likes

I confess to stealing your term parsing code.

Not often I can offer an improvement, but in this case you can use lists:enumerate/1 in place of your enum/1 function. My belated part 1 solution was otherwise pretty similar. My compare/2 implementation was:

compare(L, L) ->
    continue;
compare(L, R) when is_integer(L) andalso is_integer(R) -> L < R;
compare([HL | TL], [HR | TR]) ->
    case compare(HL, HR) of
        continue -> compare(TL, TR);
        Result -> Result
    end;
compare(L, R) when is_list(L) andalso is_integer(R) -> compare(L, [R]);
compare(L, R) when is_integer(L) andalso is_list(R) -> compare([L], R);
compare(L, []) when is_list(L) -> false;
compare([], R) when is_list(R) -> true.
2 Likes

I copied my enum from my previous year solution since lists: enumerate didn’t exist back then :slight_smile:

2 Likes