Advent of Code 2021 - Day 13

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

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

The entry code is:


Hope future puzzles won’t require us to parse ASCII text that we’re printing out :sweat_smile: :

main(File) ->
    {ok, RawData} = file:read_file(File),
    [RawDots, RawFold] = binary:split(RawData, <<"\n\n">>),
    Dots = lists:sort([ begin
                            [X, Y] = binary:split(Line, <<",">>),
                            {binary_to_integer(X), binary_to_integer(Y)}
                        end || Line <- binary:split(RawDots, <<"\n">>, [global, trim]) ]),
    Fold = [ begin
                 [Instruction, V] = binary:split(Line, <<"=">>, [global, trim]),
                 {Instruction, binary_to_integer(V)}
             end || Line <- binary:split(RawFold, <<"\n">>, [global, trim]) ],
    io:format("part 1: ~p~n", [solve1(Dots, Fold)]),
    io:format("part 2: ~p~n", [solve2(Dots, Fold)]).

solve1(Map, Fold) ->
    length(fold(hd(Fold), Map)).

solve2(Map, Fold) ->
    print(lists:foldl(fun fold/2, Map, Fold)).

fold(Instruction, Map) ->
    lists:usort([ fold_dot(Dot, Instruction) || Dot <- Map ]).

fold_dot({X, Y}, {<<"fold along y">>, V}) when Y > V -> {X, 2 * V - Y};
fold_dot({X, Y}, {<<"fold along x">>, V}) when X > V -> {2 * V - X, Y};
fold_dot({X, Y}, _)                                  -> {X, Y}.

print(Map) ->
    [ print(Map, Y) || Y <- lists:usort([ Y || {_, Y} <- Map ]) ],

print(Map, Y) ->
    Dots = [ X || {X, Y0} <- Map, Y0 =:= Y ],
    [ case lists:member(X, Dots) of
          true  -> io:format("#");
          false -> io:format(" ")
      end || X <- lists:seq(0, lists:max(Dots)) ],

I just output it directly and read it myself. I got my first real awful experience with Awk for Advent of Code today: advent-of-code-2021/day13.awk at main · ferd/advent-of-code-2021 · GitHub

I got confusing snippets where I’d compare the indices of a nested array and compare them with a parsed value. Somehow I kept having values like 7 is always greater than 1, 5, 14, 19, whatever, or 5 being greater than 38.

So I figured “wait, that might be a thing where I get strings instead of ints” so I just made sure to cast all values as int() when getting them in, but a later check found that even though I use ints for array indices, I’d get strings back.

And then I remembered something the friend who taught me awk years ago (old-timer Erlang user ttmrichter if you recall him) told me: Awk does not support arrays of arrays, it has normal arrays, and it then cheats with strings, by concatenating all fields and values and using a special SUBSEP string to fake arrays of arrays. This means that when you have arrays of arrays going a[x][y], even if you start with x and y being ints, you’re gonna get strings back in a for (x in a) { for (y in a[x]) { … } }. Usually this is fine, but when you don’t do any arithmetic involving an int with them and you just compare two strings, then you get string comparison and of course, “5” sorts higher than “38”.

So uh, there we are. I haven’t converted anything because I spent all my free AoC time on fighting loose typing.


Back after 2 days.
My ugly Erlang code: