This topic is about Day 17 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!
This topic is about Day 17 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!
Is that Tetris I see?
Oh boy, first part simulation was straightforward, finding cycles for second part in the simulation was not, I’m not sure my solution is general enough, I thought that it’s expected to have a full line at some point so you can treat it as if there are no previous blocks in the state, and go from there, but I don’t think it will work on all inputs, anyway here’s solution that works for my input
main(File) ->
{ok, RawData} = file:read_file(File),
Data = binary_to_list(RawData),
io:format("part 1: ~p~n", [solve1(Data)]),
io:format("part 2: ~p~n", [solve2(Data)]).
solve1(Data) ->
element(1, simulate(Data, 1, 2022)).
solve2(Data) ->
{_, Rep} = simulate(Data, 1, 10000),
{CycleHeight, CyclePeriod, CycleStart} = find_cycle(Rep),
Total = 1000000000000,
Cycles = Total div CyclePeriod,
io:format("~nHeight: ~p Period: ~p Start: ~p~n", [CycleHeight, CyclePeriod, CycleStart]),
io:format("Cycles: ~p~n~n", [Cycles]),
{AddedHeight, _} = simulate(Data, 1, Total - Cycles * CyclePeriod),
AddedHeight + Cycles * CycleHeight.
find_cycle(Rep) ->
[{H1, B1, _, P}, {H2, B2, _, P}|_]
= hd([ V || {_, _, R, P} <- Rep,
length(V = [ X || {_, _, R0, P0} = X <- Rep, R0 =:= R, P0 =:= P ]) > 1 ]),
{H2 - H1, B2 - B1, B1}.
simulate(Pattern, From, To) ->
State = {0, Pattern, [], #{}, []},
{FloorHeight, _, _, _, Rep} = lists:foldl(fun do_simulate/2, State, lists:seq(From, To)),
{FloorHeight, lists:reverse(Rep)}.
do_simulate(RockNum, {FloorHeight, Pattern, RestPattern, Map, Rep}) ->
Rock = plus({2, FloorHeight + 3}, rock((RockNum - 1) rem 5)),
{MaxY, NewP, NewRestP, NewMap, NewRep} = simulate_drop(Rock, RockNum, Pattern, RestPattern, Map, Rep),
{max(FloorHeight, MaxY), NewP, NewRestP, NewMap, NewRep}.
simulate_drop(Rock, RockNum, [], RestPattern, Map, Rep) ->
simulate_drop(Rock, RockNum, lists:reverse(RestPattern), [], Map, Rep);
simulate_drop(Rock, RockNum, [Direction|Rest], RestPattern, Map, Rep) ->
Plus = case Direction of
$< -> {-1, 0};
$> -> { 1, 0}
end,
NewRock0 = plus(Plus, Rock),
NewRock1 = case collision(NewRock0, Map) of
true -> Rock;
false -> NewRock0
end,
NewRock2 = plus({0, -1}, NewRock1),
case collision(NewRock2, Map) of
true ->
MaxY = lists:max([ Y || {_, Y} <- NewRock1 ]),
NewMap = lists:foldl(fun (X, Acc) -> Acc#{X => ok} end, Map, NewRock1),
NewRep = case length([ true || X <- lists:seq(1, 7), maps:is_key({X, MaxY}, NewMap) ]) of
7 -> [{MaxY, RockNum, (RockNum - 1) rem 5, length(RestPattern)}|Rep];
_ -> Rep
end,
{MaxY, Rest, [Direction|RestPattern], NewMap, NewRep};
false ->
simulate_drop(NewRock2, RockNum, Rest, [Direction|RestPattern], Map, Rep)
end.
plus({X, Y}, Rock) ->
[ {X0 + X, Y0 + Y} || {X0, Y0} <- Rock ].
collision(Rock, Map) ->
lists:any(fun ({X, Y} = C) -> X =:= 0 orelse X =:= 8 orelse Y =:= 0 orelse is_map_key(C, Map) end, Rock).
rock(0) -> [ {X, 1} || X <- lists:seq(1, 4) ];
rock(1) -> [{2, 1}, {2, 3}] ++ [ {X, 2} || X <- lists:seq(1, 3) ];
rock(2) -> [{3, 3}, {3, 2}] ++ [ {X, 1} || X <- lists:seq(1, 3) ];
rock(3) -> [ {1, Y} || Y <- lists:seq(1, 4) ];
rock(4) -> [{1, 1}, {2, 1}, {1, 2}, {2, 2}].