re-organise repo
This commit is contained in:
166
2021/day15/day15.erl
Normal file
166
2021/day15/day15.erl
Normal file
@@ -0,0 +1,166 @@
|
||||
%% to compile: erlc day3A.erl
|
||||
%% to run: erl -noshell -s day3 solve
|
||||
%%
|
||||
-module(day15).
|
||||
|
||||
-export ([solve/0, solve/1, solve/2]).
|
||||
-export ([read_input/0]).
|
||||
|
||||
-compile([export_all]).
|
||||
|
||||
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(Input) ->
|
||||
Graph = astar:graph(Input),
|
||||
astar:search(Graph, {0, 0}, {99, 99}).
|
||||
|
||||
solution2(Input) ->
|
||||
Graph = astar:graph(Input),
|
||||
astar:search(Graph, {0, 0}, {499, 499}).
|
||||
|
||||
coords([H|_] = Table) ->
|
||||
X = length(H),
|
||||
Y = length(Table),
|
||||
lists:flatten([[{A,B} || A <- lists:seq(1,X)] || B <- lists:seq(1,Y)]).
|
||||
|
||||
|
||||
%init_data({X,Y}, Table) when X =< 100 andalso Y =< 100 ->
|
||||
% lists:nth(X, lists:nth(Y, Table));
|
||||
init_data({X,Y}, Table) ->
|
||||
X1 =
|
||||
case (X rem 100) of
|
||||
0 -> 100;
|
||||
A -> A
|
||||
end,
|
||||
Y1 =
|
||||
case (Y rem 100) of
|
||||
0 -> 100;
|
||||
B -> B
|
||||
end,
|
||||
D = lists:nth(X1, lists:nth(Y1, Table)),
|
||||
D1 = (D + ((X-1) div 100) + ((Y-1) div 100)) rem 9,
|
||||
D2 =
|
||||
case D1 of
|
||||
0 -> 9;
|
||||
C -> C
|
||||
end,
|
||||
%% io:format("~p -> ~p -> ~p~n", [{X,Y},{X1,Y1},{D,D2}]),
|
||||
D2.
|
||||
|
||||
get_value({X,Y}, _Table) when X < 1; Y < 1; X > 500; Y > 500 -> 'invalid';
|
||||
get_value({X,Y}, Table) ->
|
||||
%% {C, V} = lists:keyfind(C, 1, Data),
|
||||
%% V.
|
||||
X1 =
|
||||
case (X rem 100) of
|
||||
0 -> 100;
|
||||
A -> A
|
||||
end,
|
||||
Y1 =
|
||||
case (Y rem 100) of
|
||||
0 -> 100;
|
||||
B -> B
|
||||
end,
|
||||
D = lists:nth(X1, lists:nth(Y1, Table)),
|
||||
D1 = (D + ((X-1) div 100) + ((Y-1) div 100)) rem 9,
|
||||
D2 =
|
||||
case D1 of
|
||||
0 -> 9;
|
||||
C -> C
|
||||
end,
|
||||
%% io:format("~p -> ~p -> ~p~n", [{X,Y},{X1,Y1},{D,D2}]),
|
||||
D2.
|
||||
|
||||
get_neighbors({X,Y}, Data) ->
|
||||
Neigbours = [{X+1,Y},{X-1,Y},{X,Y+1},{X,Y-1}],
|
||||
lists:filter(fun({_,E}) -> E /= 'invalid' end, [{C, get_value(C, Data)} || C <- Neigbours]).
|
||||
|
||||
build_graph(Coords, Data) ->
|
||||
Graph = digraph:new(),
|
||||
[digraph:add_vertex(Graph, C) || C <- Coords],
|
||||
add_edges(Graph, Data, Coords).
|
||||
|
||||
make_coords(Coords, Loop) ->
|
||||
[{X * Loop , Y * Loop} || {X,Y} <- Coords].
|
||||
|
||||
add_edges(Graph, Data, []) -> Graph;
|
||||
add_edges(Graph, Data, [C|Rest]) ->
|
||||
Neighbors = get_neighbors(C, Data),
|
||||
[digraph:add_edge(Graph, C, X, V) || {X,V} <- Neighbors],
|
||||
add_edges(Graph, Data, Rest).
|
||||
|
||||
dijkstra(Graph,Start_node_name) ->
|
||||
Paths = dict:new(),
|
||||
Unvisited = gb_sets:new(),
|
||||
Unvisited_nodes = gb_sets:insert({0,Start_node_name,root},Unvisited),
|
||||
Paths_updated = loop_through_nodes(Graph,Paths,Unvisited_nodes),
|
||||
Paths_updated.
|
||||
|
||||
|
||||
loop_through_nodes(Graph,Paths,Unvisited_nodes) ->
|
||||
%% We need this condition to stop looping through the Unvisited nodes if it is empty
|
||||
case gb_sets:is_empty(Unvisited_nodes) of
|
||||
false ->
|
||||
{{Current_weight,Current_name,Previous_node}, Unvisited_nodes_updated} = gb_sets:take_smallest(Unvisited_nodes),
|
||||
case dict:is_key(Current_name,Paths) of
|
||||
false ->
|
||||
Paths_updated = dict:store(Current_name,{Previous_node,Current_weight},Paths),
|
||||
Out_edges = digraph:out_edges(Graph,Current_name),
|
||||
Unvisited_nodes_updated_2 = loop_through_edges(Graph,Out_edges,Paths_updated,Unvisited_nodes_updated,Current_weight),
|
||||
loop_through_nodes(Graph,Paths_updated,Unvisited_nodes_updated_2);
|
||||
true ->
|
||||
loop_through_nodes(Graph,Paths,Unvisited_nodes_updated)
|
||||
end;
|
||||
true ->
|
||||
Paths
|
||||
end.
|
||||
|
||||
loop_through_edges(Graph,[],Paths,Unvisited_nodes,Current_weight) ->
|
||||
Unvisited_nodes;
|
||||
|
||||
loop_through_edges(Graph,Edges,Paths,Unvisited_nodes,Current_weight) ->
|
||||
[Current_edge|Rest_edges] = Edges,
|
||||
{Current_edge,Current_node,Neighbour_node,Edge_weight} = digraph:edge(Graph,Current_edge),
|
||||
case dict:is_key(Neighbour_node,Paths) of
|
||||
false ->
|
||||
Unvisited_nodes_updated = gb_sets:insert({Current_weight+Edge_weight,Neighbour_node,Current_node},Unvisited_nodes),
|
||||
loop_through_edges(Graph,Rest_edges,Paths,Unvisited_nodes_updated,Current_weight);
|
||||
true ->
|
||||
loop_through_edges(Graph,Rest_edges,Paths,Unvisited_nodes,Current_weight)
|
||||
end.
|
||||
Reference in New Issue
Block a user