# Advent of Code 2021 - Day 5

**URL:** <https://erlangforums.com/t/advent-of-code-2021-day-5/738>\
**Category:** Coding Challenges\
**Tags:** advent-of-code\
**Created:** [December 5, 2021, 4:59am UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738 "2021-12-05T04:59:18Z")\
**Posts on this page:** 12\
**Page:** 1

<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 5, 2021, 4:59am UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/1 "2021-12-05T04:59:18Z")

</div>

This topic is about Day 5 of the [Advent of Code 2021](https://adventofcode.com/2021).

We have a private leaderboard (shared with users of the [elixir forum](https://elixirforum.com)):

[https://adventofcode.com/2021/leaderboard/private/view/370884](https://adventofcode.com/2021/leaderboard/private/view/370884)

The entry code is:  
`370884-a6a71927`

---

<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 5, 2021, 5:44am UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/2 "2021-12-05T05:44:39Z")

</div>

This one feels easier than previous day 🙂 :

```erlang
main(File) ->
    {ok, RawData} = file:read_file(File),
    Data = [ begin 
                 [From, To] = binary:split(Line, <<" -> ">>),
                 [X1b, Y1b] = binary:split(From, <<",">>),
                 [X2b, Y2b] = binary:split(To, <<",">>),
                 {{binary_to_integer(X1b), binary_to_integer(Y1b)},
                  {binary_to_integer(X2b), binary_to_integer(Y2b)}}
             end || Line <- 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) ->
    count_overlap([ L || Coords <- Data, 
                              L <- to_straight_line(Coords) ]).

count_overlap(Lines) ->
    Map = lists:foldl(fun update_counter/2, #{}, Lines),
    length([X || X <- maps:values(Map), X >= 2]).

update_counter(Coord, Acc) ->
    Fun = fun(V) -> V + 1 end,
    maps:update_with(Coord, Fun, 1, Acc).

to_straight_line({{X1, Y1}, {X2, Y2}}) when X1 =:= X2 ->
    [{X1, Y} || Y <- from_to(Y1, Y2)];
to_straight_line({{X1, Y1}, {X2, Y2}}) when Y1 =:= Y2 ->
    [{X, Y1} || X <- from_to(X1, X2)];
to_straight_line(_) ->
    [].

from_to(A, B) ->
    case B > A of
        true -> lists:seq(A, B);
        false -> lists:seq(A, B, -1)
    end.

solve2(Data) ->
    count_overlap([ L || Coords <- Data, 
                              L <- to_straight_line(Coords) 
                                ++ to_diagonal_line(Coords) ]).

to_diagonal_line({{X1, Y1}, {X2, Y2}}) when abs(X1 - X2) =:= abs(Y1 - Y2) ->
    lists:zip(from_to(X1, X2), from_to(Y1, Y2));
to_diagonal_line(_) ->
    [].

```

Curious to see solution without keeping each individual dot in memory with counter

---

<div class="post-metadata">

**Author:** ![michallepicki](https://erlangforums.com/letter_avatar_proxy/v4/letter/m/5f9b8f/32.png) [@michallepicki](https://erlangforums.com/u/michallepicki)\
**Post date:** [December 5, 2021, 12:24pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/3 "2021-12-05T12:24:47Z")

</div>

Day 5 in Sesterl - [adventofcode/main.sest at master · michallepicki/adventofcode · GitHub](https://github.com/michallepicki/adventofcode/blob/master/2021/sesterl/5/src/main.sest)  
All those `if then else` are getting ugly, I should send a PR to add `&&` and `||` 😃

---

<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 5, 2021, 1:25pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/4 "2021-12-05T13:25:36Z")

</div>

> [@danilagamma](#):
>
> This one feels easier than previous day

Yes, or perhaps just well suited to Erlang. And unlike yesterday, it’s not a test of how efficiently you can write a file parser or manipulate text in your [favourite editor](https://erlangforums.com/t/which-code-editor-or-ide-do-you-use/463).

I feel happy enough with my code today to post it (although having seen it, I like @ danilagamma’s `from_to/2` better than my `dir/2` - though I’d implement it as clauses rather than a `case`):

```erlang
p1(InputData) ->
    count_points(fun points_p1/2, InputData).

p2(InputData) ->
    count_points(fun points_p2/2, InputData).

count_points(F, InputData) ->
    AllPoints = lists:foldl(
        fun(E, A) ->
            maps:put(E, maps:get(E, A, 0) + 1, A)
        end,
        #{},
        lists:flatten([F(StartPos, EndPos) || {StartPos, EndPos} <- InputData])),
    maps:size(maps:filter(fun(_K, V) -> V >= 2 end, AllPoints)).

points_p1({X1, Y}, {X2, Y}) ->
    [{X, Y} || X <- lists:seq(X1, X2, dir(X1, X2))];
points_p1({X, Y1}, {X, Y2}) ->
    [{X, Y} || Y <- lists:seq(Y1, Y2, dir(Y1, Y2))];
points_p1(_, _) ->
    [].

points_p2({X1, Y1}, {X2, Y2}) when abs(X2 - X1) =:= abs(Y2 - Y1) ->
    Xs = [X || X <- lists:seq(X1, X2, dir(X1, X2))],
    Ys = [Y || Y <- lists:seq(Y1, Y2, dir(Y1, Y2))],
    lists:zip(Xs, Ys);
points_p2(P1, P2) ->
    points_p1(P1, P2).

dir(A, B) when A < B ->
    1;
dir(_, _) ->
    -1.

```

---

<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 5, 2021, 1:43pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/5 "2021-12-05T13:43:39Z")

</div>

As an aside, it feels like `maps:put(Key, maps:get(Key, Map, 0) + 1, Map)` is a common enough idiom that it should have its own library function. Is it me that’s missing something, or is OTP?

---

<div class="post-metadata">

**Author:** ![michallepicki](https://erlangforums.com/letter_avatar_proxy/v4/letter/m/5f9b8f/32.png) [@michallepicki](https://erlangforums.com/u/michallepicki)\
**Post date:** [December 5, 2021, 1:54pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/6 "2021-12-05T13:54:01Z")

</div>

There’s [`maps:update_with/4`](https://www.erlang.org/doc/man/maps.html#update_with-4)

---

<div class="post-metadata">

**Author:** ![adolfont](https://erlangforums.com/user_avatar/erlangforums.com/adolfont/32/402_2.png) [@adolfont](https://erlangforums.com/u/adolfont)\
**Post date:** [December 5, 2021, 2:40pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/7 "2021-12-05T14:40:35Z")

</div>

My lazy solution for “Hydrothermal Venture” - Day 5 - Advent of Code 2021 in Erlang.

> <https://github.com/adolfont/pensandoemelixir/blob/main/adventofcode/2021/day05_2021/day05.erl>

---

<div class="post-metadata">

**Author:** ![adolfont](https://erlangforums.com/user_avatar/erlangforums.com/adolfont/32/402_2.png) [@adolfont](https://erlangforums.com/u/adolfont)\
**Post date:** [December 5, 2021, 3:16pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/8 "2021-12-05T15:16:47Z")

</div>

Beautiful!  
I learned that you can use begin and end on list comprehensions!

---

<div class="post-metadata">

**Author:** ![MononcQc](https://erlangforums.com/user_avatar/erlangforums.com/mononcqc/32/417_2.png) [@MononcQc](https://erlangforums.com/u/MononcQc)\
**Post date:** [December 5, 2021, 3:58pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/9 "2021-12-05T15:58:15Z")

</div>

Compact version for p2:

```erlang
-module(day5).
-export([main/1]).
-mode(compile).

main(_) ->
    {ok, Bin} = file:read_file("day5.input"),
    Rows = [[binary_to_integer(B) || B <- re:split(Line, "[,> -]+")]
            || Line <- string:split(Bin, "\n", all), Line =/= <<>>],
    Tid = ets:new(acc, [set]),
    [ets:update_counter(Tid, {X1+N*X, Y1+N*Y}, {2,1}, {{X1+N*X, Y1+N*Y},0})
     || [X1,Y1,X2,Y2] <- Rows,
         X1==X2 orelse Y1==Y2 orelse abs(X2-X1)==abs(Y2-Y1),
         X <- [if X1==X2 -> 0; true -> trunc((X2-X1)/abs(X2-X1)) end],
         Y <- [if Y1==Y2 -> 0; true -> trunc((Y2-Y1)/abs(Y2-Y1)) end],
         N <- lists:seq(0, max(abs(X2-X1),abs(Y2-Y1)))],
    io:format("~p~n", [length([1 || {_,X} <- ets:tab2list(Tid), X > 1])]).

```

---

<div class="post-metadata">

**Author:** ![adolfont](https://erlangforums.com/user_avatar/erlangforums.com/adolfont/32/402_2.png) [@adolfont](https://erlangforums.com/u/adolfont)\
**Post date:** [December 5, 2021, 4:25pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/10 "2021-12-05T16:25:39Z")

</div>

> [@MononcQc](#):
>
> `re:split(Line, "[,> -]+")`

Great! I was trying to find how to do that with string:split but I quit.

---

<div class="post-metadata">

**Author:** ![peerst](https://erlangforums.com/user_avatar/erlangforums.com/peerst/32/557_2.png) [@peerst](https://erlangforums.com/u/peerst)\
**Post date:** [December 5, 2021, 7:40pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/11 "2021-12-05T19:40:17Z")

</div>

```erlang
p5_1() ->
    Hv = lists:append([line(L, hv) || L <- p5_read("priv/p05.txt")]),
    R1 = length(lists:usort(lists:sort(Hv) -- lists:usort(Hv))),
    D = lists:append([line(L, diag) || L <- p5_read("priv/p05.txt")]),
    R2 = length(lists:usort(lists:sort(D) -- lists:usort(D))),
    {R1, R2}.

line([[X,Y1],[X,Y2]], _) ->
    [[X,Y] || Y <- seq(Y1,Y2)];
line([[X1,Y],[X2,Y]], _) ->
    [[X,Y] || X <- seq(X1,X2)];
line([[X1,Y1], [X2,Y2]], diag) ->
    [tuple_to_list(E) 
     || E <- (lists:zip(seq(X1, X2), seq(Y1, Y2)))];
line(_, hv) ->
    [].
     
seq(A,B) when A < B ->    
    lists:seq(A,B);
seq(A,B) when A >= B -> 
    lists:seq(A,B,-1).
    
p5_read(Fn) ->
    {ok, Bin} = file:read_file(Fn),
    Lines = string:split(string:trim(Bin), "\n", all),
    deep_integer([ [ string:split(P, ",", all) 
                     || P <-string:split(L, " -> ", all) ] || L <- Lines]) .

```

With this re-used from yesterday:

```erlang
deep_integer(L) when is_list(L) ->
    [deep_integer(E) || E <- L];
deep_integer(B) when is_binary(B) ->
    binary_to_integer(B).

```

---

<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 6, 2021, 3:37pm UTC](https://erlangforums.com/t/advent-of-code-2021-day-5/738/12 "2021-12-06T15:37:24Z")

</div>

```erlang
part1() ->
  {ok, Bin} = file:read_file("input_test"),
  Data = data(re:split(Bin, "[,> -/\n]+")),
  length(lists:usort(unique(lists:sort(lists:flatten(lines(Data)))))).

data([]) -> [];
data([H1, H2, H3, H4|T]) -> [{{data(H1), data(H2)}, {data(H3), data(H4)}} | data(T)];
data([_|T]) -> data(T);
data(Bin) -> binary_to_integer(Bin).

lines([]) -> [];
lines([{{X, Y1}, {X, Y2}}|T]) -> [[{X, Y} || Y <- seq(Y1, Y2)] | lines(T)];
lines([{{X1, Y}, {X2, Y}}|T]) -> [[{X, Y} || X <- seq(X1, X2)] | lines(T)];
lines([_|T]) -> lines(T).

unique([]) -> [];
unique([H, H|T]) -> [H | unique(T)];
unique([_|T]) -> unique(T).

seq(A, B) when A < B -> lists:seq(A, B);
seq(A, B) when A >= B -> lists:seq(A, B, -1).

```
