Created
December 5, 2024 04:04
-
-
Save joeytrapp/dccd46391e4fb6f2f06b39b92de43f30 to your computer and use it in GitHub Desktop.
Advent of Code Day 4 Part 1 and Part 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(aoc). | |
-export([main/1]). | |
main([Path]) -> | |
{ok, Content} = file:read_file(Path), | |
Data = fill(Content), | |
YSize = array:size(Data), | |
XSize = array:size(array:get(0, Data)), | |
persistent_term:put(?MODULE, Data), | |
Strings = make_strings(XSize, YSize), | |
io:format("Xmas Sum: ~p~n", [lists:sum(lists:map(fun test_binary/1, Strings))]), | |
io:format("Cross Sum: ~p~n", [lists:sum(find_x_mas(XSize, YSize))]), | |
erlang:halt(0). | |
fill(Binary) when is_binary(Binary) -> | |
Lines = binary:split(Binary, <<"\n">>, [global, trim_all]), | |
fill(Lines, array:new(length(Lines))). | |
fill(Lines, Arr) -> | |
Struct = lists:foldl(fun(Bin, {I, AccIn}) -> | |
AccOut = array:set(I, fill_row(Bin, array:new(string:length(Bin)), 0), AccIn), | |
{I+1, AccOut} | |
end, {0, Arr}, Lines), | |
element(2, Struct). | |
fill_row(<<>>, Arr, _) -> Arr; | |
fill_row(<<C:1/binary, T/binary>>, Arr, Iter) -> fill_row(T, array:set(Iter, C, Arr), Iter+1). | |
make_strings(XSize, YSize) -> | |
Bounds = {{0,0},{XSize-1,YSize-1}}, | |
L1 = range(0, YSize, fun(I) -> make_line(fun horizontal/2, {0,I}, Bounds) end), | |
L2 = range(0, XSize, fun(I) -> make_line(fun vertical/2, {I,0}, Bounds) end), | |
L3 = range(0, YSize, fun(I) -> make_line(fun diagonal_down/2, {0,I}, Bounds) end), | |
L4 = range(1, XSize, fun(I) -> make_line(fun diagonal_down/2, {I,0}, Bounds) end), | |
L5 = range(0, YSize, fun(I) -> make_line(fun diagonal_up/2, {0,I}, Bounds) end), | |
L6 = range(1, XSize, fun(I) -> make_line(fun diagonal_up/2, {I,YSize-1}, Bounds) end), | |
lists:append(L1, lists:append(L2, lists:append(L3, lists:append(L4, lists:append(L5, L6))))). | |
find_x_mas(XSize, YSize) -> | |
L = range(1, YSize-1, fun(Y) -> | |
range(1, XSize-1, fun(X) -> | |
test_x_mas(lookup({X,Y}), X, Y) | |
end) | |
end), | |
lists:flatten(L). | |
test_x_mas(<<"A">>, X, Y) -> | |
case {lookup({X-1,Y-1}), lookup({X+1,Y-1}), lookup({X-1,Y+1}), lookup({X+1,Y+1})} of | |
{<<"M">>, <<"M">>, <<"S">>, <<"S">>} -> 1; | |
{<<"S">>, <<"S">>, <<"M">>, <<"M">>} -> 1; | |
{<<"M">>, <<"S">>, <<"M">>, <<"S">>} -> 1; | |
{<<"S">>, <<"M">>, <<"S">>, <<"M">>} -> 1; | |
_ -> 0 | |
end; | |
test_x_mas(_, _, _) -> 0. | |
lookup({X,Y}) when is_integer(X), is_integer(Y) -> lookup({X,Y}, persistent_term:get(?MODULE)). | |
lookup({X,Y}, Arr) when is_integer(X), is_integer(Y) -> | |
array:get(X, array:get(Y, Arr)). | |
test_binary(Bin) -> test_binary(Bin, 0). | |
test_binary(<<>>, Acc) -> Acc; | |
test_binary(<<"XMAS", _/binary>> = <<_:1/binary, T/binary>>, Acc) -> test_binary(T, Acc + 1); | |
test_binary(<<"SAMX", _/binary>> = <<_:1/binary, T/binary>>, Acc) -> test_binary(T, Acc + 1); | |
test_binary(<<_:1/binary, T/binary>>, Acc) -> test_binary(T, Acc). | |
range(A, B, Func) -> range(A, B, Func, []). | |
range(A, B, _, Acc) when A == B -> lists:reverse(Acc); | |
range(A, B, Func, Acc) when A < B -> range(A+1, B, Func, [Func(A) | Acc]); | |
range(A, B, Func, Acc) when A > B -> range(A-1, B, Func, [Func(A) | Acc]). | |
make_line(Transform, Point, Bounds) -> | |
make_line(Transform, Point, Bounds, 0, <<>>). | |
make_line(Transform, Point, Bounds, I, Bin) -> | |
Char = lookup(Point), | |
Updated = <<Bin/binary, Char/binary>>, | |
case Transform(Point, Bounds) of | |
oob -> Updated; | |
NextPoint -> make_line(Transform, NextPoint, Bounds, I+1, Updated) | |
end. | |
vertical({X,Y}, {{_MinX,_MinY},{_MaxX,MaxY}}) -> | |
case Y+1 > MaxY of | |
true -> oob; | |
false -> {X, Y+1} | |
end. | |
horizontal({X,Y}, {{_MinX,_MinY},{MaxX,_MaxY}}) -> | |
case X+1 > MaxX of | |
true -> oob; | |
false -> {X+1, Y} | |
end. | |
diagonal_down({X,Y}, {{_MinX,_MinY},{MaxX,MaxY}}) -> | |
case {X+1 > MaxX, Y+1 > MaxY} of | |
{true, _} -> oob; | |
{_, true} -> oob; | |
_ -> {X+1,Y+1} | |
end. | |
diagonal_up({X,Y}, {{_MinX,MinY},{MaxX,_MaxY}}) -> | |
case {X+1 > MaxX, Y-1 < MinY} of | |
{true, _} -> oob; | |
{_, true} -> oob; | |
_ -> {X+1,Y-1} | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment