Packages

The A* search algorithm implemented in gleam

Current section

Files

Jump to
gleamstar src gleamstar.erl
Raw

src/gleamstar.erl

-module(gleamstar).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([a_star/3]).
-file("/home/keii/Coding/gleamstar/src/gleamstar.gleam", 37).
-spec infinity() -> integer().
infinity() ->
4294967296.
-file("/home/keii/Coding/gleamstar/src/gleamstar.gleam", 41).
-spec reconstruct_path(
gleam@dict:dict({integer(), integer()}, {integer(), integer()}),
{integer(), integer()},
list({integer(), integer()})
) -> list({integer(), integer()}).
reconstruct_path(Came_from, Current, Total_path) ->
case begin
_pipe = maps:keys(Came_from),
gleam@list:contains(_pipe, Current)
end of
true ->
reconstruct_path(
Came_from,
case gleam_stdlib:map_get(Came_from, Current) of
{ok, Value} ->
Value;
{error, _} ->
erlang:error(#{gleam_error => panic,
message => <<"unreachable"/utf8>>,
module => <<"gleamstar"/utf8>>,
function => <<"reconstruct_path"/utf8>>,
line => 55})
end,
gleam@list:prepend(Total_path, Current)
);
false ->
Total_path
end.
-file("/home/keii/Coding/gleamstar/src/gleamstar.gleam", 63).
-spec open_set_sorted_by_f_score(
list({integer(), integer()}),
gleam@dict:dict({integer(), integer()}, float())
) -> list({integer(), integer()}).
open_set_sorted_by_f_score(Open_set, F_score) ->
gleam@list:sort(
Open_set,
fun(A, B) ->
Ascore = case gleam_stdlib:map_get(F_score, A) of
{error, _} ->
_pipe = infinity(),
erlang:float(_pipe);
{ok, Score} ->
Score
end,
Bscore = case gleam_stdlib:map_get(F_score, B) of
{error, _} ->
_pipe@1 = infinity(),
erlang:float(_pipe@1);
{ok, Score@1} ->
Score@1
end,
case Ascore < Bscore of
true ->
lt;
false ->
case Ascore > Bscore of
true ->
gt;
false ->
eq
end
end
end
).
-file("/home/keii/Coding/gleamstar/src/gleamstar.gleam", 86).
-spec get_neighbors_of_current({integer(), integer()}) -> list({integer(),
integer()}).
get_neighbors_of_current(Current) ->
[{erlang:element(1, Current) - 1, erlang:element(2, Current) - 1},
{erlang:element(1, Current), erlang:element(2, Current) - 1},
{erlang:element(1, Current) + 1, erlang:element(2, Current) - 1},
{erlang:element(1, Current) - 1, erlang:element(2, Current)},
{erlang:element(1, Current) + 1, erlang:element(2, Current)},
{erlang:element(1, Current) - 1, erlang:element(2, Current) + 1},
{erlang:element(1, Current), erlang:element(2, Current) + 1},
{erlang:element(1, Current) + 1, erlang:element(2, Current) + 1}].
-file("/home/keii/Coding/gleamstar/src/gleamstar.gleam", 99).
-spec heuristic({integer(), integer()}, {integer(), integer()}) -> float().
heuristic(Neighbor, Goal) ->
_pipe = (gleam@int:absolute_value(
erlang:element(1, Neighbor) - erlang:element(1, Goal)
)
+ gleam@int:absolute_value(
erlang:element(2, Neighbor) - erlang:element(2, Goal)
)),
erlang:float(_pipe).
-file("/home/keii/Coding/gleamstar/src/gleamstar.gleam", 107).
-spec distance({integer(), integer()}, {integer(), integer()}) -> float().
distance(Goal, Current) ->
_pipe@2 = (begin
_pipe = gleam@int:power(
erlang:element(1, Goal) - erlang:element(1, Current),
2.0
),
gleam@result:unwrap(_pipe, +0.0)
end
+ begin
_pipe@1 = gleam@int:power(
erlang:element(2, Goal) - erlang:element(2, Current),
2.0
),
gleam@result:unwrap(_pipe@1, +0.0)
end),
_pipe@3 = gleam@float:square_root(_pipe@2),
gleam@result:unwrap(_pipe@3, +0.0).
-file("/home/keii/Coding/gleamstar/src/gleamstar.gleam", 116).
-spec handle_neighbors_of_current(
list({integer(), integer()}),
gleam@dict:dict({integer(), integer()}, float()),
gleam@dict:dict({integer(), integer()}, float()),
gleam@dict:dict({integer(), integer()}, {integer(), integer()}),
{integer(), integer()},
{integer(), integer()},
list({integer(), integer()}),
list({integer(), integer()})
) -> {ok, list({integer(), integer()})} | {error, nil}.
handle_neighbors_of_current(
Neighbors,
F_score,
G_score,
Came_from,
Current,
Goal,
Open_set,
Obstacles
) ->
case Neighbors of
[Neighbor | Rest] ->
gleam@bool:lazy_guard(
gleam@list:contains(Obstacles, Neighbor),
fun() ->
handle_neighbors_of_current(
Rest,
G_score,
F_score,
Came_from,
Current,
Goal,
Open_set,
Obstacles
)
end,
fun() ->
Tentative_g_score = (case gleam_stdlib:map_get(
G_score,
Current
) of
{ok, Value} ->
Value;
{error, _} ->
_pipe = infinity(),
erlang:float(_pipe)
end)
+ distance(Goal, Current),
case Tentative_g_score < case gleam_stdlib:map_get(
G_score,
Neighbor
) of
{ok, Value@1} ->
Value@1;
{error, _} ->
_pipe@1 = infinity(),
erlang:float(_pipe@1)
end of
true ->
Came_from@1 = gleam@dict:insert(
Came_from,
Neighbor,
Current
),
G_score@1 = gleam@dict:insert(
G_score,
Neighbor,
Tentative_g_score
),
F_score@1 = gleam@dict:insert(
F_score,
Neighbor,
Tentative_g_score + heuristic(Neighbor, Goal)
),
Open_set@1 = case gleam@list:contains(
Open_set,
Neighbor
) of
false ->
[Neighbor | Open_set];
true ->
Open_set
end,
handle_neighbors_of_current(
Rest,
F_score@1,
G_score@1,
Came_from@1,
Current,
Goal,
Open_set@1,
Obstacles
);
false ->
handle_neighbors_of_current(
Rest,
F_score,
G_score,
Came_from,
Current,
Goal,
Open_set,
Obstacles
)
end
end
);
[] ->
do_a_star(Open_set, F_score, G_score, Goal, Came_from, Obstacles)
end.
-file("/home/keii/Coding/gleamstar/src/gleamstar.gleam", 200).
-spec do_a_star(
list({integer(), integer()}),
gleam@dict:dict({integer(), integer()}, float()),
gleam@dict:dict({integer(), integer()}, float()),
{integer(), integer()},
gleam@dict:dict({integer(), integer()}, {integer(), integer()}),
list({integer(), integer()})
) -> {ok, list({integer(), integer()})} | {error, nil}.
do_a_star(Open_set, F_score, G_score, Goal, Came_from, Obstacles) ->
case gleam@list:is_empty(Open_set) of
false ->
gleam@result:'try'(
case open_set_sorted_by_f_score(Open_set, F_score) of
[Lowest | _] ->
{ok, Lowest};
_ ->
{error, nil}
end,
fun(Current) ->
gleam@bool:guard(
Current =:= Goal,
{ok, reconstruct_path(Came_from, Current, [])},
fun() ->
Open_set@1 = gleam@list:filter(
Open_set,
fun(Value) -> Value /= Current end
),
handle_neighbors_of_current(
get_neighbors_of_current(Current),
F_score,
G_score,
Came_from,
Current,
Goal,
Open_set@1,
Obstacles
)
end
)
end
);
true ->
{error, nil}
end.
-file("/home/keii/Coding/gleamstar/src/gleamstar.gleam", 23).
-spec a_star(
{integer(), integer()},
{integer(), integer()},
list({integer(), integer()})
) -> {ok, list({integer(), integer()})} | {error, nil}.
a_star(Start, Goal, Obstacles) ->
Open_set = [Start],
G_score = begin
_pipe = maps:new(),
gleam@dict:insert(_pipe, Start, +0.0)
end,
F_score = begin
_pipe@1 = maps:new(),
gleam@dict:insert(_pipe@1, Start, heuristic(Start, Goal))
end,
do_a_star(Open_set, F_score, G_score, Goal, maps:new(), Obstacles).