Advent of Code 2024 - Day 1

Late to the party, as usual.

day01.erl:

-module(day01).
-include_lib("eunit/include/eunit.hrl").

-export([p1/1, p2/1]).

p1(InputData) ->
    [As, Bs] = transpose_input(InputData),
    lists:sum([abs(A - B) || {A, B} <- lists:zip(lists:sort(As), lists:sort(Bs))]).

p2(InputData) ->
    [As, Bs] = transpose_input(InputData),
    lists:sum([A * length([B || B <- Bs, A =:= B]) || A <- As]).

transpose_input(InputData) ->
    util:transpose([util:str_to_ints(Row) || Row <- InputData]).

gen_test_() ->
    {setup, fun read_input/0, fun check_results/1}.

read_input() ->
    {
        util:read_input(?MODULE_STRING ++ "_test.txt"),
        util:read_input(?MODULE_STRING ++ "_input.txt")
    }.

check_results({TestData, InputData}) ->
    [
        ?_assertEqual(11, p1(TestData)),
        ?_assertEqual(31, p2(TestData)),
        ?_assertEqual(2192892, p1(InputData)),
        ?_assertEqual(22962826, p2(InputData))
    ].

util.erl:

-module(util).

-export([read_input/1, str_to_ints/1, transpose/1]).

-spec read_input(Name) -> Lines when
    Name :: string(),
    Lines :: [string()].

read_input(Name) ->
    File = filename:join([code:priv_dir(escratch), Name]),
    {ok, S} = file:open(File, [read]),
    read_lines(S, []).

read_lines(S, Lines) ->
    case file:read_line(S) of
        {ok, Line} ->
            read_lines(S, [string:trim(Line) | Lines]);
        eof ->
            file:close(S),
            lists:reverse(Lines)
    end.

-spec str_to_ints(S) -> Ints when
    S :: string(),
    Ints :: [integer()].

str_to_ints(S) ->
    [list_to_integer(X) || X <- string:tokens(S, " ")].

-spec transpose(Matrix1) -> Matrix2 when
    Matrix1 :: [nonempty_list()],
    Matrix2 :: [nonempty_list()].

transpose([[] | _]) -> [];
transpose(M) -> [lists:map(fun hd/1, M) | transpose(lists:map(fun tl/1, M))].
2 Likes