-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).