Skip to content

Instantly share code, notes, and snippets.

@joeytrapp
Last active December 7, 2024 19:08
Show Gist options
  • Save joeytrapp/eb48413a58ca43827b4735748d9b76bb to your computer and use it in GitHub Desktop.
Save joeytrapp/eb48413a58ca43827b4735748d9b76bb to your computer and use it in GitHub Desktop.
Advent of Code Day 6 Part 1 and Part 2
-module(aoc).
-export([main/1]).
main([Path]) ->
{ok, Content} = file:read_file(Path),
{Grid, [Guard]} = parse(Content),
Complete = rounds(Grid, Guard),
Tests = sets:del_element(element(2, Guard), Complete),
io:format("Visited: ~p~n", [sets:size(Complete)]),
Loops = sets:fold(fun(Pos,Acc) ->
case contains_loop(obstruct(Grid,Pos), Guard) of
true -> Acc + 1;
false -> Acc
end
end, 0, Tests),
io:format("Loops: ~p~n", [Loops]),
erlang:halt(0).
parse(Bin) when is_binary(Bin) ->
Lines = binary:split(Bin, <<"\n">>, [global, trim_all]),
lists:foldl(fun({Y, Line}, {A0, G0}) ->
{Row, G1} = collect(Line, Y, 0, [], array:new(string:length(Line))),
{array:set(Y-1, Row, A0), lists:append(G0, G1)}
end, {array:new(length(Lines)), []}, lists:enumerate(Lines)).
collect(<<>>, _, _, G, A) -> {A, G};
collect(<<C:1/binary, T/binary>>, Y, X, G0, A0) ->
{Symbol, G1} = case C of
<<".">> -> {empty, []};
<<"#">> -> {obstruction, []};
<<"^">> -> {empty, [{up, {X,Y}}]};
<<">">> -> {empty, [{right, {X,Y}}]};
<<"v">> -> {empty, [{down, {X,Y}}]};
<<"<">> -> {empty, [{left, {X,Y}}]}
end,
collect(T, Y, X+1, lists:append(G0, G1), array:set(X, Symbol, A0)).
lookup(G0, {X,Y}) ->
try
array:get(X, array:get(Y, G0))
catch
error:_Reason -> undefined
end.
obstruct(G0, {X,Y}) ->
R0 = array:get(Y, G0),
R1 = array:set(X, obstruction, R0),
array:set(Y, R1, G0).
move_up({X,Y}) -> {X,Y-1}.
move_right({X,Y}) -> {X+1,Y}.
move_down({X,Y}) -> {X,Y+1}.
move_left({X,Y}) -> {X-1,Y}.
move_fn(up) -> fun move_up/1;
move_fn(right) -> fun move_right/1;
move_fn(down) -> fun move_down/1;
move_fn(left) -> fun move_left/1.
turn(up) -> right;
turn(right) -> down;
turn(down) -> left;
turn(left) -> up.
rounds(Grid, Guard) -> rounds(Grid, Guard, sets:new()).
rounds(_, undefined, Seen) -> Seen;
rounds(Grid, {Dir,P0}, Seen) ->
Fn = move_fn(Dir),
P1 = Fn(P0),
case lookup(Grid, P1) of
obstruction -> rounds(Grid, {turn(Dir), P0}, Seen);
undefined -> rounds(Grid, undefined, sets:add_element(P0, Seen));
_ -> rounds(Grid, {Dir, P1}, sets:add_element(P0, Seen))
end.
contains_loop(Grid, Guard) -> contains_loop(Grid, Guard, sets:new()).
contains_loop(_, undefined, _) -> false;
contains_loop(Grid, {Dir,P0}, Seen) ->
Fn = move_fn(Dir),
P1 = Fn(P0),
case lookup(Grid, P1) of
undefined -> contains_loop(Grid, undefined, Seen);
obstruction -> contains_loop(Grid, {turn(Dir), P0}, Seen);
_ ->
case sets:is_element({Dir,P0}, Seen) of
true -> true;
false -> contains_loop(Grid, {Dir, P1}, sets:add_element({Dir,P0}, Seen))
end
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment