local a=require('pl.utils')local b=require('pl.types')local getmetatable,setmetatable,require=getmetatable,setmetatable,require;local c,d,e=table.sort,table.insert,table.remove;local f=math.min;local pairs,type,g,select,tostring=pairs,type,a.unpack,select,tostring;local h=a.function_arg;local i=a.assert_arg;local j={}local function k(l,m,n)local o=getmetatable(m)or n and require('pl.'..n)return o and setmetatable(l,o)or l end;local function p(q)return setmetatable(q,require('pl.List'))end;local function r(s)return setmetatable(s,require('pl.Map'))end;local function t(u,v)error(('argument %d is not %s'):format(u,v),3)end;local function w(u,x)if not b.is_indexable(x)then t(u,"indexable")end end;local function y(u,x)if not b.is_iterable(x)then t(u,"iterable")end end;local function z(u,x)if not b.is_writeable(x)then t(u,"writeable")end end;function j.update(A,B)z(1,A)y(2,B)for C,D in pairs(B)do A[C]=D end;return A end;function j.size(E)y(1,E)local F=0;for C in pairs(E)do F=F+1 end;return F end;function j.copy(E)y(1,E)local l={}for C,D in pairs(E)do l[C]=D end;return l end;local function G(E,H)if type(E)~='table'then return E end;if H[E]then return H[E]end;y(1,E)local l={}H[E]=l;local o=getmetatable(E)for C,D in pairs(E)do C=G(C,H)D=G(D,H)l[C]=D end;setmetatable(l,o)return l end;function j.deepcopy(E)return G(E,{})end;local I=math.abs;local function J(A,B,K,L,H)if H[A]and H[A][B]then return true end;local M=type(A)local N=type(B)if M~=N then return false end;if M~='table'then if M=='number'and L then return I(A-B)<L end;return A==B end;local o=getmetatable(A)if not K and o and o.__eq then return A==B end;for O in pairs(A)do if B[O]==nil then return false end end;for P in pairs(B)do if A[P]==nil then return false end end;H[A]=H[A]or{}H[A][B]=true;for O,Q in pairs(A)do local R=B[O]if not J(Q,R,K,L,H)then return false end end;return true end;function j.deepcompare(A,B,K,L)return J(A,B,K,L,{})end;function j.compare(A,B,S)w(1,A)w(2,B)if#A~=#B then return false end;S=h(3,S)for C=1,#A do if not S(A[C],B[C])then return false end end;return true end;function j.compare_no_order(A,B,S)w(1,A)w(2,B)if S then S=h(3,S)end;if#A~=#B then return false end;local T={}for F=1,#A do local x=A[F]local U;for V=1,#B do if not T[V]then local W;if S then W=S(x,B[V])else W=x==B[V]end;if W then U=V;break end end end;if not U then return false end;T[U]=true end;return true end;function j.find(E,x,u)w(1,E)u=u or 1;if u<0 then u=#E+u+1 end;for F=u,#E do if E[F]==x then return F end end;return nil end;function j.rfind(E,x,u)w(1,E)u=u or#E;if u<0 then u=#E+u+1 end;for F=u,1,-1 do if E[F]==x then return F end end;return nil end;function j.find_if(E,S,X)y(1,E)S=h(2,S)for C,D in pairs(E)do local Y=S(D,X)if Y then return C,Y end end;return nil end;function j.index_by(m,u)w(1,m)w(2,u)local l={}for F=1,#u do l[F]=m[u[F]]end;return k(l,m,'List')end;function j.map(Z,E,...)y(1,E)Z=h(1,Z)local l={}for C,D in pairs(E)do l[C]=Z(D,...)end;return k(l,E)end;function j.imap(Z,E,...)w(1,E)Z=h(1,Z)local l={}for F=1,#E do l[F]=Z(E[F],...)or false end;return k(l,E,'List')end;function j.map_named_method(_,E,...)a.assert_string(1,_)w(2,E)local l={}for F=1,#E do local x=E[F]local Z=x[_]l[F]=Z(x,...)end;return k(l,E,'List')end;function j.transform(Z,E,...)y(1,E)Z=h(1,Z)for C,D in pairs(E)do E[C]=Z(D,...)end end;function j.range(a0,a1,a2)local l;a2=a2 or 1;if a0==a1 then l={a0}elseif a0>a1 and a2>0 or a1>a0 and a2<0 then l={}else local C=1;l={}for F=a0,a1,a2 do l[C]=F;C=C+1 end end;return p(l)end;function j.map2(Z,A,B,...)y(1,A)y(2,B)Z=h(1,Z)local l={}for C,D in pairs(A)do l[C]=Z(D,B[C],...)end;return k(l,A,'List')end;function j.imap2(Z,A,B,...)w(2,A)w(3,B)Z=h(1,Z)local l,a3={},math.min(#A,#B)for F=1,a3 do l[F]=Z(A[F],B[F],...)end;return l end;function j.reduce(Z,E,a4)w(2,E)Z=h(1,Z)local a3=#E;if a3==0 then return a4 end;local l=a4 and Z(a4,E[1])or E[1]for F=2,a3 do l=Z(l,E[F])end;return l end;function j.foreach(E,Z,...)y(1,E)Z=h(2,Z)for C,D in pairs(E)do Z(D,C,...)end end;function j.foreachi(E,Z,...)w(1,E)Z=h(2,Z)for F=1,#E do Z(E[F],F,...)end end;function j.mapn(Z,...)Z=h(1,Z)local l={}local a5={...}local a6=1e40;for F=1,#a5 do a6=f(a6,#a5[F])end;for F=1,a6 do local a7,C={},1;for V=1,#a5 do a7[C]=a5[V][F]C=C+1 end;l[#l+1]=Z(g(a7))end;return l end;function j.pairmap(Z,E,...)y(1,E)Z=h(1,Z)local l={}for C,D in pairs(E)do local a8,a9=Z(C,D,...)if a9 then if l[a9]then if type(l[a9])=='table'then table.insert(l[a9],a8)else l[a9]={l[a9],a8}end else l[a9]=a8 end else l[#l+1]=a8 end end;return l end;local function aa(F,D)return F end;function j.keys(E)y(1,E)return p(j.pairmap(aa,E))end;local function ab(F,D)return D end;function j.values(E)y(1,E)return p(j.pairmap(ab,E))end;local function ac(F,D)return F,D end;function j.index_map(E)w(1,E)return r(j.pairmap(ac,E))end;local function ad(F,D)return true,D end;function j.makeset(E)w(1,E)return setmetatable(j.pairmap(ad,E),require('pl.Set'))end;function j.merge(A,B,ae)y(1,A)y(2,B)local l={}for C,D in pairs(A)do if ae or B[C]then l[C]=D end end;if ae then for C,D in pairs(B)do l[C]=D end end;return k(l,A,'Map')end;function j.union(A,B)return j.merge(A,B,true)end;function j.intersection(A,B)return j.merge(A,B,false)end;function j.difference(af,ag,ah)y(1,af)y(2,ag)local l={}for C,D in pairs(af)do if ag[C]==nil then l[C]=D end end;if ah then for C,D in pairs(ag)do if af[C]==nil then l[C]=D end end end;return k(l,af,'Map')end;function j.count_map(E,S)w(1,E)local l,ai={},{}S=h(2,S or'==')local a3=#E;for F=1,#E do local D=E[F]if not ai[D]then ai[D]=true;l[D]=1;for V=F+1,a3 do local aj=E[V]local ak=S(D,aj)if ak then l[D]=l[D]+1;ai[aj]=true end end end end;return r(l)end;function j.filter(E,al,X)w(1,E)al=h(2,al)local l,C={},1;for F=1,#E do local D=E[F]if al(D,X)then l[C]=D;C=C+1 end end;return k(l,E,'List')end;function j.zip(...)return j.mapn(function(...)return{...}end,...)end;local am;function am(an,ao,ap,aq,ar,as)ap=ap or 1;aq=aq or 1;local at;if not ar then ar=#ao;at=#ao else at=aq+f(ar-1,#ao-aq)end;if an==ao then if ap>aq and at>=ap then ao=j.sub(ao,aq,ar)aq=1;at=#ao end end;for F=aq,at do an[ap]=ao[F]ap=ap+1 end;if as then j.clear(an,ap)end;return an end;function j.icopy(an,ao,ap,aq,ar)w(1,an)w(2,ao)return am(an,ao,ap,aq,ar,true)end;function j.move(an,ao,ap,aq,ar)w(1,an)w(2,ao)return am(an,ao,ap,aq,ar,false)end;function j._normalize_slice(self,au,av)local aw=#self;if not au then au=1 end;if au<0 then au=aw+au+1 end;if not av then av=aw end;if av<0 then av=aw+1+av end;return au,av end;function j.sub(E,au,av)w(1,E)au,av=j._normalize_slice(E,au,av)local l={}for F=au,av do d(l,E[F])end;return k(l,E,'List')end;function j.set(E,x,ax,ay)w(1,E)ax,ay=ax or 1,ay or#E;if b.is_callable(x)then for F=ax,ay do E[F]=x(F)end else for F=ax,ay do E[F]=x end end end;function j.new(a3,x)local l={}j.set(l,x,1,a3)return l end;function j.clear(E,az)az=az or 1;for F=az,#E do e(E)end end;function j.insertvalues(E,...)i(1,E,'table')local aA,aB;if select('#',...)==1 then aA,aB=#E+1,...else aA,aB=...end;if#aB>0 then for F=#E,aA,-1 do E[F+#aB]=E[F]end;local aC=1-aA;for F=aA,aA+#aB-1 do E[F]=aB[F+aC]end end;return E end;function j.removevalues(E,ax,ay)i(1,E,'table')ax,ay=j._normalize_slice(E,ax,ay)for F=ax,ay do e(E,ax)end;return E end;local aD;aD=function(E,aE,aF)for C,D in pairs(E)do if D==aE then return C end end;for C,D in pairs(E)do if not aF[D]and type(D)=='table'then aF[D]=true;local l=aD(D,aE,aF)if l then l=tostring(l)if type(C)~='string'then return'['..C..']'..l else return C..'.'..l end end end end end;function j.search(E,aE,aG)y(1,E)local aF={[E]=true}if aG then for aH,D in pairs(aG)do aF[D]=true end end;return aD(E,aE,aF)end;function j.sort(E,aI)local aJ={}for C in pairs(E)do aJ[#aJ+1]=C end;c(aJ,aI)local F=0;return function()F=F+1;return aJ[F],E[aJ[F]]end end;function j.sortv(E,aI)aI=h(2,aI or'<')local aJ={}for C in pairs(E)do aJ[#aJ+1]=C end;c(aJ,function(aK,aL)return aI(E[aK],E[aL])end)local F=0;return function()F=F+1;return aJ[F],E[aJ[F]]end end;function j.readonly(E)local o={__index=E,__newindex=function(E,C,D)error("Attempt to modify read-only table",2)end,__pairs=function()return pairs(E)end,__ipairs=function()return ipairs(E)end,__len=function()return#E end,__metatable=false}return setmetatable({},o)end;return j