Packages

A collection of Gleam utilities all written in pure gleam

Current section

Files

Jump to
glib src glib@tree.erl
Raw

src/glib@tree.erl

-module(glib@tree).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([to_list/1, size/1, is_balanced/1, remove/2, add/2, main/0]).
-export_type([tree/1, tree_node/1]).
-opaque tree(GPP) :: {tree,
gleam@option:option(tree_node(GPP)),
fun((GPP, GPP) -> gleam@order:order())}.
-type tree_node(GPQ) :: {tree_node,
GPQ,
integer(),
gleam@option:option(tree_node(GPQ)),
gleam@option:option(tree_node(GPQ))}.
-spec do_to_list(tree_node(GPU)) -> list(GPU).
do_to_list(Tree) ->
gleam@list:concat([case erlang:element(4, Tree) of
none ->
[];
{some, Node} ->
do_to_list(Node)
end, gleam@list:repeat(
erlang:element(2, Tree),
erlang:element(3, Tree)
), case erlang:element(5, Tree) of
none ->
[];
{some, Node@1} ->
do_to_list(Node@1)
end]).
-spec to_list(tree(GPR)) -> list(GPR).
to_list(Tree) ->
case erlang:element(2, Tree) of
none ->
[];
{some, Node} ->
do_to_list(Node)
end.
-spec get_size(integer(), gleam@option:option(tree_node(any()))) -> integer().
get_size(Size, Node) ->
case Node of
none ->
Size + 1;
{some, Tn} ->
get_size(Size, erlang:element(4, Tn)) + get_size(
Size,
erlang:element(5, Tn)
)
end.
-spec size(tree(any())) -> integer().
size(Tree) ->
get_size(0, erlang:element(2, Tree)).
-spec get_height(integer(), gleam@option:option(tree_node(any()))) -> integer().
get_height(Height, Node) ->
case Node of
none ->
Height;
{some, Tn} ->
gleam@int:max(
get_height(Height + 1, erlang:element(4, Tn)),
get_height(Height + 1, erlang:element(5, Tn))
)
end.
-spec is_balanced(tree(any())) -> boolean().
is_balanced(Tree) ->
case erlang:element(2, Tree) of
none ->
true;
{some, Root} ->
Left = get_height(1, erlang:element(4, Root)),
Right = get_height(1, erlang:element(5, Root)),
gleam@int:absolute_value(Left - Right) =< gleam@result:unwrap(
gleam@int:modulo(size(Tree) - 1, 2),
0
)
end.
-spec move_node(tree(GQW), tree_node(GQW), tree_node(GQW)) -> tree_node(GQW).
move_node(Tree, Root_node, Moved_node) ->
case (erlang:element(3, Tree))(
erlang:element(2, Root_node),
erlang:element(2, Moved_node)
) of
eq ->
erlang:error(#{gleam_error => panic,
message => <<"panic expression evaluated"/utf8>>,
module => <<"glib/tree"/utf8>>,
function => <<"move_node"/utf8>>,
line => 177});
lt ->
case erlang:element(4, Root_node) of
none ->
erlang:setelement(4, Root_node, {some, Moved_node});
{some, Lnode} ->
move_node(Tree, Lnode, Moved_node)
end;
gt ->
case erlang:element(5, Root_node) of
none ->
erlang:setelement(5, Root_node, {some, Moved_node});
{some, Rnode} ->
move_node(Tree, Rnode, Moved_node)
end
end.
-spec do_remove(tree(GQH), tree_node(GQH), GQH) -> gleam@option:option(tree_node(GQH)).
do_remove(Tree, Node, Value) ->
case (erlang:element(3, Tree))(Value, erlang:element(2, Node)) of
eq ->
case erlang:element(3, Node) > 1 of
true ->
{some,
erlang:setelement(3, Node, erlang:element(3, Node) - 1)};
false ->
case erlang:element(4, Node) of
none ->
case erlang:element(5, Node) of
none ->
none;
{some, _} ->
erlang:element(5, Node)
end;
{some, Lnode} ->
case erlang:element(5, Node) of
none ->
erlang:element(4, Node);
{some, Rnode} ->
{some, move_node(Tree, Lnode, Rnode)}
end
end
end;
lt ->
case erlang:element(4, Node) of
none ->
{some, Node};
{some, Leftnode} ->
{some,
erlang:setelement(
4,
Node,
do_remove(Tree, Leftnode, Value)
)}
end;
gt ->
case erlang:element(5, Node) of
none ->
{some, Node};
{some, Rightnode} ->
{some,
erlang:setelement(
5,
Node,
do_remove(Tree, Rightnode, Value)
)}
end
end.
-spec remove(tree(GQE), GQE) -> tree(GQE).
remove(Tree, Value) ->
case erlang:element(2, Tree) of
none ->
Tree;
{some, Root} ->
erlang:setelement(2, Tree, do_remove(Tree, Root, Value))
end.
-spec new_node(GRB) -> tree_node(GRB).
new_node(Value) ->
{tree_node, Value, 1, none, none}.
-spec do_add(tree(GQA), tree_node(GQA), GQA) -> tree_node(GQA).
do_add(Tree, Node, Value) ->
case (erlang:element(3, Tree))(Value, erlang:element(2, Node)) of
eq ->
erlang:setelement(3, Node, erlang:element(3, Node) + 1);
lt ->
case erlang:element(4, Node) of
none ->
erlang:setelement(4, Node, {some, new_node(Value)});
{some, Leftnode} ->
erlang:setelement(
4,
Node,
{some, do_add(Tree, Leftnode, Value)}
)
end;
gt ->
case erlang:element(5, Node) of
none ->
erlang:setelement(5, Node, {some, new_node(Value)});
{some, Rightnode} ->
erlang:setelement(
5,
Node,
{some, do_add(Tree, Rightnode, Value)}
)
end
end.
-spec add(tree(GPX), GPX) -> tree(GPX).
add(Tree, Value) ->
case erlang:element(2, Tree) of
none ->
erlang:setelement(2, Tree, {some, new_node(Value)});
{some, Root} ->
erlang:setelement(2, Tree, {some, do_add(Tree, Root, Value)})
end.
-spec main() -> nil.
main() ->
_pipe = {tree, none, fun gleam@int:compare/2},
_pipe@1 = to_list(_pipe),
_pipe@2 = gleam@string:inspect(_pipe@1),
gleam@io:println(_pipe@2),
_pipe@3 = {tree, none, fun gleam@int:compare/2},
_pipe@4 = add(_pipe@3, 123),
_pipe@5 = to_list(_pipe@4),
_pipe@6 = gleam@string:inspect(_pipe@5),
gleam@io:println(_pipe@6).