123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476(* Copyright 2003 Yamagata Yoriyuki. distributed with LGPL *)(* Modified by Edgar Friendly <thelema314@gmail.com> *)(* Modified by Philippe Veber <philippe.veber@gmail.com> *)(* Copyright 2003 Yamagata Yoriyuki. distributed with LGPL *)(* Modified by Edgar Friendly <thelema314@gmail.com> *)moduleInt=IntopenCFStreammoduleBatAvlTree=structtype'atree=|Empty|Nodeof'atree*'a*'atree*int(* height *)letempty=Emptyletis_empty=function|Empty->true|Node_->falseletsingleton_treex=Node(Empty,x,Empty,1)letleft_branch=function|Empty->raiseCaml.Not_found|Node(l,_,_,_)->lletright_branch=function|Empty->raiseCaml.Not_found|Node(_,_,r,_)->rletroot=function|Empty->raiseCaml.Not_found|Node(_,v,_,_)->vletheight=function|Empty->0|Node(_,_,_,h)->hletcreatelvr=leth'=1+Int.max(heightl)(heightr)inassert(abs(heightl-heightr)<2);Node(l,v,r,h')(* Assume |hl - hr| < 3 *)letballvr=lethl=heightlinlethr=heightrinifhl>=hr+2thenmatchlwith|Empty->assertfalse|Node(ll,lv,lr,_)->ifheightll>=heightlrthencreatelllv(createlrvr)elsematchlrwith|Empty->assertfalse|Node(lrl,lrv,lrr,_)->create(createlllvlrl)lrv(createlrrvr)elseifhr>=hl+2thenmatchrwith|Empty->assertfalse|Node(rl,rv,rr,_)->ifheightrr>=heightrlthencreate(createlvrl)rvrrelsematchrlwith|Empty->assertfalse|Node(rll,rlv,rlr,_)->create(createlvrll)rlv(createrlrrvrr)elsecreatelvrletrecadd_leftv=function|Empty->Node(Empty,v,Empty,1)|Node(l,v',r,_)->bal(add_leftvl)v'rletrecadd_rightv=function|Empty->Node(Empty,v,Empty,1)|Node(l,v',r,_)->ballv'(add_rightvr)(* No assumption of height of l and r. *)letrecmake_treelvr=matchl,rwith|Empty,_->add_leftvr|_,Empty->add_rightvl|Node(ll,lv,lr,lh),Node(rl,rv,rr,rh)->iflh>rh+1thenballllv(make_treelrvr)elseifrh>lh+1thenbal(make_treelvrl)rvrrelsecreatelvr(* Utilities *)letrecsplit_leftmost=function|Empty->raiseCaml.Not_found|Node(Empty,v,r,_)->(v,r)|Node(l,v,r,_)->letv0,l'=split_leftmostlin(v0,make_treel'vr)letrecsplit_rightmost=function|Empty->raiseCaml.Not_found|Node(l,v,Empty,_)->(v,l)|Node(l,v,r,_)->letv0,r'=split_rightmostrin(v0,make_treelvr')letrecconcatt1t2=matcht1,t2with|Empty,_->t2|_,Empty->t1|Node(l1,v1,r1,h1),Node(l2,v2,r2,h2)->ifh1<h2thenmake_tree(concatt1l2)v2r2elsemake_treel1v1(concatr1t2)letreciterproc=function|Empty->()|Node(l,v,r,_)->iterprocl;procv;iterprocrletrecfoldftinit=matchtwith|Empty->init|Node(l,v,r,_)->letx=foldflinitinletx=fvxinfoldfrx(* FIXME: this is nlog n because of the left nesting of appends *)letrecto_stream=function|Empty->Stream.empty()|Node(l,v,r,_)->Stream.append(Stream.append(Stream.of_lazy(lazy(to_streaml)))(Stream.singletonv))(Stream.of_lazy(lazy(to_streamr)))endincludeBatAvlTreetypet=(int*int)treeletrecmems(n:int)=ifis_emptysthenfalseelseletv1,v2=rootsinifn<v1thenmem(left_branchs)nelseifv1<=n&&n<=v2thentrueelsemem(right_branchs)nletrecintersects_rangesij=ifi>jthenraise(Invalid_argument"iset_intersects_range");ifis_emptysthenfalseelseletv1,v2=rootsinifj<v1thenintersects_range(left_branchs)ijelseifv2<ithenintersects_range(right_branchs)ijelsetrueletrecaddsn=ifis_emptysthenmake_treeempty(n,n)emptyelselet(v1,v2)asv=rootsinlets0=left_branchsinlets1=right_branchsinifv1<>Int.min_value&&n<v1-1thenmake_tree(adds0n)vs1elseifv2<>Int.max_value&&n>v2+1thenmake_trees0v(adds1n)elseifn+1=v1thenifnot(is_emptys0)thenlet(u1,u2),s0'=split_rightmosts0inifu2<>Int.max_value&&u2+1=nthenmake_trees0'(u1,v2)s1elsemake_trees0(n,v2)s1elsemake_trees0(n,v2)s1elseifv2+1=nthenifnot(is_emptys1)thenlet(u1,u2),s1'=split_leftmosts1inifn<>Int.max_value&&n+1=u1thenmake_trees0(v1,u2)s1'elsemake_trees0(v1,n)s1elsemake_trees0(v1,n)s1elsesletrecfroms~n=ifis_emptysthenemptyelselet(v1,v2)asv=rootsinlets0=left_branchsinlets1=right_branchsinifn<v1thenmake_tree(froms0~n)vs1elseifn>v2thenfroms1~nelsemake_treeempty(n,v2)s1letafters~n=ifn=Int.max_valuethenemptyelsefroms~n:(n+1)letrecuntils~n=ifis_emptysthenemptyelselet(v1,v2)asv=rootsinlets0=left_branchsinlets1=right_branchsinifn>v2thenmake_trees0v(untils1~n)elseifn<v1thenuntils0~nelsemake_trees0(v1,n)emptyletbefores~n=ifn=Int.min_valuethenemptyelseuntils~n:(n-1)letadd_rangesn1n2=ifn1>n2theninvalid_arg(Printf.sprintf"ISet.add_range - %d > %d"n1n2)elseletn1,l=ifn1=Int.min_valuethenn1,emptyelseletl=untils~n:(n1-1)inifis_emptylthenn1,emptyelselet(v1,v2),l'=split_rightmostlinifv2+1=n1thenv1,l'elsen1,linletn2,r=ifn2=Int.max_valuethenn2,emptyelseletr=froms~n:(n2+1)inifis_emptyrthenn2,emptyelselet(v1,v2),r'=split_leftmostrinifn2+1=v1thenv2,r'elsen2,rinmake_treel(n1,n2)rletsingletonn=singleton_tree(n,n)letrecremovesn=ifis_emptysthenemptyelselet(v1,v2)asv=rootsinlets1=left_branchsinlets2=right_branchsinifn<v1thenmake_tree(removes1n)vs2elseifn=v1thenifv1=v2thenconcats1s2elsemake_trees1(v1+1,v2)s2elseifn>v1&&n<v2thenlets=make_trees1(v1,n-1)emptyinmake_trees(n+1,v2)s2elseifn=v2thenmake_trees1(v1,v2-1)s2elsemake_trees1v(removes2n)letremove_rangesn1n2=ifn1>n2theninvalid_arg"ISet.remove_range"elseconcat(befores~n:n1)(afters~n:n2)letrecunions1s2=ifis_emptys1thens2elseifis_emptys2thens1elselets1,s2=ifheights1>heights2thens1,s2elses2,s1inletn1,n2=roots1inletl1=left_branchs1inletr1=right_branchs1inletl2=befores2~n:n1inletr2=afters2~n:n2inletn1,l=ifn1=Int.min_valuethenn1,emptyelseletl=unionl1l2inifis_emptylthenn1,lelselet(v1,v2),l'=split_rightmostlin(* merge left *)ifv2+1=n1thenv1,l'elsen1,linletn2,r=ifn1=Int.max_valuethenn2,emptyelseletr=unionr1r2inifis_emptyrthenn2,relselet(v1,v2),r'=split_leftmostrin(* merge right *)ifn2+1=v1thenv2,r'elsen2,rinmake_treel(n1,n2)r(*$= union & ~cmp:equal ~printer:(IO.to_string print)
(union (of_list [3,5]) (of_list [1,3])) (of_list [1,5])
(union (of_list [3,5]) (of_list [1,2])) (of_list [1,5])
(union (of_list [3,5]) (of_list [1,5])) (of_list [1,5])
(union (of_list [1,5]) (of_list [3,5])) (of_list [1,5])
(union (of_list [1,2]) (of_list [4,5])) (of_list [1,2;4,5])
*)letrecinters1s2=ifis_emptys1thenemptyelseifis_emptys2thenemptyelselets1,s2=ifheights1>heights2thens1,s2elses2,s1inletn1,n2=roots1inletl1=left_branchs1inletr1=right_branchs1inletl2=befores2~n:n1inletr2=afters2~n:n2inletm=until(froms2~n:n1)~n:n2inconcat(concat(interl1l2)m)(interr1r2)(*$= inter & ~cmp:equal ~printer:(IO.to_string print)
(inter (of_list [1,5]) (of_list [2,3])) (of_list [2,3])
(inter (of_list [1,4]) (of_list [2,6])) (of_list [2,4])
*)letreccompl_auxn1n2s=ifis_emptysthenadd_rangeemptyn1n2elseletv1,v2=rootsinletl=left_branchsinletr=right_branchsinletl=ifv1=Int.min_valuethenemptyelsecompl_auxn1(v1-1)linletr=ifv2=Int.max_valuethenemptyelsecompl_aux(v2+1)n2rinconcatlrletcompls=compl_auxInt.min_valueInt.max_valuesletdiffs1s2=inters1(compls2)letreccompare_auxx1x2=matchx1,x2with[],[]->0|`Sets::rest,x->ifis_emptysthencompare_auxrestx2elseletl=left_branchsinletv=rootsinletr=right_branchsincompare_aux(`Setl::`Rangev::`Setr::rest)x|_x,`Sets::rest->ifis_emptysthencompare_auxx1restelseletl=left_branchsinletv=rootsinletr=right_branchsincompare_auxx1(`Setl::`Rangev::`Setr::rest)|`Range((v1,v2))::rest1,`Range((v3,v4))::rest2->letsgn=Int.comparev1v3inifsgn<>0thensgnelseletsgn=Int.comparev2v4inifsgn<>0thensgnelsecompare_auxrest1rest2|[],_->~-1|_,[]->1letcompares1s2=compare_aux[`Sets1][`Sets2]letequals1s2=compares1s2=0letrecsubsets1s2=ifis_emptys1thentrueelseifis_emptys2thenfalseelseletv1,v2=roots2inletl2=left_branchs2inletr2=right_branchs2inletl1=befores1~n:v1inletr1=afters1~n:v2in(subsetl1l2)&&(subsetr1r2)letfold_ranges~init~f=BatAvlTree.fold(fun(n1,n2)x->fn1n2x)sinitletfolds~init~f=letrecgn1n2a=ifn1=n2thenfn1aelseg(n1+1)n2(fn1a)infold_range~f:gs~initletiters~f=folds~init:()~f:(funn()->fn)letiter_ranges~f=BatAvlTree.iter(fun(n1,n2)->fn1n2)sletfor_alls~f=letrectest_rangen1n2=ifn1=n2thenfn1elsefn1&&test_range(n1+1)n2inletrectest_sets=ifis_emptysthentrueelseletn1,n2=rootsintest_rangen1n2&&test_set(left_branchs)&&test_set(right_branchs)intest_sets(*$T for_all
for_all (fun x -> x < 10) (of_list [1,3;2,7])
not (for_all (fun x -> x = 5) (of_list [4,5]))
*)letexistss~f=letrectest_rangen1n2=ifn1=n2thenfn1elsefn1||test_range(n1+1)n2inletrectest_sets=ifis_emptysthenfalseelseletn1,n2=rootsintest_rangen1n2||test_set(left_branchs)||test_set(right_branchs)intest_sets(*$T exists
exists (fun x -> x = 5) (of_list [1,10])
not (exists (fun x -> x = 5) (of_list [1,3;7,10]))
*)letfilter_rangepn1n2a=letrecloopn1n2a=functionNone->ifn1=n2thenmake_treea(n1,n1)emptyelseloop(n1+1)n2a(ifpn1thenSomen1elseNone)|Somev1asx->ifn1=n2thenmake_treea(v1,n1)emptyelseifpn1thenloop(n1+1)n2axelseloop(n1+1)n2(make_treea(v1,n1-1)empty)Noneinloopn1n2aNoneletfilters~f=fold_ranges~f:(filter_rangef)~init:emptyletpartition_rangepn1n2(a,b)=letrecloopn1n2acc=letacc=leta,b,(v,n)=accinifBool.(pn1=v)thenaccelseifvthen(make_treea(n,n1)empty,b,(notv,n1))else(a,make_treeb(n,n1)empty,(notv,n1))inifn1=n2thenleta,b,(v,n)=accinifvthen(make_treea(n,n1)empty,b)else(a,make_treeb(n,n1)empty)elseloop(n1+1)n2accinloopn1n2(a,b,(pn1,n1))letpartitions~f=fold_range~f:(partition_rangef)s~init:(empty,empty)letcardinals=fold_range~f:(funn1n2c->c+n2-n1+1)s~init:0(*$T cardinal
cardinal (of_list [1,3;5,9]) = 8
*)letrev_rangess=fold_range~f:(funn1n2a->(n1,n2)::a)s~init:[]letrecburst_rangen1n2a=ifn1=n2thenn1::aelseburst_rangen1(n2-1)(n2::a)letelementss=letfa(n1,n2)=burst_rangen1n2ainList.fold_left~f~init:[](rev_rangess)(*$Q ranges;of_list
(Q.list (Q.pair Q.int Q.int)) (fun l -> \
let norml = List.map (fun (x,y) -> if x < y then (x,y) else (y,x)) l in \
let set = of_list norml in \
equal set (ranges set |> of_list) \
)
*)letrangess=List.rev(rev_rangess)letmin_elts=let(n,_),_=split_leftmostsinnletmax_elts=let(_,n),_=split_rightmostsinnletchooses=fst(roots)letof_listl=List.fold_left~f:(funs(lo,hi)->add_rangeslohi)~init:emptylletof_streame=Stream.fold~f:(funs(lo,hi)->add_rangeslohi)~init:emptye