Advent of Code 2021 - Day 17

This topic is about Day 17 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

3 Likes

I thought I needed some fancy maths to do this. Turns out I did not :slight_smile:

4 Likes

Same, initially I solved it with brute force with some arbitrary bound on dy, like 1000, and it was still fast enough to iterate through all initial {dx,dy} combinations in a second or so. Later I tried to optimise it and be smart, but only figured out limit on dy is abs(min_y) from the input, that only works for max_y < start_y so :man_shrugging: :

main(File) ->
    {ok, RawData} = file:read_file(File),
    {match, RawTarget} = re:run(RawData, <<"([-\\d]+)">>, [{capture, all_but_first, list}, global]),
    Target = list_to_tuple([ list_to_integer(X) || [X] <- RawTarget ]),
    io:format("part 1: ~p~n", [solve1(Target)]),
    io:format("part 2: ~p~n", [solve2(Target)]).

solve1(Target) ->
    lists:max(heights(Target)).

solve2(Target) ->
    length(heights(Target)).

heights({_MinX, MaxX, MinY, _MaxY} = Target) ->
    [ H || X <- lists:seq(1, MaxX),
           Y <- lists:seq(MinY, abs(MinY)),
           (H = iter_steps({X, Y}, Target)) =/= false ].

iter_steps(V, Target) ->
    iter_steps(V, Target, {0, 0}, 0).

iter_steps(V, Target, {_, Y} = C, H) ->
    case position(C, Target) of
        hit ->
            H;
        continue ->
            {NewV, NewC} = step(V, C),
            iter_steps(NewV, Target, NewC, max(Y, H));
        _ ->
            false
    end.

step({Dx, Dy}, {X, Y}) ->
    {{max(0, Dx - 1), Dy - 1}, {X + Dx, Y + Dy}}.

position({X,  Y}, { MinX,  MaxX,  MinY,  MaxY}) when X >= MinX, X =< MaxX, Y >= MinY, Y =< MaxY -> hit;
position({X, _Y}, {_MinX,  MaxX, _MinY, _MaxY}) when X  > MaxX                                  -> over;
position({_,  Y}, {_MinX, _MaxX,  MinY, _MaxY}) when Y  < MinY                                  -> under;
position(_XY,     _Target)                                                                      -> continue.
3 Likes

Much more fun with fancy math though. It’s possible to generate initial x and y velocity backward from a target coordinate using arithmetic progression.
However, I needed to apply a brute force version eventually to the second part to compare results and find missing pairs caused by a small bug in the fancy math :wink:

3 Likes