Skip to content

Instantly share code, notes, and snippets.

@joeytrapp
Created December 6, 2024 06:53
Show Gist options
  • Save joeytrapp/a5dcd31e5e45838284c3a1624cf0a349 to your computer and use it in GitHub Desktop.
Save joeytrapp/a5dcd31e5e45838284c3a1624cf0a349 to your computer and use it in GitHub Desktop.
Advent of Code Day 5 Part 1 and Part 2
-module(aoc).
-export([main/1]).
main([Path]) ->
{ok, Content} = file:read_file(Path),
{Rules, Edits} = parse(Content),
{Correct, Incorrect} = classify_edits(Edits, Rules),
Corrected = corrections(Incorrect, Rules),
io:format("Originally Correct: ~p~n", [sum_of_middles(Correct)]),
io:format("Updated to Correct: ~p~n", [sum_of_middles(Corrected)]),
erlang:halt(0).
parse(Bin) when is_binary(Bin) ->
Lines = binary:split(Bin, <<"\n">>, [global, trim]),
{Rules, T} = parse_rules(Lines, #{}),
Edits = lists:map(fun parse_edits_line/1, T),
{Rules, Edits}.
parse_rules([<<>>|T], Rules) -> {Rules, T};
parse_rules([H|T], Rules) -> parse_rules(T, parse_rules_line(H, Rules)).
parse_rules_line(Bin, Rules) when is_binary(Bin), is_map(Rules) ->
[LS,RS] = binary:split(Bin, <<"|">>, [global, trim]),
L = binary_to_integer(LS),
R = binary_to_integer(RS),
M = maps:update_with(L, fun({A,B}) ->
{A, sets:add_element(R, B)}
end, {sets:from_list([]), sets:from_list([R])}, Rules),
maps:update_with(R, fun({A,B}) ->
{sets:add_element(L, A), B}
end, {sets:from_list([L]), sets:from_list([])}, M).
parse_edits_line(Bin) when is_binary(Bin) ->
L = binary:split(Bin,<<",">>, [global, trim]),
lists:map(fun(S) -> binary_to_integer(S) end, L).
sum_of_middles(List) ->
lists:sum(lists:map(fun(L) -> lists:nth(ceil(length(L) / 2), L) end, List)).
classify_edits(Edits, Rules) -> lists:partition(fun(L) -> is_correct(L, Rules) end, Edits).
is_correct(L, Rules) -> is_correct(true, build_set_list(L), Rules).
is_correct(false, _, _) -> false;
is_correct(B, [], _) -> B;
is_correct(B, [{N, Before, After}|T], Rules) ->
case maps:get(N, Rules, nil) of
nil ->
is_correct(B, T, Rules);
Allowed = {_, _} ->
is_correct(is_valid(Before, After, Allowed), T, Rules)
end.
is_valid(Before, After, {AllowedBefore,AllowedAfter}) ->
sets:is_subset(Before, AllowedBefore) andalso sets:is_subset(After, AllowedAfter).
build_set_list(L) -> build_set_list(L, [], []).
build_set_list([], _, Acc) -> lists:reverse(Acc);
build_set_list([H|A], B, Acc) ->
Acc2 = [{H, sets:from_list(B), sets:from_list(A)} | Acc],
build_set_list(A, [H|B], Acc2).
corrections(L, Rules) ->
lists:map(fun(H) ->
C = lists:sort(fun(A, B) ->
sets:is_element(B, element(2, maps:get(A, Rules)))
end, H),
lists:sort(fun(A, B) ->
sets:is_element(A, element(1, maps:get(B, Rules)))
end, C)
end, L).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment