# Advent of Code 2024 - Day 1

**URL:** <https://erlangforums.com/t/advent-of-code-2024-day-1/4231>\
**Category:** Coding Challenges\
**Tags:** advent-of-code\
**Created:** [December 1, 2024, 1:05am UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231 "2024-12-01T01:05:30Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![vkatsuba](https://erlangforums.com/user_avatar/erlangforums.com/vkatsuba/32/314_2.png) [@vkatsuba](https://erlangforums.com/u/vkatsuba)\
**Post date:** [December 1, 2024, 1:05am UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/1 "2024-12-01T01:05:30Z")

</div>

Hi folks! **Ukrainian Erlanger** is here 🤘! The wait is almost over! **[Advent of Code 2024](https://adventofcode.com/2024)** is just around the corner, and **Day 1** will unlock in a matter of hours. It’s time to sharpen your tools, warm up your Erlang shells, and prepare for another year of coding challenges!

No hints, no spoilers - just anticipation and the promise of puzzles that will test our problem-solving skills and showcase Erlang’s elegance.

💡 **Pro Tips Before the Countdown Ends:**  
• Set up your environment - whether it’s your favorite editor or the trusty Erlang shell.  
• Have a hot drink and snacks ready; debugging is better with a warm cup by your side! ☕  
• Remember: simplicity and recursion are your best friends.

✨ **Motivation:**  
The hardest part of any journey is the first step. Let’s make that step in Erlang - one function, one match, one challenge at a time.

Check back here when **Day 1** goes live to share your first impressions and start the conversation. Let’s solve this together, Erlangers!

Happy coding, and see you at the starting line! 🎅

---

<div class="post-metadata">

**Author:** ![vkatsuba](https://erlangforums.com/user_avatar/erlangforums.com/vkatsuba/32/314_2.png) [@vkatsuba](https://erlangforums.com/u/vkatsuba)\
**Post date:** [December 1, 2024, 11:26am UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/2 "2024-12-01T11:26:22Z")

</div>

🎄 **Advent of Code 2024 - Day 1: My Solution** 🎄

Hey everyone! 👋

**[Day 1](https://adventofcode.com/2024/day/1)** is finally here, and I just finished working on my solution in Erlang. 🚀 It was a fun challenge involving parsing input data and transforming it into usable structures. I focused on splitting the input into two separate lists, one for each column, with all items converted to integers.

It’s always satisfying to see Erlang’s pattern matching and list comprehensions shine in tasks like this. 💡

How’s everyone else doing? Share your approaches, tips, or even struggles - let’s learn from each other and make this **[Advent of Code](https://adventofcode.com/2024/)** journey memorable! 🎅

Happy coding, and let’s Beam together! ✨

```erlang
-module(day_1).

-export([task_1/0, task_2/0]).

task_1() ->
    File = "input",
    {ok, RawData} = file:read_file(File),
    Raw = binary:split(RawData, <<"\n">>, [global, trim]),
    Data = [[binary_to_integer(X) || X <- binary:split(R, <<" ">>, [global, trim]), X /= <<>>] || R <- Raw],
    sum(prepare(Data, [], []), 0).

prepare([], Left, Right) ->
    [lists:sort(Left), lists:sort(Right)];
prepare([[L, R] | Rest], Left, Right) ->
    prepare(Rest, [L | Left], [R | Right]).

sum([[], []], Sum) ->
    Sum;
sum([[L | T1], [R | T2]], Sum) when L >= R ->
    sum([T1, T2], (Sum + (L - R)));
sum([[L | T1], [R | T2]], Sum) when R >= L ->
    sum([T1, T2], (Sum + (R - L))).

task_2() ->
    File = "input2",
    {ok, RawData} = file:read_file(File),
    Raw = binary:split(RawData, <<"\n">>, [global, trim]),
    Data = [[binary_to_integer(X) || X <- binary:split(R, <<" ">>, [global, trim]), X /= <<>>] || R <- Raw],
    sum2(prepare2(Data, [], []), 0).

prepare2([], Left, Right) ->
    [Left, Right];
prepare2([[L, R] | Rest], Left, Right) ->
    prepare2(Rest, [L | Left], [R | Right]).

sum2([[], _], Sum) ->
    Sum;
sum2([[L | Rest], Right], Sum) ->
    sum2([Rest, Right], Sum + (L * erlang:length([L || R <- Right, R == L]))).

```

---

<div class="post-metadata">

**Author:** ![danilagamma](https://erlangforums.com/user_avatar/erlangforums.com/danilagamma/32/342_2.png) [@danilagamma](https://erlangforums.com/u/danilagamma)\
**Post date:** [December 1, 2024, 11:46am UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/3 "2024-12-01T11:46:19Z")

</div>

Thank you @vkatsuba for creating AoC threads again this year 🙂

Here’s my Day 1 solution:

```erlang
-module(day1).

-compile(export_all).

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

solve1(Data) ->
    {A, B} = lists:unzip(Data),
    lists:sum([abs(L - R) || {L, R} <- lists:zip(lists:sort(A), lists:sort(B))]).

solve2(Data) ->
    {A, B} = lists:unzip(Data),
    Counts = lists:foldl(fun(N, Acc) -> maps:update_with(N, fun(V) -> V + 1 end, 1, Acc) end, #{}, B),
    lists:foldl(fun(N, Acc) -> N * maps:get(N, Counts, 0) + Acc end, 0, A).

```

---

<div class="post-metadata">

**Author:** ![vkatsuba](https://erlangforums.com/user_avatar/erlangforums.com/vkatsuba/32/314_2.png) [@vkatsuba](https://erlangforums.com/u/vkatsuba)\
**Post date:** [December 1, 2024, 11:53am UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/4 "2024-12-01T11:53:24Z")

</div>

You’re welcome! 🎄 Great to see your solution for Day 1 - awesome work! 💻 Looking forward to seeing more creative approaches from everyone this year. Let’s keep the AoC spirit alive! 🚀

---

<div class="post-metadata">

**Author:** ![bjorng](https://erlangforums.com/user_avatar/erlangforums.com/bjorng/32/174_2.png) [@bjorng](https://erlangforums.com/u/bjorng)\
**Post date:** [December 1, 2024, 1:02pm UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/5 "2024-12-01T13:02:54Z")

</div>

Here is my solution:

```erlang
#!/usr/bin/env escript

main(_) ->
    Input = get_input(),
    io:format("Part 1: ~p\n", [part1(Input)]),
    io:format("Part 2: ~p\n", [part2(Input)]).

part1(Input0) ->
    {L1,L2} = lists:unzip(Input0),
    lists:sum(lists:zipwith(fun(A, B) ->
                                    abs(A - B)
                            end,
                            lists:sort(L1),
                            lists:sort(L2))).
    %% In OTP 28 the preceding expression can be replaced with:
    %% lists:sum([abs(A - B) ||
    %% A <- lists:sort(L1) && B <- lists:sort(L2)]).

part2(Input0) ->
    {L1,L2} = lists:unzip(Input0),
    Gs = maps:groups_from_list(fun(I) -> I end, L2),
    lists:sum([A * length(maps:get(A, Gs, [])) || A <- L1]).

get_input() ->
    {ok,Input} = file:read_file("input.txt"),
    Lines = binary:split(Input, ~"\n", [global,trim]),
    [begin
         [A,B] = binary:split(Line, ~" ", [global,trim_all]),
         {binary_to_integer(A),
          binary_to_integer(B)}
     end || Line <- Lines].

```

I also have a solution [in Elixir](https://elixirforum.com/t/advent-of-code-2024-day-1/67786?u=bjorng).

---

<div class="post-metadata">

**Author:** ![vkatsuba](https://erlangforums.com/user_avatar/erlangforums.com/vkatsuba/32/314_2.png) [@vkatsuba](https://erlangforums.com/u/vkatsuba)\
**Post date:** [December 1, 2024, 1:30pm UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/6 "2024-12-01T13:30:07Z")

</div>

Your solution looks fantastic! I love seeing the different ways we can approach these challenges in Erlang. Great work on Day 1 - excited to see what you come up with next! 🎄🚀

---

<div class="post-metadata">

**Author:** ![danilagamma](https://erlangforums.com/user_avatar/erlangforums.com/danilagamma/32/342_2.png) [@danilagamma](https://erlangforums.com/u/danilagamma)\
**Post date:** [December 1, 2024, 2:14pm UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/7 "2024-12-01T14:14:52Z")

</div>

I’ve implemented and seen many implementations of `Enum.frequencies` in production code, do you think it’s a good idea to add something similar to OTP `maps` or `lists` module?

---

<div class="post-metadata">

**Author:** ![bjorng](https://erlangforums.com/user_avatar/erlangforums.com/bjorng/32/174_2.png) [@bjorng](https://erlangforums.com/u/bjorng)\
**Post date:** [December 2, 2024, 6:27am UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/8 "2024-12-02T06:27:30Z")

</div>

Yes, I think that an implementation of `Enum.frequencies` could be a useful addition to the `maps` module.

---

<div class="post-metadata">

**Author:** ![phild](https://erlangforums.com/user_avatar/erlangforums.com/phild/32/742_2.png) [@phild](https://erlangforums.com/u/phild)\
**Post date:** [December 3, 2024, 8:57pm UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/9 "2024-12-03T20:57:06Z")

</div>

Late to the party, as usual.

day01.erl:

```erlang
-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:

```erlang
-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))].

```

---

<div class="post-metadata">

**Author:** ![vkatsuba](https://erlangforums.com/user_avatar/erlangforums.com/vkatsuba/32/314_2.png) [@vkatsuba](https://erlangforums.com/u/vkatsuba)\
**Post date:** [December 3, 2024, 9:08pm UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/10 "2024-12-03T21:08:22Z")

</div>

Better late than never! 🚀 I really like your approach - using **transpose\_input** to structure the data cleanly and leveraging **lists:zip** for pairwise operations makes the solution both readable and efficient. Great use of **EUnit** for testing as well - those assertions ensure everything is solid. Nice work! 🎄💻

---

<div class="post-metadata">

**Author:** ![phild](https://erlangforums.com/user_avatar/erlangforums.com/phild/32/742_2.png) [@phild](https://erlangforums.com/u/phild)\
**Post date:** [December 3, 2024, 9:10pm UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/11 "2024-12-03T21:10:36Z")

</div>

I spent a _lot_ more time on prettifying than on solving 😉

---

<div class="post-metadata">

**Author:** ![vkatsuba](https://erlangforums.com/user_avatar/erlangforums.com/vkatsuba/32/314_2.png) [@vkatsuba](https://erlangforums.com/u/vkatsuba)\
**Post date:** [December 3, 2024, 9:20pm UTC](https://erlangforums.com/t/advent-of-code-2024-day-1/4231/12 "2024-12-03T21:20:48Z")

</div>

Sometimes prettifying takes as much creativity as solving! 😉 A clean and elegant solution is always satisfying.
