-module(gleamy@pairing_heap). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([new/1, find_min/1, insert/2, merge/2, delete_min/1]). -export_type([tree/1, heap/1]). -type tree(GSH) :: empty | {tree, GSH, list(tree(GSH))}. -opaque heap(GSI) :: {heap, tree(GSI), fun((GSI, GSI) -> gleam@order:order())}. -spec new(fun((GSJ, GSJ) -> gleam@order:order())) -> heap(GSJ). new(Compare) -> {heap, empty, Compare}. -spec find_min(heap(GSO)) -> {ok, GSO} | {error, nil}. find_min(Heap) -> case erlang:element(2, Heap) of {tree, X, _} -> {ok, X}; empty -> {error, nil} end. -spec merge_trees(tree(GTB), tree(GTB), fun((GTB, GTB) -> gleam@order:order())) -> tree(GTB). merge_trees(X, Y, Compare) -> case {X, Y} of {X@1, empty} -> X@1; {empty, Y@1} -> Y@1; {{tree, Xk, Xs}, {tree, Yk, Ys}} -> case Compare(Xk, Yk) of gt -> {tree, Yk, [X | Ys]}; _ -> {tree, Xk, [Y | Xs]} end end. -spec insert(heap(GSL), GSL) -> heap(GSL). insert(Heap, Key) -> {heap, merge_trees( {tree, Key, []}, erlang:element(2, Heap), erlang:element(3, Heap) ), erlang:element(3, Heap)}. -spec merge(heap(GSX), heap(GSX)) -> heap(GSX). merge(Heap1, Heap2) -> Compare = erlang:element(3, Heap1), {heap, merge_trees(erlang:element(2, Heap1), erlang:element(2, Heap2), Compare), Compare}. -spec merge_pairs(list(tree(GTF)), fun((GTF, GTF) -> gleam@order:order())) -> tree(GTF). merge_pairs(L, Compare) -> case L of [] -> empty; [H] -> H; [H1, H2 | Hs] -> merge_trees( merge_trees(H1, H2, Compare), merge_pairs(Hs, Compare), Compare ) end. -spec delete_min(heap(GSS)) -> {ok, {GSS, heap(GSS)}} | {error, nil}. delete_min(Heap) -> case erlang:element(2, Heap) of {tree, X, Xs} -> {ok, {X, {heap, merge_pairs(Xs, erlang:element(3, Heap)), erlang:element(3, Heap)}}}; empty -> {error, nil} end.