'''
Created on 10.10.2012
@author: pycz
'''
import copy
class Num:
def __init__(self):
self.num='#'
self.next=None
class LongNum(object):
def __init__(self,ln=0):
self.head=Num()
self.sign='+'
self._fill(str(ln))
def _addFirst(self,el):
x=Num()
x.num=el
x.next=self.head.next
self.head.next=x
def _del(self):
self.head.next=None
self.sign="+"
def _fill(self,ln):
ln=str(ln)
self._del()
self.sign="+"
if ln and ln[0]=='-':
self.sign='-'
ln=ln[1:]
if ln and ln[0]=='+':
ln=ln[1:]
for l in ln:
x=int(l)
self._addFirst(x)
if ln:
self._reduce_zeros()
self._isZero()
def _isZero(self):
if self.head.next and self.head.next.num==0 and self.head.next.next==None:
self.sign='+'
return True
else:
return False
def __str__(self):
res=""
p=self.head.next
while p!=None:
res=str(p.num)+res
p=p.next
if not self._isZero() and self.sign!='+':
res='-'+res
return res
def empty(self):
return not self.head.next
def __neg__(self):
res=copy.deepcopy(self)
if self._isZero():
return res
if self.sign=='+':
res.sign="-"
else:
res.sign="+"
return res
def __abs__(self):
res=copy.deepcopy(self)
res.sign="+"
return res
def _simple_add(self,other):
'''
return simple a+b, no signs
'''
res=LongNum()
per=0
p1=self.head.next
p2=other.head.next
p3=res.head
while not (p1==None and p2==None):
if p1!=None and p2==None:
p3.next=Num()
p3=p3.next
p3.num=(p1.num+per)%10
per=(p1.num+per)/10
p1=p1.next
if p1==None and p2!=None:
p3.next=Num()
p3=p3.next
p3.num=(p2.num+per)%10
per=(p2.num+per)/10
p2=p2.next
if p1!=None and p2!=None:
p3.next=Num()
p3=p3.next
p3.num=(p2.num+per+p1.num)%10
per=(p2.num+per+p1.num)/10
p2=p2.next
p1=p1.next
if per!=0:
p3.next=Num()
p3=p3.next
p3.num=per
return res
def _reduce_zeros(self):
p=self.head.next
mark=None
while(p.next):
if(p.next.num!=0):
mark=p
p=p.next
if mark:
mark.next.next=None
else:
self.head.next.next=None
def _simple_sub(self,other):
'''
return simple a-b, no signs, a>=b
'''
res=LongNum()
per=0
p1=self.head.next
p2=other.head.next
p3=res.head
while p1!=None:
if p1!=None and p2==None:
p3.next=Num()
p3=p3.next
p3.num=(p1.num-per)#%10
if p3.num<0:
p3.num+=10
per=1
else:
per=0
p1=p1.next
if p1!=None and p2!=None:
p3.next=Num()
p3=p3.next
p3.num=(p1.num-p2.num-per)#%10
if p3.num<0:
p3.num+=10
per=1
else:
per=0
p2=p2.next
p1=p1.next
res._reduce_zeros()
return res
def __eq__(self,other):
p1=self.head.next
p2=other.head.next
if self.sign==other.sign:
equ=True
else:
equ=False
while p1 and p2 and equ:
equ=(p1.num==p2.num)
p1=p1.next
p2=p2.next
if not p1 and not p2 and equ:
return True
else:
return False
def __len__(self):
'''
length without sign
'''
count=0
p=self.head
while(p.next):
count+=1
p=p.next
return count
def reverse(self):
t1 = self.head.next
s = None;
while t1 <> None:
p = t1
t1 = t1.next
p.next = s
s = p
self.head.next = s
def _low_then(self,other):
'''
A<B, A>=0, B>=0
'''
if len(self)<len(other):
return True
elif len(self)>len(other):
return False
else:
s=copy.deepcopy(self)
o=copy.deepcopy(other)
s.reverse()
o.reverse()
p1=s.head.next
p2=o.head.next
while p1.num==p2.num and p1.next:
p1=p1.next
p2=p2.next
if p1.num<p2.num:
return True
else:
return False
def __lt__(self,other):
if self.sign=="+" and other.sign=="-":
return False
elif self.sign=="-" and other.sign=="+":
return True
elif self.sign=="-" and other.sign=="-":
return other._low_then(self)
else:
return self._low_then(other)
def __le__(self,other):
if self<other or self==other:
return True
else:
return False
def __ne__(self,other):
if self==other:
return False
else:
return True
def __gt__(self,other):
if other<self:
return True
else:
return False
def __ge__(self,other):
if self<other:
return False
else:
return True
def __add__(self,other):
if self.sign=="+" and other.sign=="+":
return self._simple_add(other)
elif self.sign=="-" and other.sign=="-":
res=self._simple_add(other)
res.sign="-"
return res
elif self.sign=="-" and other.sign=="+":
s=abs(self)
o=abs(other)
if o>s:
res=o._simple_sub(s)
res.sign="+"
else:
res=s._simple_sub(o)
res.sign="-"
return res
else:
return other+self
def __sub__(self,other):
return self+(-other)
def _x10mul(self,count=1):
for i in xrange(count):
self._addFirst(0)
def _x10div(self,count=1):
for i in xrange(count):
self.head.next=self.head.next.next
def _simple_mul(self,other):
'''
a*b, a>=0, b>=0
'''
summa=LongNum()
temp=LongNum()
p2=other.head.next
level=0
while p2:
per=0
tres=temp.head
p1=self.head.next
while p1:
tres.next=Num()
tres=tres.next
tres.num=((p1.num*p2.num)+per)%10
per=((p1.num*p2.num)+per)/10
p1=p1.next
tres.next=Num()
tres=tres.next
tres.num=per
temp._x10mul(level)
summa=summa+temp
temp=LongNum()
level+=1
p2=p2.next
summa._reduce_zeros()
return summa
def __mul__(self,other):
if (self.sign=="+" and other.sign=="+") or (self.sign=="-" and other.sign=="-"):
return self._simple_mul(other)
elif self.sign=="-" and other.sign=="+":
return -(self._simple_mul(other))
else:
return other*self
def __sub_left(self,other):
'''
A=aaaa;B=bb; A-B=aaaa-bb00
'''
o=abs(other)
o._x10mul(len(self)-len(other))
if o<=self:
return self-o
else:
o._x10div(1)
return self-o
def _simple_div(self,other):
'''
A/B; B!=0; no signs
'''
s=abs(self)
o=abs(other)
res=LongNum()
delit=copy.deepcopy(o)
count=0
while(o<=s):
count+=1
o._x10mul()
o._x10div()
count-=1
j=0
while j<=count:
C=LongNum()
i=0
C._fill(i)
while C*o<=s:
i+=1
C._fill(i)
i-=1
res._addFirst(i)
if i==-1: i=0
C._fill(i)
s=s-(C*o)
if o!=delit:
o._x10div()
j+=1
res._reduce_zeros()
return res
if __name__== "__main__":
x1=LongNum()
x2=LongNum()
y1=1010
y2=101
x1._fill(y1)
x2._fill(y2)
lol=x1._simple_div(x2)
print lol
print y1/y2
# print
# print x1+x2
# print x2+x1
JycnCkNyZWF0ZWQgb24gMTAuMTAuMjAxMgoKQGF1dGhvcjogcHljegonJycKCmltcG9ydCBjb3B5CgpjbGFzcyBOdW06CiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgc2VsZi5udW09JyMnCiAgICAgICAgc2VsZi5uZXh0PU5vbmUKCgpjbGFzcyBMb25nTnVtKG9iamVjdCk6CiAgICBkZWYgX19pbml0X18oc2VsZixsbj0wKToKICAgICAgICBzZWxmLmhlYWQ9TnVtKCkKICAgICAgICBzZWxmLnNpZ249JysnCiAgICAgICAgc2VsZi5fZmlsbChzdHIobG4pKQogICAgICAgICAgICAKICAgIGRlZiBfYWRkRmlyc3Qoc2VsZixlbCk6CiAgICAgICAgeD1OdW0oKQogICAgICAgIHgubnVtPWVsCiAgICAgICAgeC5uZXh0PXNlbGYuaGVhZC5uZXh0CiAgICAgICAgc2VsZi5oZWFkLm5leHQ9eCAKICAgIAogICAgZGVmIF9kZWwoc2VsZik6CiAgICAgICAgc2VsZi5oZWFkLm5leHQ9Tm9uZQogICAgICAgIHNlbGYuc2lnbj0iKyIKICAgICAgICAgICAgICAgICAgIAogICAgZGVmIF9maWxsKHNlbGYsbG4pOgogICAgICAgIGxuPXN0cihsbikKICAgICAgICBzZWxmLl9kZWwoKQogICAgICAgIHNlbGYuc2lnbj0iKyIKICAgICAgICBpZiBsbiBhbmQgbG5bMF09PSctJzoKICAgICAgICAgICAgc2VsZi5zaWduPSctJwogICAgICAgICAgICBsbj1sblsxOl0KICAgICAgICBpZiBsbiBhbmQgbG5bMF09PScrJzoKICAgICAgICAgICAgbG49bG5bMTpdCiAgICAgICAgZm9yIGwgaW4gbG46CiAgICAgICAgICAgIHg9aW50KGwpCiAgICAgICAgICAgIHNlbGYuX2FkZEZpcnN0KHgpCiAgICAgICAgaWYgbG46CiAgICAgICAgICAgIHNlbGYuX3JlZHVjZV96ZXJvcygpCiAgICAgICAgICAgIHNlbGYuX2lzWmVybygpCiAgICAgICAgICAgIAogICAgZGVmIF9pc1plcm8oc2VsZik6CiAgICAgICAgaWYgc2VsZi5oZWFkLm5leHQgYW5kIHNlbGYuaGVhZC5uZXh0Lm51bT09MCBhbmQgc2VsZi5oZWFkLm5leHQubmV4dD09Tm9uZToKICAgICAgICAgICAgc2VsZi5zaWduPScrJwogICAgICAgICAgICByZXR1cm4gVHJ1ZQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJldHVybiBGYWxzZQogICAgICAgIAogICAgZGVmIF9fc3RyX18oc2VsZik6CiAgICAgICAgcmVzPSIiCiAgICAgICAgcD1zZWxmLmhlYWQubmV4dAogICAgICAgIHdoaWxlIHAhPU5vbmU6CiAgICAgICAgICAgIHJlcz1zdHIocC5udW0pK3JlcwogICAgICAgICAgICBwPXAubmV4dAogICAgICAgIGlmIG5vdCBzZWxmLl9pc1plcm8oKSBhbmQgc2VsZi5zaWduIT0nKyc6CiAgICAgICAgICAgIHJlcz0nLScrcmVzCiAgICAgICAgcmV0dXJuIHJlcwogICAgCiAgICBkZWYgZW1wdHkoc2VsZik6CiAgICAgICAgcmV0dXJuIG5vdCBzZWxmLmhlYWQubmV4dAogICAgCiAgICBkZWYgX19uZWdfXyhzZWxmKToKICAgICAgICByZXM9Y29weS5kZWVwY29weShzZWxmKQogICAgICAgIGlmIHNlbGYuX2lzWmVybygpOgogICAgICAgICAgICByZXR1cm4gcmVzCiAgICAgICAgaWYgc2VsZi5zaWduPT0nKyc6CiAgICAgICAgICAgIHJlcy5zaWduPSItIgogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJlcy5zaWduPSIrIgogICAgICAgIHJldHVybiByZXMKICAgIAogICAgZGVmIF9fYWJzX18oc2VsZik6CiAgICAgICAgcmVzPWNvcHkuZGVlcGNvcHkoc2VsZikKICAgICAgICByZXMuc2lnbj0iKyIKICAgICAgICByZXR1cm4gcmVzCiAgICAKICAgIGRlZiBfc2ltcGxlX2FkZChzZWxmLG90aGVyKToKICAgICAgICAnJycKICAgICAgICByZXR1cm4gc2ltcGxlIGErYiwgbm8gc2lnbnMKICAgICAgICAnJycKICAgICAgICByZXM9TG9uZ051bSgpCiAgICAgICAgcGVyPTAKICAgICAgICBwMT1zZWxmLmhlYWQubmV4dAogICAgICAgIHAyPW90aGVyLmhlYWQubmV4dAogICAgICAgIHAzPXJlcy5oZWFkCiAgICAgICAgd2hpbGUgbm90IChwMT09Tm9uZSBhbmQgcDI9PU5vbmUpOgogICAgICAgICAgICBpZiBwMSE9Tm9uZSBhbmQgcDI9PU5vbmU6CiAgICAgICAgICAgICAgICBwMy5uZXh0PU51bSgpCiAgICAgICAgICAgICAgICBwMz1wMy5uZXh0CiAgICAgICAgICAgICAgICBwMy5udW09KHAxLm51bStwZXIpJTEwCiAgICAgICAgICAgICAgICBwZXI9KHAxLm51bStwZXIpLzEwCiAgICAgICAgICAgICAgICBwMT1wMS5uZXh0CiAgICAgICAgICAgIGlmIHAxPT1Ob25lIGFuZCBwMiE9Tm9uZToKICAgICAgICAgICAgICAgIHAzLm5leHQ9TnVtKCkKICAgICAgICAgICAgICAgIHAzPXAzLm5leHQKICAgICAgICAgICAgICAgIHAzLm51bT0ocDIubnVtK3BlciklMTAKICAgICAgICAgICAgICAgIHBlcj0ocDIubnVtK3BlcikvMTAKICAgICAgICAgICAgICAgIHAyPXAyLm5leHQKICAgICAgICAgICAgaWYgcDEhPU5vbmUgYW5kIHAyIT1Ob25lOgogICAgICAgICAgICAgICAgcDMubmV4dD1OdW0oKQogICAgICAgICAgICAgICAgcDM9cDMubmV4dCAgICAgICAgICAgIAogICAgICAgICAgICAgICAgcDMubnVtPShwMi5udW0rcGVyK3AxLm51bSklMTAKICAgICAgICAgICAgICAgIHBlcj0ocDIubnVtK3BlcitwMS5udW0pLzEwCiAgICAgICAgICAgICAgICBwMj1wMi5uZXh0CiAgICAgICAgICAgICAgICBwMT1wMS5uZXh0CiAgICAgICAgaWYgcGVyIT0wOgogICAgICAgICAgICBwMy5uZXh0PU51bSgpCiAgICAgICAgICAgIHAzPXAzLm5leHQKICAgICAgICAgICAgcDMubnVtPXBlciAgICAgICAgCiAgICAgICAgcmV0dXJuIHJlcwogICAgCiAgICBkZWYgX3JlZHVjZV96ZXJvcyhzZWxmKToKICAgICAgICBwPXNlbGYuaGVhZC5uZXh0CiAgICAgICAgbWFyaz1Ob25lCiAgICAgICAgd2hpbGUocC5uZXh0KToKICAgICAgICAgICAgaWYocC5uZXh0Lm51bSE9MCk6CiAgICAgICAgICAgICAgICBtYXJrPXAKICAgICAgICAgICAgcD1wLm5leHQKICAgICAgICBpZiBtYXJrOgogICAgICAgICAgICBtYXJrLm5leHQubmV4dD1Ob25lCiAgICAgICAgZWxzZToKICAgICAgICAgICAgc2VsZi5oZWFkLm5leHQubmV4dD1Ob25lCiAgICAgICAgICAgCiAgICBkZWYgX3NpbXBsZV9zdWIoc2VsZixvdGhlcik6CiAgICAgICAgJycnCiAgICAgICAgcmV0dXJuIHNpbXBsZSBhLWIsIG5vIHNpZ25zLCBhPj1iCiAgICAgICAgJycnCiAgICAgICAgcmVzPUxvbmdOdW0oKQogICAgICAgIHBlcj0wCiAgICAgICAgcDE9c2VsZi5oZWFkLm5leHQKICAgICAgICBwMj1vdGhlci5oZWFkLm5leHQKICAgICAgICBwMz1yZXMuaGVhZAogICAgICAgIHdoaWxlIHAxIT1Ob25lOgogICAgICAgICAgICBpZiBwMSE9Tm9uZSBhbmQgcDI9PU5vbmU6CiAgICAgICAgICAgICAgICBwMy5uZXh0PU51bSgpCiAgICAgICAgICAgICAgICBwMz1wMy5uZXh0ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgcDMubnVtPShwMS5udW0tcGVyKSMlMTAKICAgICAgICAgICAgICAgIGlmIHAzLm51bTwwOgogICAgICAgICAgICAgICAgICAgIHAzLm51bSs9MTAKICAgICAgICAgICAgICAgICAgICBwZXI9MQogICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICBwZXI9MAogICAgICAgICAgICAgICAgcDE9cDEubmV4dAogICAgICAgICAgICBpZiBwMSE9Tm9uZSBhbmQgcDIhPU5vbmU6CiAgICAgICAgICAgICAgICBwMy5uZXh0PU51bSgpCiAgICAgICAgICAgICAgICBwMz1wMy5uZXh0ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBwMy5udW09KHAxLm51bS1wMi5udW0tcGVyKSMlMTAKICAgICAgICAgICAgICAgIGlmIHAzLm51bTwwOgogICAgICAgICAgICAgICAgICAgIHAzLm51bSs9MTAKICAgICAgICAgICAgICAgICAgICBwZXI9MQogICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICBwZXI9MAogICAgICAgICAgICAgICAgcDI9cDIubmV4dAogICAgICAgICAgICAgICAgcDE9cDEubmV4dAogICAgICAgIHJlcy5fcmVkdWNlX3plcm9zKCkKICAgICAgICByZXR1cm4gcmVzICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAKICAgIGRlZiBfX2VxX18oc2VsZixvdGhlcik6CiAgICAgICAgcDE9c2VsZi5oZWFkLm5leHQKICAgICAgICBwMj1vdGhlci5oZWFkLm5leHQKICAgICAgICBpZiBzZWxmLnNpZ249PW90aGVyLnNpZ246CiAgICAgICAgICAgIGVxdT1UcnVlCiAgICAgICAgZWxzZToKICAgICAgICAgICAgZXF1PUZhbHNlCiAgICAgICAgICAgIAogICAgICAgIHdoaWxlIHAxIGFuZCBwMiBhbmQgZXF1OgogICAgICAgICAgICBlcXU9KHAxLm51bT09cDIubnVtKQogICAgICAgICAgICBwMT1wMS5uZXh0CiAgICAgICAgICAgIHAyPXAyLm5leHQKICAgICAgICBpZiBub3QgcDEgYW5kIG5vdCBwMiBhbmQgZXF1OgogICAgICAgICAgICByZXR1cm4gVHJ1ZQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJldHVybiBGYWxzZQogICAgCiAgICBkZWYgX19sZW5fXyhzZWxmKToKICAgICAgICAnJycKICAgICAgICBsZW5ndGggd2l0aG91dCBzaWduCiAgICAgICAgJycnCiAgICAgICAgY291bnQ9MAogICAgICAgIHA9c2VsZi5oZWFkCiAgICAgICAgd2hpbGUocC5uZXh0KToKICAgICAgICAgICAgY291bnQrPTEKICAgICAgICAgICAgcD1wLm5leHQKICAgICAgICByZXR1cm4gY291bnQKICAgIAogICAgZGVmIHJldmVyc2Uoc2VsZik6CiAgICAgICAgdDEgPSBzZWxmLmhlYWQubmV4dAogICAgICAgIHMgPSBOb25lOwogICAgICAgIHdoaWxlIHQxIDw+IE5vbmU6IAogICAgICAgICAgICBwID0gdDEKICAgICAgICAgICAgdDEgPSB0MS5uZXh0CiAgICAgICAgICAgIHAubmV4dCA9IHMKICAgICAgICAgICAgcyA9IHAKICAgICAgICBzZWxmLmhlYWQubmV4dCA9IHMgCiAgICAgICAgCiAgICBkZWYgX2xvd190aGVuKHNlbGYsb3RoZXIpOgogICAgICAgICcnJwogICAgICAgIEE8QiwgQT49MCwgQj49MAogICAgICAgICcnJwogICAgICAgIGlmIGxlbihzZWxmKTxsZW4ob3RoZXIpOgogICAgICAgICAgICByZXR1cm4gVHJ1ZQogICAgICAgIGVsaWYgbGVuKHNlbGYpPmxlbihvdGhlcik6CiAgICAgICAgICAgIHJldHVybiBGYWxzZQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHM9Y29weS5kZWVwY29weShzZWxmKQogICAgICAgICAgICBvPWNvcHkuZGVlcGNvcHkob3RoZXIpCiAgICAgICAgICAgIHMucmV2ZXJzZSgpCiAgICAgICAgICAgIG8ucmV2ZXJzZSgpCiAgICAgICAgICAgIHAxPXMuaGVhZC5uZXh0CiAgICAgICAgICAgIHAyPW8uaGVhZC5uZXh0CiAgICAgICAgICAgIHdoaWxlIHAxLm51bT09cDIubnVtIGFuZCBwMS5uZXh0OgogICAgICAgICAgICAgICAgcDE9cDEubmV4dAogICAgICAgICAgICAgICAgcDI9cDIubmV4dAogICAgICAgICAgICBpZiBwMS5udW08cDIubnVtOgogICAgICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHJldHVybiBGYWxzZQogICAgICAgICAgICAgICAgCiAgICBkZWYgX19sdF9fKHNlbGYsb3RoZXIpOgogICAgICAgIGlmIHNlbGYuc2lnbj09IisiIGFuZCBvdGhlci5zaWduPT0iLSI6CiAgICAgICAgICAgIHJldHVybiBGYWxzZQogICAgICAgIGVsaWYgc2VsZi5zaWduPT0iLSIgYW5kIG90aGVyLnNpZ249PSIrIjoKICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgICAgICBlbGlmIHNlbGYuc2lnbj09Ii0iIGFuZCBvdGhlci5zaWduPT0iLSI6CiAgICAgICAgICAgIHJldHVybiBvdGhlci5fbG93X3RoZW4oc2VsZikKICAgICAgICBlbHNlOgogICAgICAgICAgICByZXR1cm4gc2VsZi5fbG93X3RoZW4ob3RoZXIpICAgCiAgICAKICAgIGRlZiBfX2xlX18oc2VsZixvdGhlcik6CiAgICAgICAgaWYgc2VsZjxvdGhlciBvciBzZWxmPT1vdGhlcjoKICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgICAgICBlbHNlOgogICAgICAgICAgICByZXR1cm4gRmFsc2UKICAgICAgICAKICAgIGRlZiBfX25lX18oc2VsZixvdGhlcik6CiAgICAgICAgaWYgc2VsZj09b3RoZXI6CiAgICAgICAgICAgIHJldHVybiBGYWxzZQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJldHVybiBUcnVlCiAgICAKICAgIGRlZiBfX2d0X18oc2VsZixvdGhlcik6CiAgICAgICAgaWYgb3RoZXI8c2VsZjoKICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgICAgICBlbHNlOgogICAgICAgICAgICByZXR1cm4gRmFsc2UKICAgICAgICAKICAgIGRlZiBfX2dlX18oc2VsZixvdGhlcik6CiAgICAgICAgaWYgc2VsZjxvdGhlcjoKICAgICAgICAgICAgcmV0dXJuIEZhbHNlCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmV0dXJuIFRydWUgICAgCiAgICAgICAgICAgICAgCiAgICBkZWYgX19hZGRfXyhzZWxmLG90aGVyKToKICAgICAgICBpZiBzZWxmLnNpZ249PSIrIiBhbmQgb3RoZXIuc2lnbj09IisiOgogICAgICAgICAgICByZXR1cm4gc2VsZi5fc2ltcGxlX2FkZChvdGhlcikKICAgICAgICBlbGlmIHNlbGYuc2lnbj09Ii0iIGFuZCBvdGhlci5zaWduPT0iLSI6CiAgICAgICAgICAgIHJlcz1zZWxmLl9zaW1wbGVfYWRkKG90aGVyKQogICAgICAgICAgICByZXMuc2lnbj0iLSIKICAgICAgICAgICAgcmV0dXJuIHJlcwogICAgICAgIGVsaWYgc2VsZi5zaWduPT0iLSIgYW5kIG90aGVyLnNpZ249PSIrIjoKICAgICAgICAgICAgcz1hYnMoc2VsZikKICAgICAgICAgICAgbz1hYnMob3RoZXIpCiAgICAgICAgICAgIGlmIG8+czoKICAgICAgICAgICAgICAgIHJlcz1vLl9zaW1wbGVfc3ViKHMpCiAgICAgICAgICAgICAgICByZXMuc2lnbj0iKyIKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHJlcz1zLl9zaW1wbGVfc3ViKG8pCiAgICAgICAgICAgICAgICByZXMuc2lnbj0iLSIKICAgICAgICAgICAgcmV0dXJuIHJlcwogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJldHVybiBvdGhlcitzZWxmCiAgICAgICAKICAgIGRlZiBfX3N1Yl9fKHNlbGYsb3RoZXIpOgogICAgICAgIHJldHVybiBzZWxmKygtb3RoZXIpCiAgICAKICAgIGRlZiBfeDEwbXVsKHNlbGYsY291bnQ9MSk6CiAgICAgICAgZm9yIGkgaW4geHJhbmdlKGNvdW50KToKICAgICAgICAgICAgc2VsZi5fYWRkRmlyc3QoMCkKICAgIAogICAgZGVmIF94MTBkaXYoc2VsZixjb3VudD0xKToKICAgICAgICBmb3IgaSBpbiB4cmFuZ2UoY291bnQpOgogICAgICAgICAgICBzZWxmLmhlYWQubmV4dD1zZWxmLmhlYWQubmV4dC5uZXh0CiAgICAgICAgICAgICAgICAKICAgIGRlZiBfc2ltcGxlX211bChzZWxmLG90aGVyKToKICAgICAgICAnJycKICAgICAgICBhKmIsIGE+PTAsIGI+PTAKICAgICAgICAnJycKICAgICAgICBzdW1tYT1Mb25nTnVtKCkKICAgICAgICB0ZW1wPUxvbmdOdW0oKQogICAgICAgIHAyPW90aGVyLmhlYWQubmV4dAogICAgICAgIGxldmVsPTAKICAgICAgICB3aGlsZSBwMjoKICAgICAgICAgICAgcGVyPTAKICAgICAgICAgICAgdHJlcz10ZW1wLmhlYWQKICAgICAgICAgICAgcDE9c2VsZi5oZWFkLm5leHQKICAgICAgICAgICAgd2hpbGUgcDE6CiAgICAgICAgICAgICAgICB0cmVzLm5leHQ9TnVtKCkKICAgICAgICAgICAgICAgIHRyZXM9dHJlcy5uZXh0CiAgICAgICAgICAgICAgICB0cmVzLm51bT0oKHAxLm51bSpwMi5udW0pK3BlciklMTAKICAgICAgICAgICAgICAgIHBlcj0oKHAxLm51bSpwMi5udW0pK3BlcikvMTAKICAgICAgICAgICAgICAgIHAxPXAxLm5leHQKICAgICAgICAgICAgdHJlcy5uZXh0PU51bSgpCiAgICAgICAgICAgIHRyZXM9dHJlcy5uZXh0CiAgICAgICAgICAgIHRyZXMubnVtPXBlciAgICAgICAgICAgIAogICAgICAgICAgICB0ZW1wLl94MTBtdWwobGV2ZWwpCiAgICAgICAgICAgIHN1bW1hPXN1bW1hK3RlbXAKICAgICAgICAgICAgdGVtcD1Mb25nTnVtKCkKICAgICAgICAgICAgbGV2ZWwrPTEKICAgICAgICAgICAgcDI9cDIubmV4dAogICAgICAgIHN1bW1hLl9yZWR1Y2VfemVyb3MoKQogICAgICAgIHJldHVybiBzdW1tYQogICAgCiAgICBkZWYgX19tdWxfXyhzZWxmLG90aGVyKToKICAgICAgICBpZiAgKHNlbGYuc2lnbj09IisiIGFuZCBvdGhlci5zaWduPT0iKyIpIG9yIChzZWxmLnNpZ249PSItIiBhbmQgb3RoZXIuc2lnbj09Ii0iKToKICAgICAgICAgICAgcmV0dXJuIHNlbGYuX3NpbXBsZV9tdWwob3RoZXIpCiAgICAgICAgZWxpZiAgc2VsZi5zaWduPT0iLSIgYW5kIG90aGVyLnNpZ249PSIrIjoKICAgICAgICAgICAgcmV0dXJuIC0oc2VsZi5fc2ltcGxlX211bChvdGhlcikpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmV0dXJuIG90aGVyKnNlbGYKICAgIAogICAgZGVmIF9fc3ViX2xlZnQoc2VsZixvdGhlcik6CiAgICAgICAgJycnCiAgICAgICAgQT1hYWFhO0I9YmI7IEEtQj1hYWFhLWJiMDAKICAgICAgICAnJycKICAgICAgICBvPWFicyhvdGhlcikKICAgICAgICBvLl94MTBtdWwobGVuKHNlbGYpLWxlbihvdGhlcikpCiAgICAgICAgaWYgbzw9c2VsZjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYtbwogICAgICAgIGVsc2U6CiAgICAgICAgICAgIG8uX3gxMGRpdigxKQogICAgICAgICAgICByZXR1cm4gc2VsZi1vCiAgICAKICAgIGRlZiBfc2ltcGxlX2RpdihzZWxmLG90aGVyKToKICAgICAgICAnJycKICAgICAgICBBL0I7IEIhPTA7IG5vIHNpZ25zCiAgICAgICAgJycnCiAgICAgICAgcz1hYnMoc2VsZikKICAgICAgICBvPWFicyhvdGhlcikKICAgICAgICByZXM9TG9uZ051bSgpCiAgICAgICAgZGVsaXQ9Y29weS5kZWVwY29weShvKQoKICAgICAgICBjb3VudD0wCiAgICAgICAgd2hpbGUobzw9cyk6CiAgICAgICAgICAgIGNvdW50Kz0xCiAgICAgICAgICAgIG8uX3gxMG11bCgpCiAgICAgICAgby5feDEwZGl2KCkKICAgICAgICBjb3VudC09MQogICAgICAgIGo9MAogICAgICAgIHdoaWxlIGo8PWNvdW50OgogICAgICAgICAgICBDPUxvbmdOdW0oKQogICAgICAgICAgICBpPTAKICAgICAgICAgICAgQy5fZmlsbChpKQogICAgICAgICAgICB3aGlsZSBDKm88PXM6CiAgICAgICAgICAgICAgICBpKz0xCiAgICAgICAgICAgICAgICBDLl9maWxsKGkpCiAgICAgICAgICAgIGktPTEKICAgICAgICAgICAgcmVzLl9hZGRGaXJzdChpKQogICAgICAgICAgICBpZiBpPT0tMTogaT0wCiAgICAgICAgICAgIEMuX2ZpbGwoaSkKICAgICAgICAgICAgcz1zLShDKm8pCiAgICAgICAgICAgIGlmIG8hPWRlbGl0OgogICAgICAgICAgICAgICAgby5feDEwZGl2KCkKICAgICAgICAgICAgais9MQogICAgICAgICAgICAKICAgICAgICByZXMuX3JlZHVjZV96ZXJvcygpCiAgICAgICAgcmV0dXJuIHJlcwogICAgICAgIAogICAgICAgIAogICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAppZiBfX25hbWVfXz09ICJfX21haW5fXyI6CiAgICB4MT1Mb25nTnVtKCkKICAgIHgyPUxvbmdOdW0oKQogICAgeTE9MTAxMAogICAgeTI9MTAxCiAgICB4MS5fZmlsbCh5MSkKCiAgICB4Mi5fZmlsbCh5MikKICAgIGxvbD14MS5fc2ltcGxlX2Rpdih4MikKICAgIHByaW50IGxvbAogICAgcHJpbnQgeTEveTIKIAoKIyAgICBwcmludCAKIyAgICBwcmludCB4MSt4MgojICAgIHByaW50IHgyK3gxICAgCiAgICAgICAgICAgIA==