This topic is about Day 9 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 9 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!
Today’s challenge was quite fun
main(File) ->
{ok, RawData} = file:read_file(File),
Data = [ begin
[D, L] = binary:split(Line, <<" ">>, [global, trim]),
{D, binary_to_integer(L)}
end
|| Line <- binary:split(RawData, <<"\n">>, [global, trim]) ],
io:format("part 1: ~p~n", [solve1(Data)]),
io:format("part 2: ~p~n", [solve2(Data)]).
solve1(Data) ->
sets:size(move_head({0, 0}, [{0, 0}], Data, sets:new())).
solve2(Data) ->
sets:size(move_head({0, 0}, lists:duplicate(9, {0, 0}), Data, sets:new())).
move_head(_HeadPos, _Tails, [], SetAcc) -> SetAcc;
move_head( HeadPos, Tails, [{_Dir, 0} |Rest], SetAcc) -> move_head(HeadPos, Tails, Rest, SetAcc);
move_head({X0, Y0}, Tails, [{ Dir, Len}|Rest], SetAcc) ->
NewHeadPos = case Dir of
<<"R">> -> {X0 + 1, Y0};
<<"L">> -> {X0 - 1, Y0};
<<"U">> -> {X0, Y0 - 1};
<<"D">> -> {X0, Y0 + 1}
end,
NewTails = move_tails(NewHeadPos, Tails),
move_head(NewHeadPos, NewTails, [{Dir, Len - 1}|Rest], sets:add_element(lists:last(NewTails), SetAcc)).
move_tail({X0, Y0}, {X1, Y1}) when X0 == X1, abs(Y0 - Y1) == 2 -> {X0, (Y0 + Y1) div 2};
move_tail({X0, Y0}, {X1, Y1}) when X0 == X1, abs(Y0 - Y1) == 2 -> {X0, (Y0 + Y1) div 2};
move_tail({X0, Y0}, {X1, Y1}) when Y0 == Y1, abs(X0 - X1) == 2 -> {(X0 + X1) div 2, Y0};
move_tail({X0, Y0}, {X1, Y1}) when abs(X0 - X1) == 2, abs(Y0 - Y1) == 1 -> {(X0 + X1) div 2, Y0};
move_tail({X0, Y0}, {X1, Y1}) when abs(X0 - X1) == 1, abs(Y0 - Y1) == 2 -> {X0, (Y0 + Y1) div 2};
move_tail({X0, Y0}, {X1, Y1}) when abs(X0 - X1) == 2, abs(Y0 - Y1) == 2 -> {(X0 + X1) div 2, (Y0 + Y1) div 2};
move_tail(_HeadPos, TailPos) ->
TailPos.
move_tails(_Head, []) -> [];
move_tails( Head, [Tail|Rest]) ->
NewTail = move_tail(Head, Tail),
[NewTail|move_tails(NewTail, Rest)].
Wow, this is fun! I just finished Part 1. On to Part 2… (EDIT: Done with that!)
-module(day_9).
-export([solve/0, move/4]).
input() ->
{ok, Data} = file:read_file("data/9.txt"),
Data.
parse(Data) ->
Lines = binary:split(Data, <<"\n">>, [global, trim]),
Instructions = lists:map(fun parse_instruction/1, Lines),
Instructions.
parse_instruction(Line) ->
[A, B] = binary:split(Line, <<" ">>),
{binary_to_list(A), binary_to_integer(B)}.
solve() ->
Data = parse(input()),
{solver(Data, [{0, 0}]), solver(Data, lists:duplicate(9, {0, 0}))}.
solver(Data, Tails) ->
Reducer =
fun({D, V}, Acc) ->
lists:foldl(fun(_, Acc2) ->
{HeadPos, TailPos, Visits} = Acc2,
move(HeadPos, TailPos, D, Visits)
end,
Acc,
lists:seq(1, V))
end,
{_, _, Visits} = lists:foldl(Reducer, {{0, 0}, Tails, []}, Data),
sets:size(
sets:from_list(Visits)).
move({HX, HY}, Tails, D, Visits) ->
HeadPos =
case D of
"U" ->
{HX, HY + 1};
"D" ->
{HX, HY - 1};
"L" ->
{HX - 1, HY};
"R" ->
{HX + 1, HY}
end,
NewTails = move_tails(HeadPos, Tails),
{HeadPos, NewTails, [lists:last(NewTails) | Visits]}.
move_tail({HX, HY}, {TX, TY}) when HX == TX, HY - TY == 2 ->
{TX, TY + 1};
move_tail({HX, HY}, {TX, TY}) when HX == TX, TY - HY == 2 ->
{TX, TY - 1};
move_tail({HX, HY}, {TX, TY}) when HY == TY, HX - TX == 2 ->
{TX + 1, TY};
move_tail({HX, HY}, {TX, TY}) when HY == TY, TX - HX == 2 ->
{TX - 1, TY};
move_tail({HX, HY}, {TX, TY}) ->
case {HX - TX, HY - TY} of
{1, 1} ->
{TX, TY};
{-1, -1} ->
{TX, TY};
{1, -1} ->
{TX, TY};
{-1, 1} ->
{TX, TY};
{DX, DY} when DX > 0, DY > 0 ->
{TX + 1, TY + 1};
{DX, DY} when DX > 0, DY < 0 ->
{TX + 1, TY - 1};
{DX, DY} when DX < 0, DY > 0 ->
{TX - 1, TY + 1};
{DX, DY} when DX < 0, DY < 0 ->
{TX - 1, TY - 1};
{_, _} ->
{TX, TY}
end.
move_tails(_, []) ->
[];
move_tails(Head, [Tail | Rest]) ->
NewTail = move_tail(Head, Tail),
[NewTail | move_tails(NewTail, Rest)].
Hi! I used a similar approach @danilagamma , but used a cleaner tail calculation function (calculate_tail
) and used tail recursion in update_tail
-module(solver).
-export([main/0]).
-export([test/0]).
-define(START, {0,0}).
test() ->
{0,0} = calculate_tail(?START, {0,0}),
{0,0} = calculate_tail(?START, {1,0}),
{1,0} = calculate_tail(?START, {2,0}),
{0,0} = calculate_tail(?START, {1,1}),
{1,1} = calculate_tail(?START, {2,1}),
{-1,-1} = calculate_tail(?START, {-2,-1}),
TestInput = <<"R 4\nU 4\nL 3\nD 1\nR 4\nD 1\nL 5\nR 2">>,
Moves = load(TestInput),
13 = solve1(Moves),
1 = solve2(Moves),
ok.
main() ->
{ok, Data} = file:read_file(input),
Moves = load(Data),
{solve1(Moves), solve2(Moves)}.
load(Data0) ->
[
begin
[Motion, Times] = binary:split(Row, <<" ">>, [global, trim]),
{Motion, list_to_integer(binary:bin_to_list(Times))}
end
|| Row <- binary:split(Data0, <<"\n">>, [global, trim])
].
solve1(Moves) ->
Visited = visited(2, Moves),
sets:size(Visited).
solve2(Moves) ->
Visited = visited(10, Moves),
sets:size(Visited).
visited(KnotsNum, Moves) ->
{_, Visited} =
lists:foldl(fun(Move, {Knots, VisitedAcc}) ->
move_knots(Move, {Knots, VisitedAcc})
end,
{lists:duplicate(KnotsNum, ?START), sets:add_element({0,0}, sets:new())},
Moves),
Visited.
move_knots({_, 0}, Acc) -> Acc;
move_knots({Dir, Times}, {[Head | Tail] = _Knots, VisitedAcc}) ->
NewFirst = move_head(Dir, Head),
NewKnots = update_tail(Tail, [NewFirst]),
NewLastPos = lists:last(NewKnots),
NewVisitedAcc = sets:add_element(NewLastPos, VisitedAcc),
move_knots({Dir, Times - 1}, {NewKnots, NewVisitedAcc}).
update_tail([], Acc) -> lists:reverse(Acc);
update_tail([TailHead | Tail], [Head | _] = Acc) ->
NewTailHead = calculate_tail(TailHead, Head),
update_tail(Tail, [NewTailHead | Acc]).
move_head(<<"U">>, {X, Y}) -> {X, Y + 1};
move_head(<<"D">>, {X, Y}) -> {X, Y - 1};
move_head(<<"L">>, {X, Y}) -> {X - 1, Y};
move_head(<<"R">>, {X, Y}) -> {X + 1, Y}.
calculate_tail({TX, Same}, {HX, Same}) when abs(HX - TX) > 1 -> {TX + dir(HX, TX), Same};
calculate_tail({Same, TY}, {Same, HY}) when abs(HY - TY) > 1 -> {Same, TY + dir(HY, TY)};
calculate_tail({TX, TY}, {HX, HY}) when abs(HX - TX) + abs(HY - TY) > 2 -> {TX + dir(HX, TX), TY + dir(HY, TY)};
calculate_tail(TPos, _) -> TPos.
dir(0, 0) -> 0;
dir(H, T) -> (H - T) div abs(H - T).