Advent of Code 2022 Day 19 - Discussions

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

Link to our leaderboard:

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

The entry code is:
370884-a6a71927

We are at 196 right now and 200 is the cap, in case the leaderboard fills up and you are unable to join, please join the following:

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

And the code for this leaderboard is: 257223-1bcda624

Good luck!

1 Like

My original solution took a while to get the answer, after reading what people implemented on reddit, I found idea of limiting ore/clay/obsidian max values to a limit of what can be ever spend, so then number of states to go through can be pruned, so now it takes “reasonable” amount to run the code:

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

get_integers(Bin) ->
    {match, Match} = re:run(Bin, <<"([-\\d]+)">>, [{capture, all_but_first, binary}, global]),
    [ binary_to_integer(X) || [X] <- Match ].

solve1(Data) ->
    lists:sum(lists:map(fun quality/1, Data)).

solve2(Data) ->
    {L, _} = lists:split(3, Data),
    lists:foldl(fun erlang:'*'/2, 1, [ max_geodes(tl(X), 32) || X <- L ]).

quality([Id|Blueprint]) ->
    Id * max_geodes(Blueprint, 24).

max_geodes(Blueprint, N) ->
    Start = {{1, 0, 0, 0}, {0, 0, 0, 0}},
    [OreP, OreClayP, OreObsP, _, OreGeodeP, _] = Blueprint,
    max_geodes([Start], {Blueprint, lists:max([OreP, OreClayP, OreObsP, OreGeodeP])}, N).

max_geodes(Options, _Blueprint, 0) ->
    Max = lists:max([ X || {_, {_, _, _, X}} <- Options ]),
    io:format("~p~n", [Max]),
    Max;
max_geodes(Options, Blueprint, TimeLeft) ->
    ToFollow = [ X || M <- Options,
                      X <- moves(M, Blueprint, TimeLeft) ],
    io:format("."),
    max_geodes(sets:to_list(sets:from_list(ToFollow, [{version, 2}])), Blueprint, TimeLeft - 1).

moves({{OreRobotN, ClayRobotN, ObsRobotN, GeodeRobotN} = Robots,
       {Ore,       Clay,       Obs,       Geode}},
      {[OreP, OreClayP, OreObsP, ClayObsP, OreGeodeP, ObsGeodeP], OreMax},
      TimeLeft) ->
    OreLimit  = (TimeLeft * OreMax)    - OreRobotN  * (TimeLeft - 1),
    ClayLimit = (TimeLeft * ClayObsP)  - ClayRobotN * (TimeLeft - 1),
    ObsLimit  = (TimeLeft * ObsGeodeP) - ObsRobotN  * (TimeLeft - 1),
    NewItems = {min(Ore,  OreLimit)  + OreRobotN,
                min(Clay, ClayLimit) + ClayRobotN,
                min(Obs,  ObsLimit)  + ObsRobotN,
                Geode + GeodeRobotN},
    O1 = [{Robots, NewItems}],
    O2 = [ {plus(Robots, {1, 0, 0, 0}), plus({-OreP,      0,         0,          0}, NewItems)} || Ore >= OreP,                        OreRobotN  < OreMax    ],
    O3 = [ {plus(Robots, {0, 1, 0, 0}), plus({-OreClayP,  0,         0,          0}, NewItems)} || Ore >= OreClayP,                    ClayRobotN < ClayObsP  ],
    O4 = [ {plus(Robots, {0, 0, 1, 0}), plus({-OreObsP,   -ClayObsP, 0,          0}, NewItems)} || Ore >= OreObsP,   Clay >= ClayObsP, ObsRobotN  < ObsGeodeP ],
    O5 = [ {plus(Robots, {0, 0, 0, 1}), plus({-OreGeodeP, 0,         -ObsGeodeP, 0}, NewItems)} || Ore >= OreGeodeP, Obs  >= ObsGeodeP ],
    case Ore >= OreMax + 1 of
        true  -> O2 ++ O3 ++ O4 ++ O5;
        false -> O1 ++ O2 ++ O3 ++ O4 ++ O5
    end.

plus({A1, B1, C1, D1}, {A2, B2, C2, D2}) ->
    {A2 + A1, B2 + B1, C2 + C1, D1 + D2}.
2 Likes