Advent of Code 2021 - Day 6

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

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

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

The entry code is:
370884-a6a71927

6 Likes

Pretty easy one today. I used the solution they were obviously trying to trick you into using by representing the fish state as a list for part 1 and appending new fish as they spawn, before changing it to a map of counters to be able to run part 2.

Edit: Here’s a solution - did it in Go at first, which is famously verbose, and I wanted to see how much cleaner it would look in Erlang. Quite a bit, and I didn’t spend much time trying to make it pretty.

-module(day06).
-export([main/0]).

main() ->
    Init = parse("input/day06.txt"),
    io:format("Part 1: ~p~nPart 2: ~p~n", [run(Init, 80), run(Init, 256)]).

run(Fish, 0) -> lists:sum(maps:values(Fish));
run(Fish, Days) -> run(tick(Fish), Days - 1).

tick(Fish) ->
    Spawning = maps:get(0, Fish, 0),
    Decremented = lists:foldl(fun shift_down/2, Fish, lists:seq(1, 8)),
    Decremented#{8 => Spawning,
                 6 => maps:get(6, Decremented, 0) + Spawning}.

shift_down(Ix, Map) ->
    Map#{Ix - 1 => maps:get(Ix, Map, 0)}.

parse(File) ->
    {ok, BinData} = file:read_file(File),
    Str = binary_to_list(BinData),
    Trimmed = string:trim(Str),
    freq([list_to_integer(Token) || Token <- string:tokens(Trimmed, ",")]).

freq(Fish) ->
    lists:foldl(fun increment_at/2, #{}, Fish).

increment_at(Ix, Map) ->
    maps:update_with(Ix, fun(N) -> N + 1 end, 1, Map).

7 Likes

@Gwaeron that’s how it went for me :sweat_smile: :

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

solve1(Data) ->
    length(simulate_n(Data, 80)).

simulate_n(Data, Days) ->
    lists:foldl(fun (_, Acc) -> [ NewFishes || F <- Acc, NewFishes <- simulate(F) ] end,
                Data,
                lists:seq(1, Days)).

simulate(0) -> [6, 8];
simulate(X) -> [X - 1].

solve2(Data) ->
    OneToFive = maps:values(freq(Data)),
    Initial = list_to_tuple([0] ++ OneToFive ++ [0, 0, 0]),
    lists:sum(tuple_to_list(simulate_count_n(Initial, 256))).

simulate_count_n(Acc, 0) -> Acc;
simulate_count_n(Acc, N) ->
    simulate_count_n(simulate_count(Acc), N - 1).

simulate_count({V0, V1, V2, V3, V4, V5, V6, V7, V8}) ->
    {V1, V2, V3, V4, V5, V6, V7 + V0, V8, V0}.

freq(List) ->
    lists:foldl(fun (K, Acc) -> maps:update_with(K, fun (V) -> V + 1 end, 1, Acc) end,
                #{},
                List).
7 Likes

Ditto.

Buy the way, there’s an Unofficial AoC 2021 Survey - would be good if more than one person ticked Erlang :slight_smile:

5 Likes

Done in Awk first as I respect my initial engagement, but felt it would have been so much easier in Erlang:

BEGIN { FS="," }
{ for (i=1; i<=NF; i++) { l[$i]++ } }
END {
    for (i=1; i<=DAYS; i++) {
        t=l[0]
        for (j=0; j<8; j++) { l[j]=l[j+1] }
        l[8]=t; l[6]+=t
    }
    for (i in l) { c+=l[i] }
    print c
}

For comparison:

main([File]) ->
    {ok, Bin} = file:read_file(File),
    T = lists:foldl(
          fun(N,T) -> setelement(N+1, T, element(N+1,T)+1) end,
          {0,0,0,0,0,0,0,0,0},
          [binary_to_integer(B) || L <- string:split(Bin, "\n", all), L =/= <<>>,
                                   B <- string:split(L, ",", all)]
    ),
    io:format("~p~n", [run(256, T)]).

run(0,{A,B,C,D,E,F,G,H,I}) -> A+B+C+D+E+F+G+H+I;
run(N,{A,B,C,D,E,F,G,H,I}) -> run(N-1, {B,C,D,E,F,G,H+A,I,A}).
8 Likes

Part 1:

part1() ->
  Bin = <<"3,4,3,1,2\n">>,
  Data = [binary_to_integer(X) || X <- re:split(Bin, "[,/\n]+"), X /= <<>>],
  length(simulation(256, Data))

simulation(0, Fishs)    -> Fishs;
simulation(Days, Fishs) -> simulation(Days - 1, lanternfish(Fishs)).

lanternfish([])    -> [];
lanternfish([0|T]) -> [6 | [8 | lanternfish(T)]];
lanternfish([H|T]) -> [H - 1 | lanternfish(T)].

And… After crashing of my shell :stuck_out_tongue_winking_eye::
Part 2:

part2() ->
  {ok, Bin} = file:read_file("input"),
  Data = [binary_to_integer(X) || X <- re:split(Bin, "[,/\n]+"), X /= <<>>],
  Acc = #{0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0},
  gen(256, init(Data, Acc)).

init([], Acc) ->
  Acc;
init([H|T], Acc) ->
  init(T, Acc#{H => maps:get(H, Acc) + 1}).

gen(0, #{0 := D0, 1 := D1, 2 := D2, 3 := D3, 4 := D4, 5 := D5, 6 := D6, 7 := D7, 8 := D8}) ->
  D0 + D1 + D2 + D3 + D4 + D5 + D6 + D7 + D8;
gen(Days, #{0 := D0, 1 := D1, 2 := D2, 3 := D3, 4 := D4, 5 := D5, 6 := D6, 7 := D7, 8 := D8}) ->
  gen(Days - 1, #{0 => D1, 1 => D2, 2 => D3, 3 => D4, 4 => D5, 5 => D6, 6 => D0 + D7, 7 => D8, 8 => D0}).

:metal:

5 Likes

Day 6 in Sesterl - adventofcode/main.sest at master · michallepicki/adventofcode · GitHub

4 Likes

Thanks. @Gwaeron. Your first few words helped me solve today’s puzzle: pensandoemelixir/day06_v2.erl at main · adolfont/pensandoemelixir · GitHub

Ugly as usual, but I believe I am learning.

4 Likes