-module(gleeam_code@internal@tree_builder).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/gleeam_code/internal/tree_builder.gleam").
-export([tree_from_level_order/1, list_from_list/1]).
-export_type([tree_node/0, list_node/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(false).
-type tree_node() :: {tree_node,
integer(),
gleam@option:option(tree_node()),
gleam@option:option(tree_node())}.
-type list_node() :: {list_node, integer(), gleam@option:option(list_node())}.
-file("src/gleeam_code/internal/tree_builder.gleam", 64).
?DOC(false).
-spec take_next(list(gleam@option:option(integer()))) -> {gleam@option:option(integer()),
list(gleam@option:option(integer()))}.
take_next(Values) ->
case Values of
[] ->
{none, []};
[V | Rest] ->
{V, Rest}
end.
-file("src/gleeam_code/internal/tree_builder.gleam", 23).
?DOC(false).
-spec bfs_assign(
list(integer()),
list(gleam@option:option(integer())),
list({gleam@option:option(integer()), integer(), integer()}),
integer()
) -> {list({gleam@option:option(integer()), integer(), integer()}),
list(gleam@option:option(integer()))}.
bfs_assign(Queue, Remaining, Flat, Next_idx) ->
case Queue of
[] ->
{Flat, Remaining};
[Parent_idx | Rest_queue] ->
{Left_val, After_left} = take_next(Remaining),
{Right_val, After_right} = take_next(After_left),
{Left_idx, Flat2, Queue2, Idx2} = case Left_val of
none ->
{-1, Flat, Rest_queue, Next_idx};
{some, _} ->
{Next_idx,
lists:append(Flat, [{Left_val, -1, -1}]),
lists:append(Rest_queue, [Next_idx]),
Next_idx + 1}
end,
{Right_idx, Flat3, Queue3, Idx3} = case Right_val of
none ->
{-1, Flat2, Queue2, Idx2};
{some, _} ->
{Idx2,
lists:append(Flat2, [{Right_val, -1, -1}]),
lists:append(Queue2, [Idx2]),
Idx2 + 1}
end,
Flat4 = gleam@list:index_map(
Flat3,
fun(Entry, I) -> case I =:= Parent_idx of
true ->
{erlang:element(1, Entry), Left_idx, Right_idx};
false ->
Entry
end end
),
bfs_assign(Queue3, After_right, Flat4, Idx3)
end.
-file("src/gleeam_code/internal/tree_builder.gleam", 71).
?DOC(false).
-spec build_tree_from_flat(
list({gleam@option:option(integer()), integer(), integer()}),
integer()
) -> gleam@option:option(tree_node()).
build_tree_from_flat(Flat, Idx) ->
case Idx < 0 of
true ->
none;
false ->
case gleam@list:drop(Flat, Idx) of
[] ->
none;
[{none, _, _} | _] ->
none;
[{{some, Val}, Left_idx, Right_idx} | _] ->
Left = build_tree_from_flat(Flat, Left_idx),
Right = build_tree_from_flat(Flat, Right_idx),
{some, {tree_node, Val, Left, Right}}
end
end.
-file("src/gleeam_code/internal/tree_builder.gleam", 12).
?DOC(false).
-spec tree_from_level_order(list(gleam@option:option(integer()))) -> gleam@option:option(tree_node()).
tree_from_level_order(Values) ->
case Values of
[] ->
none;
[none | _] ->
none;
[{some, Root_val} | Rest] ->
{Flat, _} = bfs_assign([0], Rest, [{{some, Root_val}, -1, -1}], 1),
build_tree_from_flat(Flat, 0)
end.
-file("src/gleeam_code/internal/tree_builder.gleam", 97).
?DOC(false).
-spec do_list_from_list(list(integer())) -> list_node().
do_list_from_list(Values) ->
case Values of
[] ->
erlang:error(#{gleam_error => panic,
message => <<"unreachable: empty list"/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"gleeam_code/internal/tree_builder"/utf8>>,
function => <<"do_list_from_list"/utf8>>,
line => 99});
[X] ->
{list_node, X, none};
[X@1 | Rest] ->
{list_node, X@1, {some, do_list_from_list(Rest)}}
end.
-file("src/gleeam_code/internal/tree_builder.gleam", 90).
?DOC(false).
-spec list_from_list(list(integer())) -> gleam@option:option(list_node()).
list_from_list(Values) ->
case Values of
[] ->
none;
_ ->
{some, do_list_from_list(Values)}
end.