%% to compile: erlc day3A.erl %% to run: erl -noshell -s day3 solve %% -module(day9). -export ([solve/0, solve/1, solve/2]). -export ([read_input/0]). solve() -> solve(['1']), solve(['2']), init:stop(). solve(A) -> solve(A, read_input()). solve(['1'], D) -> io:format("The solution to ~p puzzle1 is: ~p~n", [?MODULE, solve(1, D)]); solve(1, D) -> solution1(D); solve(['2'], D) -> io:format("The solution to ~p puzzle2 is: ~p~n", [?MODULE, solve(2, D)]); solve(2, D) -> solution2(D). read_input() -> {ok, IO} = file:open("input.txt", 'read'), Data = read_input(IO), file:close(IO), Data. read_input(IO) -> read_input(IO, []). read_input(IO, Input) -> case read_line(IO) of 'eof' -> Input; Line -> read_input(IO, Input ++ [Line]) end. read_line(IO) -> case file:read_line(IO) of 'eof' -> 'eof'; {ok, Line} -> [ X - $0 || X <- Line, [X] /= "\n"] end. solution1(Table) -> Low_points = low_points(Table), lists:foldl(fun(C, Acc) -> Acc + 1 + get_value(C, Table) end, 0, Low_points). solution2(Table) -> Low_points = low_points(Table), Basins = get_basins(Low_points, Table), [B1,B2,B3|_] = lists:sort(fun(A, B) -> length(A) > length(B) end, Basins), length(B1) * length(B2) * length(B3). get_basins(Low_points, Table) -> get_basins(Low_points, Table, []). get_basins([], _Table, Basins) -> Basins; get_basins([Low_point|Rest], Table, Basins) -> Basin = [Low_point|get_up_slopes([Low_point], Table)], get_basins(Rest, Table, [Basin|Basins]). low_points([H|_] = Table) -> X = length(H), Y = length(Table), Coords = lists:flatten([[{A,B} || A <- lists:seq(1,X)] || B <- lists:seq(1,Y)]), lists:filter(fun(C) -> is_low_point(C, Table) end, Coords). get_up_slopes(Coords, Table) -> get_up_slopes(Coords, Table, []). get_up_slopes([], _Table, Acc) -> Acc; get_up_slopes([{X, Y}|Rest], Table, Acc) -> V = get_value({X,Y}, Table), Neighbours = [{X+1, Y},{X-1, Y},{X, Y+1},{X, Y-1}], Up_slopes = lists:filter(fun({X1,Y1}) -> C = get_value({X1,Y1}, Table), C /= 9 andalso C > V end, Neighbours), get_up_slopes(lists:usort(Rest ++ Up_slopes), Table, lists:usort(Acc ++ Up_slopes)). is_low_point({X,Y}, Table) -> V = get_value({X,Y}, Table), V < get_value({X+1, Y}, Table) andalso V < get_value({X-1, Y}, Table) andalso V < get_value({X, Y+1}, Table) andalso V < get_value({X, Y-1}, Table). get_value({X,Y}, [H|_] = Table) when X == 0; Y == 0; Y > length(Table); X > length(H) -> 9; get_value({X,Y}, Table) -> lists:nth(X, lists:nth(Y, Table)).