Current section
Files
Jump to
Current section
Files
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(GTA) :: {tree,
gleam@option:option(tree_node(GTA)),
fun((GTA, GTA) -> gleam@order:order())}.
-type tree_node(GTB) :: {tree_node,
GTB,
integer(),
gleam@option:option(tree_node(GTB)),
gleam@option:option(tree_node(GTB))}.
-spec do_to_list(tree_node(GTF)) -> list(GTF).
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(GTC)) -> list(GTC).
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(GUH), tree_node(GUH), tree_node(GUH)) -> tree_node(GUH).
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(GTS), tree_node(GTS), GTS) -> gleam@option:option(tree_node(GTS)).
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(GTP), GTP) -> tree(GTP).
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(GUM) -> tree_node(GUM).
new_node(Value) ->
{tree_node, Value, 1, none, none}.
-spec do_add(tree(GTL), tree_node(GTL), GTL) -> tree_node(GTL).
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(GTI), GTI) -> tree(GTI).
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).