-module(gleamy_structures@heap@leftist_heap). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([new/1, find_min/1, insert/2, delete_min/1]). -export_type([t/1, heap/1]). -type t(FJS) :: e | {t, integer(), FJS, t(FJS), t(FJS)}. -opaque heap(FJT) :: {heap, t(FJT), fun((FJT, FJT) -> gleam@order:order())}. -spec new(fun((FJU, FJU) -> gleam@order:order())) -> heap(FJU). new(Compare) -> {heap, e, Compare}. -spec find_min(heap(FJZ)) -> {ok, FJZ} | {error, nil}. find_min(Heap) -> case erlang:element(2, Heap) of {t, _, X, _, _} -> {ok, X}; e -> {error, nil} end. -spec make(FLG, t(FLG), t(FLG)) -> t(FLG). make(X, A, B) -> Rank_a = case A of {t, R, _, _, _} -> R; e -> 0 end, Rank_b = case B of {t, R@1, _, _, _} -> R@1; e -> 0 end, case Rank_a < Rank_b of true -> {t, Rank_a + 1, X, B, A}; _ -> {t, Rank_b + 1, X, A, B} end. -spec merge(t(FKI), t(FKI), fun((FKI, FKI) -> gleam@order:order())) -> t(FKI). merge(H1, H2, Compare) -> case {H1, H2} of {H, e} -> H; {e, H@1} -> H@1; {{t, _, X, A1, B1}, {t, _, Y, A2, B2}} -> case Compare(X, Y) of gt -> make(Y, A2, merge(H1, B2, Compare)); _ -> make(X, A1, merge(B1, H2, Compare)) end end. -spec insert(heap(FJW), FJW) -> heap(FJW). insert(Heap, Item) -> {heap, merge( {t, 1, Item, e, e}, erlang:element(2, Heap), erlang:element(3, Heap) ), erlang:element(3, Heap)}. -spec delete_min(heap(FKD)) -> {ok, {FKD, heap(FKD)}} | {error, nil}. delete_min(Heap) -> case erlang:element(2, Heap) of {t, _, X, A, B} -> {ok, {X, {heap, merge(A, B, erlang:element(3, Heap)), erlang:element(3, Heap)}}}; e -> {error, nil} end.