1 %% to compile: erlc day3A.erl
2 %% to run: erl -noshell -s day3 solve
6 -export ([solve/0, solve/1, solve/2]).
7 -export ([read_input/0]).
9 -compile([export_all]).
17 solve(A, read_input()).
20 io:format("The solution to ~p puzzle1 is: ~p~n", [?MODULE, solve(1, D)]);
24 io:format("The solution to ~p puzzle2 is: ~p~n", [?MODULE, solve(2, D)]);
29 {ok, IO} = file:open("input.txt", 'read'),
30 Data = read_input(IO),
37 read_input(IO, Input) ->
40 Line -> read_input(IO, Input ++ [Line])
44 case file:read_line(IO) of
46 {ok, Line} -> [ X - $0 || X <- Line, [X] /= "\n"]
50 Graph = astar:graph(Input),
51 astar:search(Graph, {0, 0}, {99, 99}).
54 Graph = astar:graph(Input),
55 astar:search(Graph, {0, 0}, {499, 499}).
57 coords([H|_] = Table) ->
60 lists:flatten([[{A,B} || A <- lists:seq(1,X)] || B <- lists:seq(1,Y)]).
63 %init_data({X,Y}, Table) when X =< 100 andalso Y =< 100 ->
64 % lists:nth(X, lists:nth(Y, Table));
65 init_data({X,Y}, Table) ->
76 D = lists:nth(X1, lists:nth(Y1, Table)),
77 D1 = (D + ((X-1) div 100) + ((Y-1) div 100)) rem 9,
83 %% io:format("~p -> ~p -> ~p~n", [{X,Y},{X1,Y1},{D,D2}]),
86 get_value({X,Y}, _Table) when X < 1; Y < 1; X > 500; Y > 500 -> 'invalid';
87 get_value({X,Y}, Table) ->
88 %% {C, V} = lists:keyfind(C, 1, Data),
100 D = lists:nth(X1, lists:nth(Y1, Table)),
101 D1 = (D + ((X-1) div 100) + ((Y-1) div 100)) rem 9,
107 %% io:format("~p -> ~p -> ~p~n", [{X,Y},{X1,Y1},{D,D2}]),
110 get_neighbors({X,Y}, Data) ->
111 Neigbours = [{X+1,Y},{X-1,Y},{X,Y+1},{X,Y-1}],
112 lists:filter(fun({_,E}) -> E /= 'invalid' end, [{C, get_value(C, Data)} || C <- Neigbours]).
114 build_graph(Coords, Data) ->
115 Graph = digraph:new(),
116 [digraph:add_vertex(Graph, C) || C <- Coords],
117 add_edges(Graph, Data, Coords).
119 make_coords(Coords, Loop) ->
120 [{X * Loop , Y * Loop} || {X,Y} <- Coords].
122 add_edges(Graph, Data, []) -> Graph;
123 add_edges(Graph, Data, [C|Rest]) ->
124 Neighbors = get_neighbors(C, Data),
125 [digraph:add_edge(Graph, C, X, V) || {X,V} <- Neighbors],
126 add_edges(Graph, Data, Rest).
128 dijkstra(Graph,Start_node_name) ->
130 Unvisited = gb_sets:new(),
131 Unvisited_nodes = gb_sets:insert({0,Start_node_name,root},Unvisited),
132 Paths_updated = loop_through_nodes(Graph,Paths,Unvisited_nodes),
136 loop_through_nodes(Graph,Paths,Unvisited_nodes) ->
137 %% We need this condition to stop looping through the Unvisited nodes if it is empty
138 case gb_sets:is_empty(Unvisited_nodes) of
140 {{Current_weight,Current_name,Previous_node}, Unvisited_nodes_updated} = gb_sets:take_smallest(Unvisited_nodes),
141 case dict:is_key(Current_name,Paths) of
143 Paths_updated = dict:store(Current_name,{Previous_node,Current_weight},Paths),
144 Out_edges = digraph:out_edges(Graph,Current_name),
145 Unvisited_nodes_updated_2 = loop_through_edges(Graph,Out_edges,Paths_updated,Unvisited_nodes_updated,Current_weight),
146 loop_through_nodes(Graph,Paths_updated,Unvisited_nodes_updated_2);
148 loop_through_nodes(Graph,Paths,Unvisited_nodes_updated)
154 loop_through_edges(Graph,[],Paths,Unvisited_nodes,Current_weight) ->
157 loop_through_edges(Graph,Edges,Paths,Unvisited_nodes,Current_weight) ->
158 [Current_edge|Rest_edges] = Edges,
159 {Current_edge,Current_node,Neighbour_node,Edge_weight} = digraph:edge(Graph,Current_edge),
160 case dict:is_key(Neighbour_node,Paths) of
162 Unvisited_nodes_updated = gb_sets:insert({Current_weight+Edge_weight,Neighbour_node,Current_node},Unvisited_nodes),
163 loop_through_edges(Graph,Rest_edges,Paths,Unvisited_nodes_updated,Current_weight);
165 loop_through_edges(Graph,Rest_edges,Paths,Unvisited_nodes,Current_weight)