class String
def is_digit?
!!Float ( self ) rescue false
end
end
class BFCompiler
# 0 | stack | 0 | 10 tmp cells| 0 | 3 cmp cell | 0 | ax | bx | cx | dx | 0 | 0 | 0 | 0 | 254 buffer | arrays... | strings... |
# start pos ^ index of array ^ ^
attr_accessor :registers
def addRegister( name)
@registers [ name] =@regnow
@regnow + =1
end
def initialize
@program = [ "<<<->>>" ] #init stack
@pos =0
# registers offset
@ro =16
@eqR =@ro- 4 # equal flag
@ltR =@ro- 3 # little flag
@gtR =@ro- 2 # great flag
@regnow =@ro
@registers ={ }
addRegister "ax"
addRegister "bx"
addRegister "cx"
addRegister "dx"
#addRegister "sp"
@indEl = @regnow + 2 # index of array
@arrays = [ ]
@total =256
end
def compileBf
i=0
@total = @total ==256 ? 0 : @total
"Min cells used:#{@total+@indEl}\n " + @program .join ( "" ) .split ( // ) .collect { | ch|
i+ =1
if i> =80
i=0
ch+ "\n "
else
ch
end
} .join ( "" )
end
def gotoR( reg)
@program << ( reg- @pos> 0 ? ">" : "<" ) * ( reg- @pos) .abs
@pos =reg
end
def addNumToR( reg,num)
gotoR( reg)
@program << "+" * num
end
def subNumFromR( reg,num)
gotoR( reg)
@program << "-" * num
end
def moveRToR( reg1,reg2)
startCycle( reg1)
subNumFromR( reg1,1 )
addNumToR( reg2,1 )
endCycle( reg1)
end
def outR( reg)
gotoR( reg)
@program << "."
end
def inputR( reg)
gotoR( reg)
@program << ","
end
def startCycle( reg)
gotoR( reg)
@program << "["
end
def endCycle( reg)
gotoR( reg)
@program << "]"
end
def inc( reg)
addNumToR( reg,1 )
end
def dec( reg)
subNumFromR( reg,1 )
end
def zeroR( reg)
startCycle( reg)
dec reg
endCycle( reg)
end
def setR( reg,num)
zeroR( reg)
addNumToR( reg,num)
end
def copyR( reg2,reg1)
#copy reg1 to reg2
zeroR( reg2)
zeroR( 0 )
startCycle( reg1)
dec reg1
inc reg2
inc 0
endCycle( reg1)
moveRToR( 0 ,reg1)
end
def addRToR( reg1,reg2)
# reg1=reg1+reg2
zeroR( 0 )
startCycle( reg2)
dec reg2
inc reg1
inc 0
endCycle( reg2)
moveRToR( 0 ,reg2)
end
def subRFromR( reg1,reg2)
# reg1= reg1-reg2
zeroR( 0 )
startCycle( reg2)
dec reg2
dec reg1
inc 0
endCycle( reg2)
moveRToR( 0 ,reg2)
end
def pushNumToStack( num)
setR( 0 ,num)
@program << "-<<[<]<[->+<]<<[-]>+>>[>]>[-<<[<]<+>>[>]>]"
end
def pushRToStack( reg)
copyR( 1 ,reg)
moveRToR( 1 ,0 )
gotoR( 0 )
@program << "-<<[<]<[->+<]<<[-]>+>>[>]>[-<<[<]<+>>[>]>]"
end
def popNumToR( reg)
zeroR( 0 )
@program << "+<<[<]<-[->>[>]>+<<[<]<]>>[-<+>]>[>]>"
zeroR( reg)
moveRToR( 0 ,reg)
end
def mulRonR( reg1,reg2)
zeroR( 0 )
zeroR( 1 )
startCycle( reg1)
inc 1
dec reg1
endCycle( reg1)
startCycle( 1 )
startCycle( reg2)
inc reg1
inc 0
dec reg2
endCycle( reg2)
startCycle( 0 )
inc reg2
dec 0
endCycle( 0 )
dec 1
endCycle( 1 )
end
def divRonR( reg1,reg2)
zeroR( 0 )
zeroR( 1 )
zeroR( 2 )
zeroR( 3 )
zeroR( 4 )
copyR( 1 ,reg1)
copyR( 2 ,reg2)
# divmod algorithm
gotoR( 1 )
@program << "[->-[>+>>]>[+[-<+>]>+>>]<<<<<]"
copyR( reg2,3 )
copyR( reg1,4 )
end
def cmpRR( reg1,reg2)
copyR( 1 ,reg1)
copyR( 2 ,reg2)
zeroR( 0 )
setR( @eqR,1 )
setR( @ltR,1 )
setR( @gtR,2 )
startCycle( 2 )
subNumFromR( 2 ,1 )
startCycle( 1 )
inc @ltR
moveRToR( 1 ,0 )
endCycle( 1 )
moveRToR( 0 ,1 )
dec @ltR
dec 1
endCycle( 2 )
startCycle( 1 )
inc @eqR
zeroR( 1 )
endCycle( 1 )
dec @eqR
startCycle( @ltR)
dec @gtR
moveRToR( @ltR,0 )
endCycle( @ltR)
moveRToR( 0 ,@ltR)
startCycle( @eqR)
dec @gtR
moveRToR( @eqR,0 )
endCycle( @eqR)
moveRToR( 0 ,@eqR)
end
def declareArray( name,size)
@arrays << { :name => name , :size => size+ 1 }
@total + =size+ 1
end
def getKnownArrElem( name,index,reg)
# set reg to name[index]
toArr=256
i=0
while @arrays [ i] [ :name ] !=name
toArr+ =@arrays[ i] [ :size ]
i+ =1
end
toArr+ =index
copyR( reg,@indEl+ toArr)
end
def getUnknownArrElem( name,regindex,reg)
# set reg to name[regindex]
toArr=256
i=0
while @arrays [ i] [ :name ] !=name
toArr+ =@arrays[ i] [ :size ]
i+ =1
end
copyR( @indEl,regindex)
copyR( @indEl+ 1 ,regindex)
gotoR( @indEl)
# copy indEl and indEl+1 on regindex register forward
@program << "[>[->+<]<[->+<]>-]"
# go to arr element
@program << ">" * toArr
# copy arr element
@program << "[-" << "<" * toArr << "+<+>" << ">" * toArr << "]"
# restore arr element
@program << "<" * toArr << "<[->" << ">" * toArr << "+" << "<" * toArr << "<]"
# copy indEl and indEl+1 back
@program << ">>[<[-<+>]>[-<+>]<-]<"
# fast move
@pos = @indEl
startCycle( @indEl)
dec @indEl
inc reg
endCycle( @indEl)
end
def setKnownArrElemWithR( name,index,reg)
# set name[index] to reg
toArr=256
i=0
while @arrays [ i] [ :name ] !=name
toArr+ =@arrays[ i] [ :size ]
i+ =1
end
toArr+ =index
copyR( @indEl+ toArr,reg)
end
def setKnownArrElemWithNum( name,index,num)
# set name[index] to num
toArr=256
i=0
while @arrays [ i] [ :name ] !=name
toArr+ =@arrays[ i] [ :size ]
i+ =1
end
toArr+ =index
setR( @indEl+ toArr,num)
end
def setUnknownArrElemWithNum( name,regindex,num)
# set name[regindex] to num
toArr=256
i=0
while @arrays [ i] [ :name ] !=name
toArr+ =@arrays[ i] [ :size ]
i+ =1
end
setR( @indEl- 1 ,num)
copyR( @indEl,regindex)
copyR( @indEl+ 1 ,regindex)
gotoR( @indEl)
@program << "[>[->+<]<[->+<]<[->+<]>>-]"
@program << ">" * toArr
@program << "[-]"
@program << "<" * toArr
@program << "<[->"
@program << ">" * toArr
@program << "+"
@program << "<" * toArr
@program << "<]>>[[-<+>]<-]<"
@pos =@indEl
end
def setUnknownArrElemWithR( name,regindex,reg)
# set name[regindex] to reg
toArr=256
i=0
while @arrays [ i] [ :name ] !=name
toArr+ =@arrays[ i] [ :size ]
i+ =1
end
copyR( @indEl- 1 ,reg)
copyR( @indEl,regindex)
copyR( @indEl+ 1 ,regindex)
gotoR( @indEl)
@program << "[>[->+<]<[->+<]<[->+<]>>-]"
@program << ">" * toArr
@program << "[-]"
@program << "<" * toArr
@program << "<[->"
@program << ">" * toArr
@program << "+"
@program << "<" * toArr
@program << "<]>>[[-<+>]<-]<"
@pos =@indEl
end
def makeInitCode( numArr)
res=[ ]
numArr.each { | num|
res << "+" * num << ">"
}
res.join ( "" )
end
def addString( name, data)
declareArray( name,data.length )
forInit=data.split ( "" ) .collect { | ch| ch.ord }
toArr=256
i=0
while @arrays [ i] [ :name ] !=name
toArr+ =@arrays[ i] [ :size ]
i+ =1
end
@program .unshift ( ">" * ( toArr+ @indEl) + makeInitCode( forInit) + "<" * ( toArr+ @indEl+ data.length ) )
end
def putStr( name)
toArr=256
i=0
while @arrays [ i] [ :name ] !=name
toArr+ =@arrays[ i] [ :size ]
i+ =1
end
gotoR( @indEl)
@program << ">" * toArr << "[.>]<[<]>" << "<" * toArr
end
def ifFalse( op)
case op
when :eq
reg=@eqR
when :lt
reg=@ltR
when :gt
reg=@gtR
else
raise "logic error"
end
zeroR( 5 )
zeroR( 6 )
startCycle( reg)
inc 5
moveRToR( reg,6 )
endCycle( reg)
moveRToR( 6 ,reg)
startCycle( 5 )
end
def ifTrue( op)
case op
when :eq
reg=@eqR
when :lt
reg=@ltR
when :gt
reg=@gtR
else
raise "logic error"
end
zeroR( 5 )
zeroR( 6 )
startCycle( reg)
dec 5
moveRToR( reg,6 )
endCycle( reg)
moveRToR( 6 ,reg)
inc 5
startCycle( 5 )
end
def endif
zeroR( 5 )
endCycle( 5 )
end
end
i=0
tmp=[ ]
word=[ ]
instring=false
STDIN.read .split ( "" ) .each { | a|
if !instring
if a==" " or a=="\n "
tmp << word.join ( "" ) .chomp if word.size > 0
word=[ ]
else
word << a
end
if a=="\""
instring=true
word=[]
end
else
if a=="\""
tmp << word.join("").chomp
word=[]
instring=false
else
word << a
end
end
}
tmp << word.join("").chomp
#puts tmp.inspect
cycles = []
a =BFCompiler.new
registers=a.registers
while i< tmp.length
case tmp[ i] .upcase
when "MOV"
if registers.has_key ?( tmp[ i+ 2 ] )
a.copyR ( registers[ tmp[ i+ 1 ] ] ,registers[ tmp[ i+ 2 ] ] )
else
a.setR ( registers[ tmp[ i+ 1 ] ] , tmp[ i+ 2 ] .is_digit ? ? tmp[ i+ 2 ] .to_i : tmp[ i+ 2 ] .ord )
end
i+ =3
when "SUB"
if registers.has_key ?( tmp[ i+ 2 ] )
a.subRFromR ( registers[ tmp[ i+ 1 ] ] ,registers[ tmp[ i+ 2 ] ] )
else
a.subNumFromR ( registers[ tmp[ i+ 1 ] ] ,tmp[ i+ 2 ] .to_i )
end
i+ =3
when "ADD"
if registers.has_key ?( tmp[ i+ 2 ] )
a.addRToR ( registers[ tmp[ i+ 1 ] ] ,registers[ tmp[ i+ 2 ] ] )
else
a.addNumToR ( registers[ tmp[ i+ 1 ] ] ,tmp[ i+ 2 ] .to_i )
end
i+ =3
when "MUL"
a.mulRonR ( registers[ tmp[ i+ 1 ] ] ,registers[ tmp[ i+ 2 ] ] )
i+ =3
when "DIV"
a.divRonR ( registers[ tmp[ i+ 1 ] ] ,registers[ tmp[ i+ 2 ] ] )
i+ =3
when "ARRAY"
a.declareArray ( tmp[ i+ 1 ] ,tmp[ i+ 2 ] .to_i )
i+ =3
when "CMP"
a.cmpRR ( registers[ tmp[ i+ 1 ] ] ,registers[ tmp[ i+ 2 ] ] )
i+ =3
when "GET"
if registers.has_key ?( tmp[ i+ 2 ] )
a.getUnknownArrElem ( tmp[ i+ 1 ] ,registers[ tmp[ i+ 2 ] ] ,registers[ tmp[ i+ 3 ] ] )
else
a.getKnownArrElem ( tmp[ i+ 1 ] ,tmp[ i+ 2 ] .to_i ,registers[ tmp[ i+ 3 ] ] )
end
i+ =4
when "SET"
if registers.has_key ?( tmp[ i+ 2 ] )
if registers.has_key ?( tmp[ i+ 3 ] )
a.setUnknownArrElemWithR ( tmp[ i+ 1 ] ,registers[ tmp[ i+ 2 ] ] ,registers[ tmp[ i+ 3 ] ] )
else
a.setUnknownArrElemWithNum ( tmp[ i+ 1 ] ,registers[ tmp[ i+ 2 ] ] ,tmp[ i+ 3 ] .to_i )
end
else
if registers.has_key ?( tmp[ i+ 3 ] )
a.setKnownArrElemWithR ( tmp[ i+ 1 ] ,tmp[ i+ 2 ] .to_i ,registers[ tmp[ i+ 3 ] ] )
else
a.setKnownArrElemWithNum ( tmp[ i+ 1 ] ,tmp[ i+ 2 ] .to_i ,tmp[ i+ 3 ] .to_i )
end
end
i+ =4
when "PUSH"
if registers.has_key ?( tmp[ i+ 1 ] )
a.pushRToStack ( registers[ tmp[ i+ 1 ] ] )
else
a.pushNumToStack ( tmp[ i+ 1 ] .to_i )
end
i+ =2
when "NE"
a.ifFalse ( :eq )
i+ =1
when "NL"
a.ifFalse ( :lt )
i+ =1
when "NG"
a.ifFalse ( :gt )
i+ =1
when "EQ"
a.ifTrue ( :eq )
i+ =1
when "LT"
a.ifTrue ( :lt )
i+ =1
when "GT"
a.ifTrue ( :gt )
i+ =1
when "PUT"
a.outR ( registers[ tmp[ i+ 1 ] ] )
i+ =2
when "POP"
a.popNumToR ( registers[ tmp[ i+ 1 ] ] )
i+ =2
when "TAKE"
a.inputR ( registers[ tmp[ i+ 1 ] ] )
i+ =2
when "PUTS"
a.putStr ( tmp[ i+ 1 ] )
i+ =2
when "INC"
a.inc ( registers[ tmp[ i+ 1 ] ] )
i+ =2
when "DEC"
a.dec ( registers[ tmp[ i+ 1 ] ] )
i+ =2
when "WHILE"
a.startCycle ( registers[ tmp[ i+ 1 ] ] )
cycles << registers[ tmp[ i+ 1 ] ]
i+ =2
when "ENDWHILE"
a.endCycle ( cycles.pop )
i+ =1
when "END"
a.endif
i+ =1
when "STRING"
a.addString ( tmp[ i+ 1 ] ,tmp[ i+ 2 ] )
i+ =3
else
i+ =1
end
end
puts a.compileBf
Y2xhc3MgU3RyaW5nCiAgZGVmIGlzX2RpZ2l0PwogICAgICAhIUZsb2F0KHNlbGYpIHJlc2N1ZSBmYWxzZQogIGVuZAplbmQKCmNsYXNzIEJGQ29tcGlsZXIKIyAwIHwgc3RhY2sgfCAwIHwgMTAgdG1wIGNlbGxzfCAwIHwgMyBjbXAgY2VsbCB8IDAgfCBheCB8IGJ4IHwgY3ggfCBkeCB8IDAgfCAwIHwgMCB8IDAgfCAyNTQgYnVmZmVyIHwgYXJyYXlzLi4uIHwgc3RyaW5ncy4uLiB8CiMgICAgICAgc3RhcnQgcG9zIF4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4IG9mIGFycmF5IF4gICBeCgogICAgYXR0cl9hY2Nlc3NvciA6cmVnaXN0ZXJzCiAgICAKICAgIGRlZiBhZGRSZWdpc3RlcihuYW1lKQogICAgICAgIEByZWdpc3RlcnNbbmFtZV09QHJlZ25vdwogICAgICAgIEByZWdub3crPTEKICAgIGVuZAogICAgCiAgICBkZWYgaW5pdGlhbGl6ZQogICAgICAgIEBwcm9ncmFtID0gWyI8PDwtPj4+Il0gI2luaXQgc3RhY2sKICAgICAgICBAcG9zPTAKICAgICAgICAjIHJlZ2lzdGVycyBvZmZzZXQKICAgICAgICBAcm89MTYKICAgICAgICBAZXFSPUByby00ICMgZXF1YWwgZmxhZwogICAgICAgIEBsdFI9QHJvLTMgIyBsaXR0bGUgZmxhZwogICAgICAgIEBndFI9QHJvLTIgIyBncmVhdCBmbGFnCiAgICAgICAgQHJlZ25vdz1Acm8KICAgICAgICBAcmVnaXN0ZXJzPXt9CiAgICAgICAgYWRkUmVnaXN0ZXIgImF4IgogICAgICAgIGFkZFJlZ2lzdGVyICJieCIKICAgICAgICBhZGRSZWdpc3RlciAiY3giCiAgICAgICAgYWRkUmVnaXN0ZXIgImR4IgogICAgICAgICNhZGRSZWdpc3RlciAic3AiCiAgICAgICAgQGluZEVsID0gQHJlZ25vdysyICMgaW5kZXggb2YgYXJyYXkKICAgICAgICBAYXJyYXlzID0gW10KICAgICAgICBAdG90YWw9MjU2CiAgICBlbmQKICAgIAogICAgZGVmIGNvbXBpbGVCZgogICAgICAgIGk9MAogICAgICAgIEB0b3RhbCA9IEB0b3RhbCA9PTI1Nj8gMDogQHRvdGFsCiAgICAgICAgIk1pbiBjZWxscyB1c2VkOiN7QHRvdGFsK0BpbmRFbH1cbiIgKyBAcHJvZ3JhbS5qb2luKCIiKS5zcGxpdCgvLykuY29sbGVjdCB7IHxjaHwKICAgICAgICAgICAgaSs9MQogICAgICAgICAgICBpZiBpPj04MAogICAgICAgICAgICAgIGk9MAogICAgICAgICAgICAgIGNoKyJcbiIKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgIGNoCiAgICAgICAgICAgIGVuZAogICAgICAgICAgfS5qb2luKCIiKQogICAgZW5kCiAgICAKICAgIGRlZiBnb3RvUihyZWcpCiAgICAgICAgQHByb2dyYW0gPDwgKHJlZy1AcG9zPjA/ICI+IiA6ICI8IikqKHJlZy1AcG9zKS5hYnMKICAgICAgICBAcG9zPXJlZwogICAgZW5kCiAgICAKICAgIGRlZiBhZGROdW1Ub1IocmVnLG51bSkKICAgICAgICBnb3RvUihyZWcpCiAgICAgICAgQHByb2dyYW0gPDwgIisiKm51bQogICAgZW5kCiAgICAKICAgIGRlZiBzdWJOdW1Gcm9tUihyZWcsbnVtKQogICAgICAgIGdvdG9SKHJlZykKICAgICAgICBAcHJvZ3JhbSA8PCAiLSIqbnVtCiAgICBlbmQKICAgIAogICAgZGVmIG1vdmVSVG9SKHJlZzEscmVnMikKICAgICAgICBzdGFydEN5Y2xlKHJlZzEpCiAgICAgICAgICBzdWJOdW1Gcm9tUihyZWcxLDEpCiAgICAgICAgICBhZGROdW1Ub1IocmVnMiwxKQogICAgICAgIGVuZEN5Y2xlKHJlZzEpCiAgICBlbmQKICAgIAogICAgZGVmIG91dFIocmVnKQogICAgICAgIGdvdG9SKHJlZykKICAgICAgICBAcHJvZ3JhbSA8PCAiLiIKICAgIGVuZAogICAgCiAgICBkZWYgaW5wdXRSKHJlZykKICAgICAgICBnb3RvUihyZWcpCiAgICAgICAgQHByb2dyYW0gPDwgIiwiCiAgICBlbmQKICAgIAogICAgZGVmIHN0YXJ0Q3ljbGUocmVnKQogICAgICAgIGdvdG9SKHJlZykKICAgICAgICBAcHJvZ3JhbSA8PCAiWyIKICAgIGVuZAogICAgCiAgICBkZWYgZW5kQ3ljbGUocmVnKQogICAgICAgIGdvdG9SKHJlZykKICAgICAgICBAcHJvZ3JhbSA8PCAiXSIKICAgIGVuZAogICAgCiAgICBkZWYgaW5jKHJlZykKICAgICAgICBhZGROdW1Ub1IocmVnLDEpCiAgICBlbmQKICAgIAogICAgZGVmIGRlYyhyZWcpCiAgICAgICAgc3ViTnVtRnJvbVIocmVnLDEpCiAgICBlbmQKICAgIAogICAgZGVmIHplcm9SKHJlZykKICAgICAgICBzdGFydEN5Y2xlKHJlZykKICAgICAgICAgIGRlYyByZWcKICAgICAgICBlbmRDeWNsZShyZWcpCiAgICBlbmQKICAgIAogICAgZGVmIHNldFIocmVnLG51bSkKICAgICAgICB6ZXJvUihyZWcpCiAgICAgICAgYWRkTnVtVG9SKHJlZyxudW0pCiAgICBlbmQKICAgIAogICAgZGVmIGNvcHlSKHJlZzIscmVnMSkKICAgICAgICAjY29weSByZWcxIHRvIHJlZzIKICAgICAgICB6ZXJvUihyZWcyKQogICAgICAgIHplcm9SKDApCiAgICAgICAgc3RhcnRDeWNsZShyZWcxKQogICAgICAgICAgZGVjIHJlZzEKICAgICAgICAgIGluYyByZWcyCiAgICAgICAgICBpbmMgMAogICAgICAgIGVuZEN5Y2xlKHJlZzEpCiAgICAgICAgbW92ZVJUb1IoMCxyZWcxKQogICAgZW5kCiAgICAKICAgIGRlZiBhZGRSVG9SKHJlZzEscmVnMikKICAgICAgIyByZWcxPXJlZzErcmVnMgogICAgICAgIHplcm9SKDApCiAgICAgICAgc3RhcnRDeWNsZShyZWcyKQogICAgICAgICAgZGVjIHJlZzIKICAgICAgICAgIGluYyByZWcxCiAgICAgICAgICBpbmMgMAogICAgICAgIGVuZEN5Y2xlKHJlZzIpCiAgICAgICAgbW92ZVJUb1IoMCxyZWcyKQogICAgZW5kCiAgICAKICAgIGRlZiBzdWJSRnJvbVIocmVnMSxyZWcyKQogICAgICAjIHJlZzE9IHJlZzEtcmVnMgogICAgICAgIHplcm9SKDApCiAgICAgICAgc3RhcnRDeWNsZShyZWcyKQogICAgICAgICAgZGVjIHJlZzIKICAgICAgICAgIGRlYyByZWcxCiAgICAgICAgICBpbmMgMAogICAgICAgIGVuZEN5Y2xlKHJlZzIpCiAgICAgICAgbW92ZVJUb1IoMCxyZWcyKQogICAgZW5kCiAgICAKICAgIGRlZiBwdXNoTnVtVG9TdGFjayhudW0pCiAgICAgICAgc2V0UigwLG51bSkKICAgICAgICBAcHJvZ3JhbSA8PCAiLTw8WzxdPFstPis8XTw8Wy1dPis+Pls+XT5bLTw8WzxdPCs+Pls+XT5dIgogICAgZW5kCiAgICAKICAgIGRlZiBwdXNoUlRvU3RhY2socmVnKQogICAgICAgIGNvcHlSKDEscmVnKQogICAgICAgIG1vdmVSVG9SKDEsMCkKICAgICAgICBnb3RvUigwKQogICAgICAgIEBwcm9ncmFtIDw8ICItPDxbPF08Wy0+KzxdPDxbLV0+Kz4+Wz5dPlstPDxbPF08Kz4+Wz5dPl0iCiAgICBlbmQKICAgIAogICAgZGVmIHBvcE51bVRvUihyZWcpCiAgICAgICAgemVyb1IoMCkKICAgICAgICBAcHJvZ3JhbSA8PCAiKzw8WzxdPC1bLT4+Wz5dPis8PFs8XTxdPj5bLTwrPl0+Wz5dPiIKICAgICAgICB6ZXJvUihyZWcpCiAgICAgICAgbW92ZVJUb1IoMCxyZWcpCiAgICBlbmQKICAgIAogICAgZGVmIG11bFJvblIocmVnMSxyZWcyKQogICAgICAgIHplcm9SKDApCiAgICAgICAgemVyb1IoMSkKICAgICAgICBzdGFydEN5Y2xlKHJlZzEpCiAgICAgICAgICBpbmMgMQogICAgICAgICAgZGVjIHJlZzEKICAgICAgICBlbmRDeWNsZShyZWcxKQogICAgICAgIHN0YXJ0Q3ljbGUoMSkKICAgICAgICAgIHN0YXJ0Q3ljbGUocmVnMikKICAgICAgICAgICAgaW5jIHJlZzEKICAgICAgICAgICAgaW5jIDAKICAgICAgICAgICAgZGVjIHJlZzIKICAgICAgICAgIGVuZEN5Y2xlKHJlZzIpCiAgICAgICAgICBzdGFydEN5Y2xlKDApCiAgICAgICAgICAgIGluYyByZWcyCiAgICAgICAgICAgIGRlYyAwCiAgICAgICAgICBlbmRDeWNsZSgwKQogICAgICAgICAgZGVjIDEKICAgICAgICBlbmRDeWNsZSgxKQogICAgZW5kCiAgICAKICAgIGRlZiBkaXZSb25SKHJlZzEscmVnMikKICAgICAgICAgIHplcm9SKDApCiAgICAgICAgICB6ZXJvUigxKQogICAgICAgICAgemVyb1IoMikKICAgICAgICAgIHplcm9SKDMpCiAgICAgICAgICB6ZXJvUig0KQogICAgICAgICAgY29weVIoMSxyZWcxKQogICAgICAgICAgY29weVIoMixyZWcyKQogICAgICAgICAgIyBkaXZtb2QgYWxnb3JpdGhtCiAgICAgICAgICBnb3RvUigxKQogICAgICAgICAgQHByb2dyYW0gPDwgIlstPi1bPis+Pl0+WytbLTwrPl0+Kz4+XTw8PDw8XSIKICAgICAgICAgIGNvcHlSKHJlZzIsMykKICAgICAgICAgIGNvcHlSKHJlZzEsNCkKICAgIGVuZAogICAgCiAgICBkZWYgY21wUlIocmVnMSxyZWcyKQogICAgICAgIGNvcHlSKDEscmVnMSkKICAgICAgICBjb3B5UigyLHJlZzIpCiAgICAgICAgemVyb1IoMCkKICAgICAgICBzZXRSKEBlcVIsMSkKICAgICAgICBzZXRSKEBsdFIsMSkKICAgICAgICBzZXRSKEBndFIsMikKICAgICAgICBzdGFydEN5Y2xlKDIpCiAgICAgICAgICBzdWJOdW1Gcm9tUigyLDEpCiAgICAgICAgICBzdGFydEN5Y2xlKDEpCiAgICAgICAgICAgIGluYyBAbHRSCiAgICAgICAgICAgIG1vdmVSVG9SKDEsMCkKICAgICAgICAgIGVuZEN5Y2xlKDEpCiAgICAgICAgICBtb3ZlUlRvUigwLDEpCiAgICAgICAgICBkZWMgQGx0UgogICAgICAgICAgZGVjIDEKICAgICAgICBlbmRDeWNsZSgyKQogICAgICAgIHN0YXJ0Q3ljbGUoMSkKICAgICAgICAgIGluYyBAZXFSCiAgICAgICAgICB6ZXJvUigxKQogICAgICAgIGVuZEN5Y2xlKDEpCiAgICAgICAgZGVjIEBlcVIKICAgICAgICBzdGFydEN5Y2xlKEBsdFIpCiAgICAgICAgICBkZWMgQGd0UgogICAgICAgICAgbW92ZVJUb1IoQGx0UiwwKQogICAgICAgIGVuZEN5Y2xlKEBsdFIpCiAgICAgICAgbW92ZVJUb1IoMCxAbHRSKQogICAgICAgIHN0YXJ0Q3ljbGUoQGVxUikKICAgICAgICAgIGRlYyBAZ3RSCiAgICAgICAgICBtb3ZlUlRvUihAZXFSLDApCiAgICAgICAgZW5kQ3ljbGUoQGVxUikKICAgICAgICBtb3ZlUlRvUigwLEBlcVIpCiAgICBlbmQKICAgIAogICAgZGVmIGRlY2xhcmVBcnJheShuYW1lLHNpemUpCiAgICAgICAgQGFycmF5cyA8PCB7Om5hbWUgPT4gbmFtZSAsIDpzaXplID0+IHNpemUrMSB9CiAgICAgICAgQHRvdGFsKz1zaXplKzEKICAgIGVuZAogICAgCiAgICBkZWYgZ2V0S25vd25BcnJFbGVtKG5hbWUsaW5kZXgscmVnKQogICAgICAgICMgc2V0IHJlZyB0byBuYW1lW2luZGV4XQogICAgICAgIHRvQXJyPTI1NgogICAgICAgIGk9MAogICAgICAgIHdoaWxlIEBhcnJheXNbaV1bOm5hbWVdIT1uYW1lCiAgICAgICAgICAgIHRvQXJyKz1AYXJyYXlzW2ldWzpzaXplXQogICAgICAgICAgICBpKz0xCiAgICAgICAgZW5kCiAgICAgICAgdG9BcnIrPWluZGV4CiAgICAgICAgY29weVIocmVnLEBpbmRFbCt0b0FycikKICAgIGVuZAogICAgCiAgICBkZWYgZ2V0VW5rbm93bkFyckVsZW0obmFtZSxyZWdpbmRleCxyZWcpCiAgICAgICAgIyBzZXQgcmVnIHRvIG5hbWVbcmVnaW5kZXhdCiAgICAgICAgdG9BcnI9MjU2CiAgICAgICAgaT0wCiAgICAgICAgd2hpbGUgQGFycmF5c1tpXVs6bmFtZV0hPW5hbWUKICAgICAgICAgICAgdG9BcnIrPUBhcnJheXNbaV1bOnNpemVdCiAgICAgICAgICAgIGkrPTEKICAgICAgICBlbmQKICAgICAgICBjb3B5UihAaW5kRWwscmVnaW5kZXgpCiAgICAgICAgY29weVIoQGluZEVsKzEscmVnaW5kZXgpCiAgICAgICAgZ290b1IoQGluZEVsKQogICAgICAgICMgY29weSBpbmRFbCBhbmQgaW5kRWwrMSBvbiByZWdpbmRleCByZWdpc3RlciBmb3J3YXJkIAogICAgICAgIEBwcm9ncmFtIDw8ICJbPlstPis8XTxbLT4rPF0+LV0iIAogICAgICAgICMgZ28gdG8gYXJyIGVsZW1lbnQKICAgICAgICBAcHJvZ3JhbSA8PCAiPiIqdG9BcnIKICAgICAgICAjIGNvcHkgYXJyIGVsZW1lbnQKICAgICAgICBAcHJvZ3JhbSA8PCAiWy0iIDw8ICI8Iip0b0FyciA8PCIrPCs+IiA8PCAiPiIqdG9BcnIgPDwgIl0iCiAgICAgICAgIyByZXN0b3JlIGFyciBlbGVtZW50CiAgICAgICAgQHByb2dyYW0gPDwgIjwiKnRvQXJyIDw8ICI8Wy0+IiA8PCAiPiIqdG9BcnIgPDwgIisiIDw8ICI8Iip0b0FyciA8PCAiPF0iCiAgICAgICAgIyBjb3B5IGluZEVsIGFuZCBpbmRFbCsxIGJhY2sKICAgICAgICBAcHJvZ3JhbSA8PCAiPj5bPFstPCs+XT5bLTwrPl08LV08IgogICAgICAgICMgZmFzdCBtb3ZlCiAgICAgICAgQHBvcyA9IEBpbmRFbAogICAgICAgIHN0YXJ0Q3ljbGUoQGluZEVsKQogICAgICAgICAgICBkZWMgQGluZEVsCiAgICAgICAgICAgIGluYyByZWcKICAgICAgICBlbmRDeWNsZShAaW5kRWwpCiAgICBlbmQKICAgIAogICAgZGVmIHNldEtub3duQXJyRWxlbVdpdGhSKG5hbWUsaW5kZXgscmVnKQogICAgICAgICMgc2V0IG5hbWVbaW5kZXhdIHRvIHJlZwogICAgICAgIHRvQXJyPTI1NgogICAgICAgIGk9MAogICAgICAgIHdoaWxlIEBhcnJheXNbaV1bOm5hbWVdIT1uYW1lCiAgICAgICAgICAgIHRvQXJyKz1AYXJyYXlzW2ldWzpzaXplXQogICAgICAgICAgICBpKz0xCiAgICAgICAgZW5kCiAgICAgICAgdG9BcnIrPWluZGV4CiAgICAgICAgY29weVIoQGluZEVsK3RvQXJyLHJlZykKICAgIGVuZAogICAgCiAgICBkZWYgc2V0S25vd25BcnJFbGVtV2l0aE51bShuYW1lLGluZGV4LG51bSkKICAgICAgICAjIHNldCBuYW1lW2luZGV4XSB0byBudW0KICAgICAgICB0b0Fycj0yNTYKICAgICAgICBpPTAKICAgICAgICB3aGlsZSBAYXJyYXlzW2ldWzpuYW1lXSE9bmFtZQogICAgICAgICAgICB0b0Fycis9QGFycmF5c1tpXVs6c2l6ZV0KICAgICAgICAgICAgaSs9MQogICAgICAgIGVuZAogICAgICAgIHRvQXJyKz1pbmRleAogICAgICAgIHNldFIoQGluZEVsK3RvQXJyLG51bSkKICAgIGVuZAogICAgCiAgICBkZWYgc2V0VW5rbm93bkFyckVsZW1XaXRoTnVtKG5hbWUscmVnaW5kZXgsbnVtKQogICAgICAjIHNldCBuYW1lW3JlZ2luZGV4XSB0byBudW0KICAgICAgICB0b0Fycj0yNTYKICAgICAgICBpPTAKICAgICAgICB3aGlsZSBAYXJyYXlzW2ldWzpuYW1lXSE9bmFtZQogICAgICAgICAgICB0b0Fycis9QGFycmF5c1tpXVs6c2l6ZV0KICAgICAgICAgICAgaSs9MQogICAgICAgIGVuZAogICAgICAgIHNldFIoQGluZEVsLTEsbnVtKQogICAgICAgIGNvcHlSKEBpbmRFbCxyZWdpbmRleCkKICAgICAgICBjb3B5UihAaW5kRWwrMSxyZWdpbmRleCkKICAgICAgICBnb3RvUihAaW5kRWwpIAogICAgICAgIEBwcm9ncmFtIDw8ICAiWz5bLT4rPF08Wy0+KzxdPFstPis8XT4+LV0iCiAgICAgICAgQHByb2dyYW0gPDwgIj4iKnRvQXJyCiAgICAgICAgQHByb2dyYW0gPDwgIlstXSIKICAgICAgICBAcHJvZ3JhbSA8PCAiPCIqdG9BcnIKICAgICAgICBAcHJvZ3JhbSA8PCAiPFstPiIKICAgICAgICBAcHJvZ3JhbSA8PCAiPiIqdG9BcnIKICAgICAgICBAcHJvZ3JhbSA8PCAiKyIKICAgICAgICBAcHJvZ3JhbSA8PCAiPCIqdG9BcnIKICAgICAgICBAcHJvZ3JhbSA8PCAiPF0+PltbLTwrPl08LV08IgogICAgICAgIEBwb3M9QGluZEVsCiAgICBlbmQKICAgIAogICAgZGVmIHNldFVua25vd25BcnJFbGVtV2l0aFIobmFtZSxyZWdpbmRleCxyZWcpCiAgICAgICMgc2V0IG5hbWVbcmVnaW5kZXhdIHRvIHJlZwogICAgICAgIHRvQXJyPTI1NgogICAgICAgIGk9MAogICAgICAgIHdoaWxlIEBhcnJheXNbaV1bOm5hbWVdIT1uYW1lCiAgICAgICAgICAgIHRvQXJyKz1AYXJyYXlzW2ldWzpzaXplXQogICAgICAgICAgICBpKz0xCiAgICAgICAgZW5kCiAgICAgICAgY29weVIoQGluZEVsLTEscmVnKQogICAgICAgIGNvcHlSKEBpbmRFbCxyZWdpbmRleCkKICAgICAgICBjb3B5UihAaW5kRWwrMSxyZWdpbmRleCkKICAgICAgICBnb3RvUihAaW5kRWwpIAogICAgICAgIEBwcm9ncmFtIDw8ICAiWz5bLT4rPF08Wy0+KzxdPFstPis8XT4+LV0iCiAgICAgICAgQHByb2dyYW0gPDwgIj4iKnRvQXJyCiAgICAgICAgQHByb2dyYW0gPDwgIlstXSIKICAgICAgICBAcHJvZ3JhbSA8PCAiPCIqdG9BcnIKICAgICAgICBAcHJvZ3JhbSA8PCAiPFstPiIKICAgICAgICBAcHJvZ3JhbSA8PCAiPiIqdG9BcnIKICAgICAgICBAcHJvZ3JhbSA8PCAiKyIKICAgICAgICBAcHJvZ3JhbSA8PCAiPCIqdG9BcnIKICAgICAgICBAcHJvZ3JhbSA8PCAiPF0+PltbLTwrPl08LV08IgogICAgICAgIEBwb3M9QGluZEVsCiAgICBlbmQKICAgIAogICAgZGVmIG1ha2VJbml0Q29kZShudW1BcnIpCiAgICAgICAgcmVzPVtdCiAgICAgICAgbnVtQXJyLmVhY2ggeyB8bnVtfAogICAgICAgICAgcmVzIDw8ICIrIipudW0gPDwgIj4iCiAgICAgICAgfQogICAgICAgIHJlcy5qb2luKCIiKQogICAgZW5kCiAgICAKICAgIGRlZiBhZGRTdHJpbmcobmFtZSwgZGF0YSkKICAgICAgICBkZWNsYXJlQXJyYXkobmFtZSxkYXRhLmxlbmd0aCkKICAgICAgICBmb3JJbml0PWRhdGEuc3BsaXQoIiIpLmNvbGxlY3QgeyB8Y2h8IGNoLm9yZCB9CiAgICAgICAgdG9BcnI9MjU2CiAgICAgICAgaT0wCiAgICAgICAgd2hpbGUgQGFycmF5c1tpXVs6bmFtZV0hPW5hbWUKICAgICAgICAgICAgdG9BcnIrPUBhcnJheXNbaV1bOnNpemVdCiAgICAgICAgICAgIGkrPTEKICAgICAgICBlbmQKICAgICAgICBAcHJvZ3JhbS51bnNoaWZ0KCI+IioodG9BcnIrQGluZEVsKSttYWtlSW5pdENvZGUoZm9ySW5pdCkrIjwiKih0b0FycitAaW5kRWwrZGF0YS5sZW5ndGgpKSAgICAgIAogICAgZW5kCiAgICAKICAgIGRlZiBwdXRTdHIobmFtZSkKICAgICAgICB0b0Fycj0yNTYKICAgICAgICBpPTAKICAgICAgICB3aGlsZSBAYXJyYXlzW2ldWzpuYW1lXSE9bmFtZQogICAgICAgICAgICB0b0Fycis9QGFycmF5c1tpXVs6c2l6ZV0KICAgICAgICAgICAgaSs9MQogICAgICAgIGVuZAogICAgICAgIGdvdG9SKEBpbmRFbCkKICAgICAgICBAcHJvZ3JhbSA8PCAiPiIqdG9BcnIgPDwgIlsuPl08WzxdPiIgPDwgIjwiKnRvQXJyCiAgICBlbmQKICAgIAogICAgZGVmIGlmRmFsc2Uob3ApCiAgICAgICAgY2FzZSBvcAogICAgICAgIHdoZW4gOmVxCiAgICAgICAgICByZWc9QGVxUgogICAgICAgIHdoZW4gOmx0CiAgICAgICAgICByZWc9QGx0UgogICAgICAgIHdoZW4gOmd0CiAgICAgICAgICByZWc9QGd0UgogICAgICAgIGVsc2UKICAgICAgICAgIHJhaXNlICJsb2dpYyBlcnJvciIKICAgICAgICBlbmQKICAgICAgICB6ZXJvUig1KQogICAgICAgIHplcm9SKDYpCiAgICAgICAgc3RhcnRDeWNsZShyZWcpCiAgICAgICAgICBpbmMgNQogICAgICAgICAgbW92ZVJUb1IocmVnLDYpCiAgICAgICAgZW5kQ3ljbGUocmVnKQogICAgICAgIG1vdmVSVG9SKDYscmVnKQogICAgICAgIHN0YXJ0Q3ljbGUoNSkKICAgIGVuZAogICAgCiAgICBkZWYgaWZUcnVlKG9wKQogICAgICAgIGNhc2Ugb3AKICAgICAgICB3aGVuIDplcQogICAgICAgICAgcmVnPUBlcVIKICAgICAgICB3aGVuIDpsdAogICAgICAgICAgcmVnPUBsdFIKICAgICAgICB3aGVuIDpndAogICAgICAgICAgcmVnPUBndFIKICAgICAgICBlbHNlCiAgICAgICAgICByYWlzZSAibG9naWMgZXJyb3IiCiAgICAgICAgZW5kCiAgICAgICAgemVyb1IoNSkKICAgICAgICB6ZXJvUig2KQogICAgICAgIHN0YXJ0Q3ljbGUocmVnKQogICAgICAgICAgZGVjIDUKICAgICAgICAgIG1vdmVSVG9SKHJlZyw2KQogICAgICAgIGVuZEN5Y2xlKHJlZykKICAgICAgICBtb3ZlUlRvUig2LHJlZykKICAgICAgICBpbmMgNQogICAgICAgIHN0YXJ0Q3ljbGUoNSkKICAgIGVuZAogICAgCiAgICBkZWYgZW5kaWYKICAgICAgemVyb1IoNSkKICAgICAgZW5kQ3ljbGUoNSkKICAgIGVuZAogICAgCmVuZAppPTAKdG1wPVtdCgp3b3JkPVtdCmluc3RyaW5nPWZhbHNlCgpTVERJTi5yZWFkLnNwbGl0KCIiKS5lYWNoIHsgfGF8CiAgaWYgIWluc3RyaW5nCiAgICBpZiBhPT0iICIgb3IgYT09IlxuIgogICAgICB0bXAgPDwgd29yZC5qb2luKCIiKS5jaG9tcCBpZiB3b3JkLnNpemUgPjAKICAgICAgd29yZD1bXQogICAgZWxzZQogICAgICB3b3JkIDw8IGEKICAgIGVuZAogICAgaWYgYT09IlwiIgogICAgICBpbnN0cmluZz10cnVlCiAgICAgIHdvcmQ9W10KICAgIGVuZAogIGVsc2UKICAgIGlmIGE9PSJcIiIKICAgICAgIHRtcCA8PCB3b3JkLmpvaW4oIiIpLmNob21wCiAgICAgICB3b3JkPVtdCiAgICAgICBpbnN0cmluZz1mYWxzZQogICAgZWxzZQogICAgICB3b3JkIDw8IGEKICAgIGVuZAogIGVuZAp9CnRtcCA8PCB3b3JkLmpvaW4oIiIpLmNob21wCiNwdXRzIHRtcC5pbnNwZWN0CmN5Y2xlcyA9IFtdCmE9QkZDb21waWxlci5uZXcKcmVnaXN0ZXJzPWEucmVnaXN0ZXJzCndoaWxlIGk8dG1wLmxlbmd0aAogICAgY2FzZSB0bXBbaV0udXBjYXNlCiAgICB3aGVuICJNT1YiCiAgICAgICAgaWYgcmVnaXN0ZXJzLmhhc19rZXk/KHRtcFtpKzJdKQogICAgICAgICAgICBhLmNvcHlSKHJlZ2lzdGVyc1t0bXBbaSsxXV0scmVnaXN0ZXJzW3RtcFtpKzJdXSkKICAgICAgICBlbHNlCiAgICAgICAgICAgIGEuc2V0UihyZWdpc3RlcnNbdG1wW2krMV1dLCB0bXBbaSsyXS5pc19kaWdpdD8gPyAgdG1wW2krMl0udG9faTogdG1wW2krMl0ub3JkKQogICAgICAgIGVuZAogICAgICAgIGkrPTMgIAogICAgd2hlbiAiU1VCIgogICAgICAgIGlmIHJlZ2lzdGVycy5oYXNfa2V5Pyh0bXBbaSsyXSkKICAgICAgICAgICAgYS5zdWJSRnJvbVIocmVnaXN0ZXJzW3RtcFtpKzFdXSxyZWdpc3RlcnNbdG1wW2krMl1dKQogICAgICAgIGVsc2UKICAgICAgICAgICAgYS5zdWJOdW1Gcm9tUihyZWdpc3RlcnNbdG1wW2krMV1dLHRtcFtpKzJdLnRvX2kpCiAgICAgICAgZW5kCiAgICAgICAgaSs9MwogICAgd2hlbiAiQUREIgogICAgICAgIGlmIHJlZ2lzdGVycy5oYXNfa2V5Pyh0bXBbaSsyXSkKICAgICAgICAgICAgYS5hZGRSVG9SKHJlZ2lzdGVyc1t0bXBbaSsxXV0scmVnaXN0ZXJzW3RtcFtpKzJdXSkKICAgICAgICBlbHNlCiAgICAgICAgICAgIGEuYWRkTnVtVG9SKHJlZ2lzdGVyc1t0bXBbaSsxXV0sdG1wW2krMl0udG9faSkKICAgICAgICBlbmQKICAgICAgICBpKz0zCiAgICB3aGVuICJNVUwiCiAgICAgICAgYS5tdWxSb25SKHJlZ2lzdGVyc1t0bXBbaSsxXV0scmVnaXN0ZXJzW3RtcFtpKzJdXSkKICAgICAgICBpKz0zCiAgICB3aGVuICJESVYiCiAgICAgICAgYS5kaXZSb25SKHJlZ2lzdGVyc1t0bXBbaSsxXV0scmVnaXN0ZXJzW3RtcFtpKzJdXSkKICAgICAgICBpKz0zCiAgICB3aGVuICJBUlJBWSIKICAgICAgICBhLmRlY2xhcmVBcnJheSh0bXBbaSsxXSx0bXBbaSsyXS50b19pKQogICAgICAgIGkrPTMKICAgIHdoZW4gIkNNUCIKICAgICAgICBhLmNtcFJSKHJlZ2lzdGVyc1t0bXBbaSsxXV0scmVnaXN0ZXJzW3RtcFtpKzJdXSkKICAgICAgICBpKz0zCiAgICB3aGVuICJHRVQiCiAgICAgICAgaWYgcmVnaXN0ZXJzLmhhc19rZXk/KHRtcFtpKzJdKQogICAgICAgICAgICBhLmdldFVua25vd25BcnJFbGVtKHRtcFtpKzFdLHJlZ2lzdGVyc1t0bXBbaSsyXV0scmVnaXN0ZXJzW3RtcFtpKzNdXSkKICAgICAgICBlbHNlCiAgICAgICAgICAgIGEuZ2V0S25vd25BcnJFbGVtKHRtcFtpKzFdLHRtcFtpKzJdLnRvX2kscmVnaXN0ZXJzW3RtcFtpKzNdXSkKICAgICAgICBlbmQKICAgICAgICBpKz00CiAgICB3aGVuICJTRVQiCiAgICAgICAgaWYgcmVnaXN0ZXJzLmhhc19rZXk/KHRtcFtpKzJdKQogICAgICAgICAgICBpZiByZWdpc3RlcnMuaGFzX2tleT8odG1wW2krM10pCiAgICAgICAgICAgICAgICBhLnNldFVua25vd25BcnJFbGVtV2l0aFIodG1wW2krMV0scmVnaXN0ZXJzW3RtcFtpKzJdXSxyZWdpc3RlcnNbdG1wW2krM11dKQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICBhLnNldFVua25vd25BcnJFbGVtV2l0aE51bSh0bXBbaSsxXSxyZWdpc3RlcnNbdG1wW2krMl1dLHRtcFtpKzNdLnRvX2kpCiAgICAgICAgICAgIGVuZAogICAgICAgIGVsc2UKICAgICAgICAgICAgaWYgcmVnaXN0ZXJzLmhhc19rZXk/KHRtcFtpKzNdKQogICAgICAgICAgICAgICAgYS5zZXRLbm93bkFyckVsZW1XaXRoUih0bXBbaSsxXSx0bXBbaSsyXS50b19pLHJlZ2lzdGVyc1t0bXBbaSszXV0pCiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIGEuc2V0S25vd25BcnJFbGVtV2l0aE51bSh0bXBbaSsxXSx0bXBbaSsyXS50b19pLHRtcFtpKzNdLnRvX2kpCiAgICAgICAgICAgIGVuZAogICAgICAgIGVuZAogICAgICAgIGkrPTQKICAgIHdoZW4gIlBVU0giCiAgICAgICAgaWYgcmVnaXN0ZXJzLmhhc19rZXk/KHRtcFtpKzFdKQogICAgICAgICAgICBhLnB1c2hSVG9TdGFjayhyZWdpc3RlcnNbdG1wW2krMV1dKQogICAgICAgIGVsc2UKICAgICAgICAgICAgYS5wdXNoTnVtVG9TdGFjayh0bXBbaSsxXS50b19pKQogICAgICAgIGVuZAogICAgICAgIGkrPTIKICAgICAgICAKICAgIHdoZW4gIk5FIgogICAgICAgIGEuaWZGYWxzZSg6ZXEpCiAgICAgICAgaSs9MQogICAgd2hlbiAiTkwiCiAgICAgICAgYS5pZkZhbHNlKDpsdCkKICAgICAgICBpKz0xCiAgICB3aGVuICJORyIKICAgICAgICBhLmlmRmFsc2UoOmd0KQogICAgICAgIGkrPTEKICAgIHdoZW4gIkVRIgogICAgICAgIGEuaWZUcnVlKDplcSkKICAgICAgICBpKz0xCiAgICB3aGVuICJMVCIKICAgICAgICBhLmlmVHJ1ZSg6bHQpCiAgICAgICAgaSs9MQogICAgd2hlbiAiR1QiCiAgICAgICAgYS5pZlRydWUoOmd0KQogICAgICAgIGkrPTEKICAgIHdoZW4gIlBVVCIKICAgICAgICBhLm91dFIocmVnaXN0ZXJzW3RtcFtpKzFdXSkKICAgICAgICBpKz0yCiAgICB3aGVuICJQT1AiCiAgICAgICAgYS5wb3BOdW1Ub1IocmVnaXN0ZXJzW3RtcFtpKzFdXSkKICAgICAgICBpKz0yICAgIAogICAgd2hlbiAiVEFLRSIKICAgICAgICBhLmlucHV0UihyZWdpc3RlcnNbdG1wW2krMV1dKQogICAgICAgIGkrPTIKICAgIHdoZW4gIlBVVFMiCiAgICAgICAgYS5wdXRTdHIodG1wW2krMV0pCiAgICAgICAgaSs9MgogICAgd2hlbiAiSU5DIgogICAgICAgIGEuaW5jKHJlZ2lzdGVyc1t0bXBbaSsxXV0pCiAgICAgICAgaSs9MgogICAgd2hlbiAiREVDIgogICAgICAgIGEuZGVjKHJlZ2lzdGVyc1t0bXBbaSsxXV0pCiAgICAgICAgaSs9MgogICAgd2hlbiAiV0hJTEUiCiAgICAgICAgYS5zdGFydEN5Y2xlKHJlZ2lzdGVyc1t0bXBbaSsxXV0pCiAgICAgICAgY3ljbGVzIDw8IHJlZ2lzdGVyc1t0bXBbaSsxXV0KICAgICAgICBpKz0yCiAgICB3aGVuICJFTkRXSElMRSIKICAgICAgICBhLmVuZEN5Y2xlKGN5Y2xlcy5wb3ApCiAgICAgICAgaSs9MQogICAgd2hlbiAiRU5EIgogICAgICAgIGEuZW5kaWYKICAgICAgICBpKz0xCiAgICB3aGVuICJTVFJJTkciCiAgICAgICAgYS5hZGRTdHJpbmcodG1wW2krMV0sdG1wW2krMl0pCiAgICAgICAgaSs9MwogICAgZWxzZQogICAgICAgIGkrPTEKICAgIGVuZAplbmQKcHV0cyBhLmNvbXBpbGVCZg==