123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148open!Core_kernelmoduleArray=Base.ArraymoduleInt=Base.IntmoduleList=Base.ListmoduleOption=Base.OptionmoduleSequence=Base.SequencemoduleSexp=Base.SexpmoduleNode=structtype'at={value:'a;children:'atlist}endopenNodetype'at={cmp:'a->'a->int;length:int;heap:'aNode.toption}letcreate~cmp={cmp;length=0;heap=None}letmerge~cmp({value=e1;children=nl1}asn1)({value=e2;children=nl2}asn2)=ifcmpe1e2<0then{value=e1;children=n2::nl1}else{value=e2;children=n1::nl2};;letmerge_pairs~cmpt=letrecloopacct=matchtwith|[]->acc|[head]->head::acc|head::next1::next2->loop(merge~cmpheadnext1::acc)next2inmatchloop[]twith|[]->None|[h]->Someh|x::xs->Some(List.foldxs~init:x~f:(merge~cmp));;letadd{cmp;length;heap}e=letnew_node={value=e;children=[]}inletheap=matchheapwith|None->new_node|Someheap->merge~cmpnew_nodeheapin{cmp;length=length+1;heap=Someheap};;lettop_exnt=matcht.heapwith|None->failwith"Fheap.top_exn called on an empty heap"|Some{value;_}->value;;lettopt=trySome(top_exnt)with|_->None;;letpop_exn{cmp;length;heap}=matchheapwith|None->failwith"Heap.pop_exn called on an empty heap"|Some{value;children}->letnew_heap=merge_pairs~cmpchildreninlett'={cmp;length=length-1;heap=new_heap}invalue,t';;letpopt=trySome(pop_exnt)with|_->None;;letremove_topt=trylet_,t'=pop_exntinSomet'with|_->None;;letpop_iftf=matchtoptwith|None->None|Somev->iffvthenpoptelseNone;;letfoldt~init~f=letrecloopaccto_visit=matchto_visitwith|[]->acc|{value;children}::rest->letacc=faccvalueinletto_visit=List.unordered_appendchildrenrestinloopaccto_visitinmatcht.heapwith|None->init|Somenode->loopinit[node];;letlengtht=t.lengthmoduleC=Container.Make(structtypenonrec'at='atletfold=foldletiter=`Define_using_foldletlength=`Customlengthend)letis_emptyt=Option.is_nonet.heapletiter=C.iterletmem=C.memletmin_elt=C.min_eltletmax_elt=C.max_eltletfind=C.findletfind_map=C.find_mapletfor_all=C.for_allletexists=C.existsletsum=C.sumletcount=C.countletto_list=C.to_listletfold_result=C.fold_resultletfold_until=C.fold_until(* We could avoid the intermediate list here, but it doesn't seem like a big deal. *)letto_array=C.to_arrayletof_foldc~cmpfold=leth=create~cmpinfoldc~init:h~f:add;;letof_listl~cmp=of_foldl~cmpList.foldletof_arrayarr~cmp=of_foldarr~cmpArray.foldletsexp_of_tsexp_of_at=List.sexp_of_tsexp_of_a(to_listt)letto_sequencet=Sequence.unfold~init:t~f:pop