Advent of Code 2022 Day 5 - Discussions

This topic is about Day 5 of the Advent of Code 2022 .

Link to our leaderboard:

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

The entry code is:
370884-a6a71927

Good luck!

2 Likes

This time parsing first part of the input seemed more of a challenge than actual problem, so I manually parsed initial state and automated it after submitting answers:

main(File) ->
    {ok, RawData} = file:read_file(File),
    [RawState, RawMoves] = binary:split(RawData, <<"\n\n">>, [global, trim]),
    State = parse_state(RawState),
    Data  = parse_moves(RawMoves),
    io:format("part 1: ~p~n", [solve1(State, Data)]),
    io:format("part 2: ~p~n", [solve2(State, Data)]).

parse_state(RawState0) ->
    RawState  = binary:split(RawState0, <<"\n">>, [global]),
    Cols      = binary_to_integer(lists:last(binary:split(lists:last(RawState), <<" ">>, [global, trim]))),
    Positions = lists:zip(lists:seq(1, Cols), [ 1 + 4 * X || X <- lists:seq(0, Cols - 1) ]),
    State     = maps:from_list([ {N, [ C || R <- lists:droplast(RawState), (C = pick_byte(R, P)) =/= <<" ">> ]}
                                 || {N, P} <- Positions ]),
    io:format("State: ~p~n", [State]),
    State.

pick_byte(Binary, Pos) when byte_size(Binary) >= Pos ->
    binary:part(Binary, {Pos, 1});
pick_byte(_Binary, _Pos) ->
    <<" ">>.

parse_moves(RawMoves) ->
    [ [ binary_to_integer(X)
        || X <- binary:split(N, [<<"move ">>, <<" from ">>, <<" to ">>], [global, trim]), X =/= <<>>]
      || N <- binary:split(RawMoves, <<"\n">>, [global, trim]) ].

solve1(State, Data) ->
    top_crates(lists:foldl(fun crane_9000/2, State, Data)).

solve2(State, Data) ->
    top_crates(lists:foldl(fun crane_9001/2, State, Data)).

crane_9000(Move, State) ->
    crane(Move, State, fun lists:reverse/2).

crane_9001(Move, State) ->
    crane(Move, State, fun lists:append/2).

crane([N, From, To], State, AppendFun) ->
    FromStack = maps:get(From, State),
    ToStack   = maps:get(To,   State),
    {ToPut, NewFromStack} = lists:split(N, FromStack),
    State#{To    => AppendFun(ToPut, ToStack),
           From  => NewFromStack}.

top_crates(State) ->
    << <<(hd(X))/binary>> || X <- maps:values(State) >>.

Can’t think of better way to parse initial state at this time of day, I’m sure it’s possible, will check it later

2 Likes

I couldn’t do day 10 with Erlang, but today’s Erlang adventure was with Day 5. I have an observation though (I will google it later). binary_to_list(list_to_binary(["A", "B", "C"])) is "ABC" but ["A", "B", "C"] and "ABC" are not the same. So X != a2z(z2a(X)) here?

Another slight annoying thing for me was that array is 0 indexed whereas lists are 1? As are tuples? But aren’t arrays based on tuples? Looks like I have some learning by learning (instead of doing) to do tomorrow.

Anyways, here’s my day 5 in Erlang:

-module(day_5).

-export([solve/0]).

input() ->
  {ok, Data} = file:read_file("data/5.txt"),
  Data.

solve() ->
  Data = parse(input()),
  {solve1(Data), solve2(Data)}.

solve1({State, Steps}) ->
  solver({State, Steps}, fun lists:reverse/1).

solve2({State, Steps}) ->
  solver({State, Steps}, fun(X) -> X end).

solver({State, Steps}, Fun) ->
  Reducer =
    fun({Q, S, D}, Acc) ->
       Source = array:get(S - 1, Acc),
       Destination = array:get(D - 1, Acc),
       {Move, NewSource} = lists:split(Q, Source),
       NewDestination = Fun(Move) ++ Destination,
       array:set(S - 1, NewSource, array:set(D - 1, NewDestination, Acc))
    end,
  top_containers(array:to_list(
                   lists:foldl(Reducer, State, Steps))).

parse(Data) ->
  [State, Steps] = binary:split(Data, <<"\n\n">>),
  {parse_state(State), parse_steps(Steps)}.

parse_steps(Steps) ->
  RawSteps = lists:map(fun binary_to_list/1, binary:split(Steps, <<"\n">>, [global])),
  ToInteger = fun(X) -> element(1, string:to_integer(X)) end,
  [begin
     [_, Q, _, S, _, D] = string:split(Step, " ", all),
     {ToInteger(Q), ToInteger(S), ToInteger(D)}
   end
   || Step <- RawSteps].

parse_state(State) ->
  Rows =
    [binary_to_list(X)
     || X
          <- lists:droplast(
               binary:split(remove_brackets(State), <<"\n">>, [global]))],
  Containers =
    lists:map(fun(X) -> [string:trim(Container) || Container <- string:split(X, "   ", all)]
              end,
              Rows),
  array:from_list([lists:dropwhile(fun(X) -> X == [] end, C)
                   || C <- common:transpose(Containers)]).

remove_brackets(Container) ->
  binary:replace(
    binary:replace(Container, <<"[">>, <<" ">>, [global]), <<"]">>, <<" ">>, [global]).

top_containers(Containers) ->
  binary_to_list(list_to_binary([hd(X) || X <- Containers])).
2 Likes