############################################################################
# Pyth version 1.1.0 #
# Posted before 7-18-2014 #
# #
# Added #, Utf-32 -> ascii, to win all of the "character count" challenges.#
# I agree it's dumb, but them's the rules. #
# #
# This python program is an interpreter for the pyth programming language. #
# It is still in development - expect new versions often. #
# #
# To use, provide pyth code on one line of stdin. #
# Further input on further lines. #
# Prints out resultant python code for debugging purposes, then runs the #
# pyth program. #
# #
# More information: #
# The parse function takes a string of pyth code, and returns a single #
# python expression ready to be executed. #
# general_parse is the same but for multiple expressions. #
# This program also defines the built-ins that the resultant expression #
# uses, once expanded. #
############################################################################
def parse( code , spacing= "\n " ) :
assert type ( code ) == type ( '' )
# If we've reached the end of the string, give up.
if len ( code ) == 0 :
return '' , ''
# Separate active character from the rest of the code.
active_char= code [ 0 ]
rest_code= code [ 1 :]
# Deal with numbers
if active_char in ".0123456789" :
output= active_char
while ( len ( rest_code) > 0
and rest_code[ 0 ] in ".0123456789"
and ( output+rest_code[ 0 ] ) .count ( "." ) <= 1 ) :
output+= rest_code[ 0 ]
rest_code= rest_code[ 1 :]
return output, rest_code
# String literals
if active_char== '"' :
output= active_char
while ( len ( rest_code) > 0
and output.count ( '"' ) < 2 ) :
output+= rest_code[ 0 ]
rest_code= rest_code[ 1 :]
if output[ -1 ] != '"' :
output+= '"'
return output, rest_code
# Python code literals
if active_char== '$' :
output= ''
while ( len ( rest_code) > 0
and rest_code[ 0 ] != '$' ) :
output+= rest_code[ 0 ]
rest_code= rest_code[ 1 :]
return output, rest_code[ 1 :]
# End paren is magic.
if active_char== ')' :
return '' , rest_code
# Backslash is more magic.
if active_char== '\\ ' :
if rest_code== '' :
return '' , ''
else :
return '' , '\\ ' +rest_code
# Designated variables
if active_char in variables:
return active_char, rest_code
# And for general functions
global c_to_f
global next_c_to_f
if active_char in c_to_f:
func_name, arity= c_to_f[ active_char]
init_paren = ( active_char not in no_init_paren)
# Swap what variables are used in the map, filter or reduce.
if active_char in next_c_to_f:
temp= c_to_f[ active_char]
c_to_f[ active_char] = next_c_to_f[ active_char] [ 0 ]
next_c_to_f[ active_char] = next_c_to_f[ active_char] [ 1 :] +[ temp]
# Recurse until terminated by end paren or EOF
# or received enough arguments
args_list= [ ]
parsed= 'Not empty'
while len ( args_list) != arity and parsed != '' :
parsed, rest_code= parse( rest_code)
args_list.append ( parsed)
# Build the output string.
py_code= func_name
if init_paren:
py_code+= '('
if len ( args_list) > 0 and args_list[ -1 ] == '' :
args_list= args_list[ :-1 ]
py_code+= ',' .join ( args_list)
py_code+= ')'
return py_code, rest_code
# General format functions/operators
global c_to_i
if active_char in c_to_i:
infixes, arity= c_to_i[ active_char]
# Make J and K into normal variables, if necessary.
if active_char in next_c_to_i:
c_to_i[ active_char] = next_c_to_i[ active_char]
args_list= [ ]
parsed= 'Not empty'
while len ( args_list) != arity and parsed != '' :
parsed, rest_code= parse( rest_code)
args_list.append ( parsed)
# Statements that cannot have anything after them
if active_char in end_statement:
rest_code= ")" +rest_code
py_code= infixes[ 0 ]
for i in range ( len ( args_list) ) :
py_code+= args_list[ i]
py_code+= infixes[ i+1 ]
return py_code, rest_code
# Statements:
if active_char in c_to_s:
# Handle the initial portion (head)
infixes, arity= c_to_s[ active_char]
args_list= [ ]
parsed= 'Not empty'
while len ( args_list) != arity and parsed != '' :
parsed, rest_code= parse( rest_code)
args_list.append ( parsed)
part_py_code= infixes[ 0 ]
for i in range ( len ( args_list) ) :
part_py_code+= args_list[ i]
part_py_code+= infixes[ i+1 ]
# Handle the body - ends object as well.
assert rest_code != ''
args_list= [ ]
parsed= 'Not empty'
while parsed != '' :
# Prepend print to any line starting with a function, var or safe infix.
if len ( rest_code) > 0 :
if ( ( rest_code[ 0 ] not in 'p ' and rest_code[ 0 ] in c_to_f) or
rest_code[ 0 ] in variables or
( rest_code[ 0 ] in 'JK' and c_to_i[ rest_code[ 0 ] ] == next_c_to_i[ rest_code[ 0 ] ] ) or
rest_code[ 0 ] in "@&|]'?;\" .0123456789#," ) :
rest_code= 'p"\\ n"' +rest_code
parsed, rest_code= parse( rest_code, spacing+' ' )
args_list.append ( parsed)
# Trim the '' away and combine.
if args_list[ -1 ] == '' :
args_list= args_list[ :-1 ]
all_pieces= [ part_py_code] +args_list
return spacing.join ( all_pieces) , rest_code
print ( "Something's wrong." )
print ( "Current char is " , active_char)
print ( "The rest of the code is " , rest_code)
raise NotImplementedError
import random
import copy
import string
# Function library, descriptions of everything.
# += # ~ Y - Sets
# repr # ` Y - General
def _not( a) :return not a # ! Y - General
# _[_] # @ Y - Ints
def utf32_ascii( a) : # #
if type ( a) == type ( '' ) :
utf_str= a
text_num= 0
for char in utf_str:
text_num*= ( 2 **20 +2 **16 )
text_num+= ord ( char)
out_str= ''
while text_num> 0 :
next_num= text_num%96
next_chr= chr ( next_num+31 ) if next_num else '\n '
out_str= next_chr+out_str
text_num//= 96
return out_str
else :
ascii_str= a[ 0 ]
text_num= 0
for char in ascii_str:
num= ord ( char)
text_num*= 96
if 32 <= num<= 126 :
text_num+= num-31
out_str= ''
while text_num> 0 :
next_chr= chr ( text_num%( 2 **20 +2 **16 ) )
out_str= next_chr+out_str
text_num//= ( 2 **20 +2 **16 )
return out_str
# $ is special - python literal Y - General
def mod( a, b) :return a%b # % Y - Lists, Sets
# pow # ^ Y - non num
# and # & Y - General
def times( a, b) :return a*b # * Y - sets
def _tuple( *a) :return a # ( Y - general
# ) is special - end extensible Y - general
def minus( a, b) :
if type ( a) == type ( set ( ) ) :
return a.difference ( b)
return a-b # - Y
def neg( a) : # _ Y
return -a
def plus( a, b) :
if type ( a) == type ( set ( ) ) :
return a.union ( b)
if type ( b) == type ( set ( ) ) :
return b.union ( a)
return a+b # + Y
# = deepcopy # = Y
copy = copy .deepcopy
def _list( *a) :return list ( a) # [ Y
# set # { Y
# [_] # ] Y
# in # } Y
# or # | Y
# break out of all containing # ) Y
def at_slice( a, b, c= None ) : # : Y
if c:
return a[ slice ( b, c) ]
else :
return a[ slice ( b) ]
# _.pop() # ; Y
def head( a) : # ' Y
if type ( a) == type ( 0 ) :
return a+1
return a[ 0 ]
# " is special - string literal Y
# Pairing # , Y
def lt( a, b) : # < Y
if type ( a) == type ( set ( ) ) :
return a.issubset ( b) and a!= b
return a< b
# . is special - numbers # . Y
def gt( a, b) : # > Y
if type ( a) == type ( set ( ) ) :
return a.issuperset ( b) and a!= b
return a> b
def div( a, b) :return a//b # / Y
# if else # ? Y
# 0-9 are special - numbers # 0-9 Y
# (x) #| | Y
# all # A Y
# .append() # a Y
# break # B Y
b= "\n " # b Y
# chr # C Y
def _chr( a) :
if type ( a) == type ( 0 ) :
return chr ( a)
if type ( a) == type ( '' ) :
return ord ( a[ 0 ] )
def count( a, b) :return a.count ( b) # c Y
# def # D Y
# variable - associated with map # d Y
d= ' '
# else # E Y
def lower( a) :return a.lower ( ) # e Y
# for # F Y
def _filter( a, b) : # f Y
return list ( filter ( a, b) )
# variable - associated with reduce # G Y
G= string .ascii_lowercase
def gte( a, b) : # g Y
if type ( a) == type ( set ( ) ) :
return a.issuperset ( b)
return a>= b
# variable - associated with reduce # H Y
H= { }
def read_file( ) : # h Y
a= "\n " .join ( open ( input ( ) ) )
return a
# h assigns the text of the user
# inputted file to the variable given.
# if # I Y
def _round( a, b= None ) : # i Y
if b is None :
return float ( a)
if b is 0 :
return int ( a)
return round ( a, b)
# Autoinitializing variable # J Y
def join( a, b) : # j Y
return a.join ( list ( map ( lambda N:str ( N) , b) ) )
# Autoinitializing variable # K Y
k= '' # k Y
def lrange( a) : # L Y
if type ( a) == type ( 0 ) :
return list ( range ( a) )
return list ( range ( len ( a) ) )
# len # l Y
# max # M Y
def _map( a, b) :return list ( map ( a, b) ) # m Y
N= None # N Y
# min # n Y
def rchoice( a) : # O Y
if type ( a) == type ( 0 ) :
return random .choice ( _range( a) )
return random .choice ( list ( a) )
# order (sorted with key) # o Y
def order( a, b) :
if type ( b) == type ( '' ) :
return '' .join ( sorted ( b, key= a) )
return sorted ( b, key= a)
def split( a, b= None ) : # P Y
if b:
return a.split ( b)
else :
return a.split ( )
def _print( a, b= "" ) : # p Y
print ( b, end= a)
def quotient( a, b) :return a/b # Q Y
def equal( a, b) :return a== b # q Y
# return # R Y
def _range( a, b= None ) : # r Y
if b:
return list ( range ( a, b) )
else :
return list ( range ( a) )
# sorted # S Y
def _sum( a) :
return reduce ( lambda b, c:b+c, a) # s Y
# T is associated with filter # T Y
T= 10
def tail( a) : # t Y
if type ( a) == type ( 0 ) :
return a-1
return a[ 1 :]
def upper( a) :return a.upper ( ) # U Y
def reduce ( a, b) : # u Y
acc= b[ 0 ]
seq= b[ 1 :]
while len ( seq) > 0 :
h= seq[ 0 ]
acc= a( acc, h)
seq= seq[ 1 :]
return acc
def rev( a) : return a[ ::-1 ] # V Y
# eval # v Y
# while # W Y
# input # w Y
def index( a, b) : # X Y
if b in a:
return a.index ( b)
# replicate functionality from str.find
else :
return -1
# exec(general_parse # x Y
Y= [ ] # Y Y
# any # y Y
Z= 0 # Z Y
def _zip( a, b) :return list ( zip ( a, b) ) # z Y
no_init_paren= 'fmou'
end_statement= 'BR'
variables= 'bdGHkNTYZ'
# To do: even preassociated variables deserve to be initialized.
# Variables cheat sheet:
# b = "\n"
# d is for map, d=' '
# G is for reduce, G=string.ascii_lowercase (abc..xyz)
# H is for reduce, H = {}
# k = ''
# J - Autoinitializer - copies, no stringing.
# K - Autoinitializer - can be strung (KJw), no copy.
# N = None, second option variable for map,filter,reduce
# T is for filter, second variable option for reduce, T=10
# Y = []
# Z = 0
c_to_s= {
'D' :( ( 'def ' , ':' ) , 1 ) ,
'E' :( ( 'else:' ) , 0 ) ,
'F' :( ( 'for ' , ' in ' , ':' ) , 2 ) ,
'I' :( ( 'if ' , ':' ) , 1 ) ,
'W' :( ( 'while ' , ':' ) , 1 ) ,
}
# Arbitrary format operators - use for assignment, infix, etc.
# All surrounding strings, arity
c_to_i= {
'~' :( ( '' , '+=' , '' ) , 2 ) ,
'@' :( ( '' , '[' , ']' ) , 2 ) ,
'&' :( ( '(' , ' and ' , ')' ) , 2 ) ,
'|' :( ( '(' , ' or ' , ')' ) , 2 ) ,
'=' :( ( '' , '=copy(' , ')' ) , 2 ) ,
']' :( ( '[' , ']' ) , 1 ) ,
'}' :( ( '(' , ' in ' , ')' ) , 2 ) ,
'?' :( ( '(' , ' if ' , ' else ' , ')' ) , 3 ) ,
',' :( ( '(' , ',' , ')' ) , 2 ) ,
';' :( ( '' , '.pop()' , ) , 1 ) ,
'a' :( ( '' , '.append(' , ')' ) , 2 ) ,
'B' :( ( 'break' , ) , 0 ) ,
'J' :( ( 'J=copy(' , ')' ) , 1 ) ,
'K' :( ( 'K=' , '' ) , 1 ) ,
'R' :( ( 'return ' , '' ) , 1 ) ,
'x' :( ( 'exec(general_parse(' , '))' ) , 1 ) ,
}
# Simple functions only.
# Extensible is allowed, nothing else complicated is.
# -1 means extensible
# name,arity
c_to_f= {
'`' :( 'repr' , 1 ) ,
'!' :( '_not' , 1 ) ,
'#' :( 'utf32_ascii' , 1 ) ,
'%' :( 'mod' , 2 ) ,
'^' :( 'pow' , 2 ) ,
'*' :( 'times' , 2 ) ,
'(' :( '_tuple' , -1 ) ,
'-' :( 'minus' , 2 ) ,
'_' :( 'neg_1r' , 1 ) ,
'+' :( 'plus' , 2 ) ,
'[' :( '_list' , -1 ) ,
'{' :( 'set' , 1 ) ,
"'" :( 'head' , 1 ) ,
':' :( 'at_slice' , 3 ) ,
'<' :( 'lt' , 2 ) ,
'>' :( 'gt' , 2 ) ,
'/' :( 'div' , 2 ) ,
' ' :( '' , 1 ) ,
'\t ' :( '' , 1 ) ,
'A' :( 'all' , 1 ) ,
'C' :( '_chr' , 1 ) ,
'c' :( 'count' , 2 ) ,
'e' :( 'lower' , 1 ) ,
'f' :( '_filter(lambda T:' , 2 ) ,
'g' :( 'gte' , 2 ) ,
'h' :( 'read_file' , 0 ) ,
'i' :( '_round' , 2 ) ,
'j' :( 'join' , 2 ) ,
'L' :( 'lrange' , 1 ) ,
'l' :( 'len' , 1 ) ,
'M' :( 'max' , 1 ) ,
'm' :( '_map(lambda d:' , 2 ) ,
'O' :( 'rchoice' , 1 ) ,
'o' :( 'order(lambda N:' , 2 ) ,
'P' :( 'split' , 2 ) ,
'p' :( '_print' , 2 ) ,
'Q' :( 'quotient' , 2 ) ,
'q' :( 'equal' , 2 ) ,
'r' :( '_range' , 2 ) ,
'S' :( 'sorted' , 1 ) ,
's' :( '_sum' , 1 ) ,
't' :( 'tail' , 1 ) ,
'U' :( 'upper' , 1 ) ,
'u' :( 'reduce(lambda G,H:' , 2 ) ,
'V' :( 'rev' , 1 ) ,
'v' :( 'eval' , 1 ) ,
'w' :( 'input' , 0 ) ,
'X' :( 'index' , 2 ) ,
'z' :( '_zip' , 2 ) ,
}
# Gives next function header to use - for filter, map, reduce.
# map: d, k, b
# filter: T, Y, Z
# order: N, Z,
# reduce: (G,H), (N,T)
next_c_to_f= {
'f' :[ ( '_filter(lambda Y:' , 2 ) , ( '_filter(lambda Z:' , 2 ) , ] ,
'm' :[ ( '_map(lambda k:' , 2 ) , ( '_map(lambda b:' , 2 ) , ] ,
'o' :[ ( 'order(lambda Z:' , 2 ) , ] ,
'u' :[ ( 'reduce(lambda N,T:' , 2 ) , ] ,
}
# For autoinitializers. One shot, not rotating.
next_c_to_i= {
'J' :( ( 'J' ) , 0 ) ,
'K' :( ( 'K' ) , 0 ) ,
}
assert set ( c_to_f.keys ( ) ) &set ( c_to_i.keys ( ) ) == set ( )
# Run it!
def general_parse( code ) :
args_list= [ ]
parsed= 'Not empty'
while parsed != '' :
# Prepend print to any line starting with a function, var or safe infix.
if len ( code ) > 0 :
if ( ( code [ 0 ] not in 'p ' and code [ 0 ] in c_to_f) or
code [ 0 ] in variables or
( code [ 0 ] in 'JK' and c_to_i[ code [ 0 ] ] == next_c_to_i[ code [ 0 ] ] ) or
code [ 0 ] in "@&|]'?;\" .0123456789#," ) :
code = 'p"\\ n"' +code
parsed, code = parse( code )
# Necessary for backslash not to infinite loop
if code and code [ 0 ] == '\\ ' :
code = code [ 1 :]
args_list.append ( parsed)
# Build the output string.
py_code= '\n ' .join ( args_list[ :-1 ] )
return py_code
code = input ( )
print ( code )
py_code= general_parse( code )
print ( py_code)
print ( '=' *50 )
exec ( py_code)
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojICAgICAgICAgICAgICAgICAgICAgICAgICAgIFB5dGggdmVyc2lvbiAxLjEuMCAgICAgICAgICAgICAgICAgICAgICAgICAgICAjCiMgICAgICAgICAgICAgICAgICAgICAgICAgIFBvc3RlZCBiZWZvcmUgNy0xOC0yMDE0ICAgICAgICAgICAgICAgICAgICAgICAgICMKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIwojIEFkZGVkICMsIFV0Zi0zMiAtPiBhc2NpaSwgdG8gd2luIGFsbCBvZiB0aGUgImNoYXJhY3RlciBjb3VudCIgY2hhbGxlbmdlcy4jCiMgSSBhZ3JlZSBpdCdzIGR1bWIsIGJ1dCB0aGVtJ3MgdGhlIHJ1bGVzLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIwojIFRoaXMgcHl0aG9uIHByb2dyYW0gaXMgYW4gaW50ZXJwcmV0ZXIgZm9yIHRoZSBweXRoIHByb2dyYW1taW5nIGxhbmd1YWdlLiAjCiMgSXQgaXMgc3RpbGwgaW4gZGV2ZWxvcG1lbnQgLSBleHBlY3QgbmV3IHZlcnNpb25zIG9mdGVuLiAgICAgICAgICAgICAgICAgICMKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIwojIFRvIHVzZSwgcHJvdmlkZSBweXRoIGNvZGUgb24gb25lIGxpbmUgb2Ygc3RkaW4uICAgICAgICAgICAgICAgICAgICAgICAgICAjCiMgRnVydGhlciBpbnB1dCBvbiBmdXJ0aGVyIGxpbmVzLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMKIyBQcmludHMgb3V0IHJlc3VsdGFudCBweXRob24gY29kZSBmb3IgZGVidWdnaW5nIHB1cnBvc2VzLCB0aGVuIHJ1bnMgdGhlICAgIwojIHB5dGggcHJvZ3JhbS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMKIyBNb3JlIGluZm9ybWF0aW9uOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIwojIFRoZSBwYXJzZSBmdW5jdGlvbiB0YWtlcyBhIHN0cmluZyBvZiBweXRoIGNvZGUsIGFuZCByZXR1cm5zIGEgc2luZ2xlICAgICAjCiMgcHl0aG9uIGV4cHJlc3Npb24gcmVhZHkgdG8gYmUgZXhlY3V0ZWQuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMKIyBnZW5lcmFsX3BhcnNlIGlzIHRoZSBzYW1lIGJ1dCBmb3IgbXVsdGlwbGUgZXhwcmVzc2lvbnMuICAgICAgICAgICAgICAgICAgIwojIFRoaXMgcHJvZ3JhbSBhbHNvIGRlZmluZXMgdGhlIGJ1aWx0LWlucyB0aGF0IHRoZSByZXN1bHRhbnQgZXhwcmVzc2lvbiAgICAjCiMgdXNlcywgb25jZSBleHBhbmRlZC4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKZGVmIHBhcnNlKGNvZGUsc3BhY2luZz0iXG4gIik6CiAgICBhc3NlcnQgdHlwZShjb2RlKT09dHlwZSgnJykKICAgICMgSWYgd2UndmUgcmVhY2hlZCB0aGUgZW5kIG9mIHRoZSBzdHJpbmcsIGdpdmUgdXAuCiAgICBpZiBsZW4oY29kZSk9PTA6CiAgICAgICAgcmV0dXJuICcnLCcnCiAgICAjIFNlcGFyYXRlIGFjdGl2ZSBjaGFyYWN0ZXIgZnJvbSB0aGUgcmVzdCBvZiB0aGUgY29kZS4KICAgIGFjdGl2ZV9jaGFyPWNvZGVbMF0KICAgIHJlc3RfY29kZT1jb2RlWzE6XQogICAgIyBEZWFsIHdpdGggbnVtYmVycwogICAgaWYgYWN0aXZlX2NoYXIgaW4gIi4wMTIzNDU2Nzg5IjoKICAgICAgICBvdXRwdXQ9YWN0aXZlX2NoYXIKICAgICAgICB3aGlsZSAobGVuKHJlc3RfY29kZSk+MAogICAgICAgICAgICAgICBhbmQgcmVzdF9jb2RlWzBdIGluICIuMDEyMzQ1Njc4OSIKICAgICAgICAgICAgICAgYW5kIChvdXRwdXQrcmVzdF9jb2RlWzBdKS5jb3VudCgiLiIpPD0xKToKICAgICAgICAgICAgb3V0cHV0Kz1yZXN0X2NvZGVbMF0KICAgICAgICAgICAgcmVzdF9jb2RlPXJlc3RfY29kZVsxOl0KICAgICAgICByZXR1cm4gb3V0cHV0LHJlc3RfY29kZQogICAgIyBTdHJpbmcgbGl0ZXJhbHMKICAgIGlmIGFjdGl2ZV9jaGFyPT0nIic6CiAgICAgICAgb3V0cHV0PWFjdGl2ZV9jaGFyCiAgICAgICAgd2hpbGUgKGxlbihyZXN0X2NvZGUpPjAKICAgICAgICAgICAgICAgYW5kIG91dHB1dC5jb3VudCgnIicpPDIpOgogICAgICAgICAgICBvdXRwdXQrPXJlc3RfY29kZVswXQogICAgICAgICAgICByZXN0X2NvZGU9cmVzdF9jb2RlWzE6XQogICAgICAgIGlmIG91dHB1dFstMV0hPSciJzoKICAgICAgICAgICAgb3V0cHV0Kz0nIicKICAgICAgICByZXR1cm4gb3V0cHV0LHJlc3RfY29kZQogICAgIyBQeXRob24gY29kZSBsaXRlcmFscwogICAgaWYgYWN0aXZlX2NoYXI9PSckJzoKICAgICAgICBvdXRwdXQ9JycKICAgICAgICB3aGlsZSAobGVuKHJlc3RfY29kZSk+MAogICAgICAgICAgICAgICBhbmQgcmVzdF9jb2RlWzBdIT0nJCcpOgogICAgICAgICAgICBvdXRwdXQrPXJlc3RfY29kZVswXQogICAgICAgICAgICByZXN0X2NvZGU9cmVzdF9jb2RlWzE6XQogICAgICAgIHJldHVybiBvdXRwdXQscmVzdF9jb2RlWzE6XQogICAgIyBFbmQgcGFyZW4gaXMgbWFnaWMuCiAgICBpZiBhY3RpdmVfY2hhcj09JyknOgogICAgICAgIHJldHVybiAnJyxyZXN0X2NvZGUKICAgICMgQmFja3NsYXNoIGlzIG1vcmUgbWFnaWMuCiAgICBpZiBhY3RpdmVfY2hhcj09J1xcJzoKICAgICAgICBpZiByZXN0X2NvZGU9PScnOgogICAgICAgICAgICByZXR1cm4gJycsJycKICAgICAgICBlbHNlOgogICAgICAgICAgICByZXR1cm4gJycsJ1xcJytyZXN0X2NvZGUKICAgICMgRGVzaWduYXRlZCB2YXJpYWJsZXMKICAgIGlmIGFjdGl2ZV9jaGFyIGluIHZhcmlhYmxlczoKICAgICAgICByZXR1cm4gYWN0aXZlX2NoYXIscmVzdF9jb2RlCiAgICAjIEFuZCBmb3IgZ2VuZXJhbCBmdW5jdGlvbnMKICAgIGdsb2JhbCBjX3RvX2YKICAgIGdsb2JhbCBuZXh0X2NfdG9fZgogICAgaWYgYWN0aXZlX2NoYXIgaW4gY190b19mOgogICAgICAgIGZ1bmNfbmFtZSxhcml0eT1jX3RvX2ZbYWN0aXZlX2NoYXJdCiAgICAgICAgaW5pdF9wYXJlbiA9IChhY3RpdmVfY2hhciBub3QgaW4gbm9faW5pdF9wYXJlbikKICAgICAgICAjIFN3YXAgd2hhdCB2YXJpYWJsZXMgYXJlIHVzZWQgaW4gdGhlIG1hcCwgZmlsdGVyIG9yIHJlZHVjZS4KICAgICAgICBpZiBhY3RpdmVfY2hhciBpbiBuZXh0X2NfdG9fZjoKICAgICAgICAgICAgdGVtcD1jX3RvX2ZbYWN0aXZlX2NoYXJdCiAgICAgICAgICAgIGNfdG9fZlthY3RpdmVfY2hhcl09bmV4dF9jX3RvX2ZbYWN0aXZlX2NoYXJdWzBdCiAgICAgICAgICAgIG5leHRfY190b19mW2FjdGl2ZV9jaGFyXT1uZXh0X2NfdG9fZlthY3RpdmVfY2hhcl1bMTpdK1t0ZW1wXQogICAgICAgICMgUmVjdXJzZSB1bnRpbCB0ZXJtaW5hdGVkIGJ5IGVuZCBwYXJlbiBvciBFT0YKICAgICAgICAjIG9yIHJlY2VpdmVkIGVub3VnaCBhcmd1bWVudHMKICAgICAgICBhcmdzX2xpc3Q9W10KICAgICAgICBwYXJzZWQ9J05vdCBlbXB0eScKICAgICAgICB3aGlsZSBsZW4oYXJnc19saXN0KSAhPSBhcml0eSBhbmQgcGFyc2VkICE9ICcnOgogICAgICAgICAgICBwYXJzZWQscmVzdF9jb2RlPXBhcnNlKHJlc3RfY29kZSkKICAgICAgICAgICAgYXJnc19saXN0LmFwcGVuZChwYXJzZWQpCiAgICAgICAgIyBCdWlsZCB0aGUgb3V0cHV0IHN0cmluZy4KICAgICAgICBweV9jb2RlPWZ1bmNfbmFtZQogICAgICAgIGlmIGluaXRfcGFyZW46CiAgICAgICAgICAgIHB5X2NvZGUrPScoJwogICAgICAgIGlmIGxlbihhcmdzX2xpc3QpPjAgYW5kIGFyZ3NfbGlzdFstMV09PScnOgogICAgICAgICAgICBhcmdzX2xpc3Q9YXJnc19saXN0WzotMV0KICAgICAgICBweV9jb2RlKz0nLCcuam9pbihhcmdzX2xpc3QpCiAgICAgICAgcHlfY29kZSs9JyknCiAgICAgICAgcmV0dXJuIHB5X2NvZGUscmVzdF9jb2RlCiAgICAjIEdlbmVyYWwgZm9ybWF0IGZ1bmN0aW9ucy9vcGVyYXRvcnMKICAgIGdsb2JhbCBjX3RvX2kKICAgIGlmIGFjdGl2ZV9jaGFyIGluIGNfdG9faToKICAgICAgICBpbmZpeGVzLGFyaXR5PWNfdG9faVthY3RpdmVfY2hhcl0KICAgICAgICAjIE1ha2UgSiBhbmQgSyBpbnRvIG5vcm1hbCB2YXJpYWJsZXMsIGlmIG5lY2Vzc2FyeS4KICAgICAgICBpZiBhY3RpdmVfY2hhciBpbiBuZXh0X2NfdG9faToKICAgICAgICAgICAgY190b19pW2FjdGl2ZV9jaGFyXT1uZXh0X2NfdG9faVthY3RpdmVfY2hhcl0KICAgICAgICBhcmdzX2xpc3Q9W10KICAgICAgICBwYXJzZWQ9J05vdCBlbXB0eScKICAgICAgICB3aGlsZSBsZW4oYXJnc19saXN0KSAhPSBhcml0eSBhbmQgcGFyc2VkICE9ICcnOgogICAgICAgICAgICBwYXJzZWQscmVzdF9jb2RlPXBhcnNlKHJlc3RfY29kZSkKICAgICAgICAgICAgYXJnc19saXN0LmFwcGVuZChwYXJzZWQpCiAgICAgICAgIyBTdGF0ZW1lbnRzIHRoYXQgY2Fubm90IGhhdmUgYW55dGhpbmcgYWZ0ZXIgdGhlbQogICAgICAgIGlmIGFjdGl2ZV9jaGFyIGluIGVuZF9zdGF0ZW1lbnQ6CiAgICAgICAgICAgIHJlc3RfY29kZT0iKSIrcmVzdF9jb2RlCiAgICAgICAgcHlfY29kZT1pbmZpeGVzWzBdCiAgICAgICAgZm9yIGkgaW4gcmFuZ2UobGVuKGFyZ3NfbGlzdCkpOgogICAgICAgICAgICBweV9jb2RlKz1hcmdzX2xpc3RbaV0KICAgICAgICAgICAgcHlfY29kZSs9aW5maXhlc1tpKzFdCiAgICAgICAgcmV0dXJuIHB5X2NvZGUsIHJlc3RfY29kZQogICAgIyBTdGF0ZW1lbnRzOgogICAgaWYgYWN0aXZlX2NoYXIgaW4gY190b19zOgogICAgICAgICMgSGFuZGxlIHRoZSBpbml0aWFsIHBvcnRpb24gKGhlYWQpCiAgICAgICAgaW5maXhlcyxhcml0eT1jX3RvX3NbYWN0aXZlX2NoYXJdCiAgICAgICAgYXJnc19saXN0PVtdCiAgICAgICAgcGFyc2VkPSdOb3QgZW1wdHknCiAgICAgICAgd2hpbGUgbGVuKGFyZ3NfbGlzdCkgIT0gYXJpdHkgYW5kIHBhcnNlZCAhPSAnJzoKICAgICAgICAgICAgcGFyc2VkLHJlc3RfY29kZT1wYXJzZShyZXN0X2NvZGUpCiAgICAgICAgICAgIGFyZ3NfbGlzdC5hcHBlbmQocGFyc2VkKQogICAgICAgIHBhcnRfcHlfY29kZT1pbmZpeGVzWzBdCiAgICAgICAgZm9yIGkgaW4gcmFuZ2UobGVuKGFyZ3NfbGlzdCkpOgogICAgICAgICAgICBwYXJ0X3B5X2NvZGUrPWFyZ3NfbGlzdFtpXQogICAgICAgICAgICBwYXJ0X3B5X2NvZGUrPWluZml4ZXNbaSsxXQogICAgICAgICMgSGFuZGxlIHRoZSBib2R5IC0gZW5kcyBvYmplY3QgYXMgd2VsbC4KICAgICAgICBhc3NlcnQgcmVzdF9jb2RlICE9ICcnCiAgICAgICAgYXJnc19saXN0PVtdCiAgICAgICAgcGFyc2VkPSdOb3QgZW1wdHknCiAgICAgICAgd2hpbGUgcGFyc2VkICE9ICcnOgogICAgICAgICAgICAjIFByZXBlbmQgcHJpbnQgdG8gYW55IGxpbmUgc3RhcnRpbmcgd2l0aCBhIGZ1bmN0aW9uLCB2YXIgb3Igc2FmZSBpbmZpeC4KICAgICAgICAgICAgaWYgbGVuKHJlc3RfY29kZSk+MDoKICAgICAgICAgICAgICAgIGlmICgocmVzdF9jb2RlWzBdIG5vdCBpbiAncCAnIGFuZCByZXN0X2NvZGVbMF0gaW4gY190b19mKSBvcgogICAgICAgICAgICAgICAgcmVzdF9jb2RlWzBdIGluIHZhcmlhYmxlcyBvcgogICAgICAgICAgICAgICAgKHJlc3RfY29kZVswXSBpbiAnSksnIGFuZCBjX3RvX2lbcmVzdF9jb2RlWzBdXT09bmV4dF9jX3RvX2lbcmVzdF9jb2RlWzBdXSkgb3IKICAgICAgICAgICAgICAgIHJlc3RfY29kZVswXSBpbiAiQCZ8XSc/O1wiLjAxMjM0NTY3ODkjLCIpOgogICAgICAgICAgICAgICAgICAgIHJlc3RfY29kZT0ncCJcXG4iJytyZXN0X2NvZGUKICAgICAgICAgICAgcGFyc2VkLHJlc3RfY29kZT1wYXJzZShyZXN0X2NvZGUsc3BhY2luZysnICcpCiAgICAgICAgICAgIGFyZ3NfbGlzdC5hcHBlbmQocGFyc2VkKQogICAgICAgICMgVHJpbSB0aGUgJycgYXdheSBhbmQgY29tYmluZS4KICAgICAgICBpZiBhcmdzX2xpc3RbLTFdPT0nJzoKICAgICAgICAgICAgYXJnc19saXN0PWFyZ3NfbGlzdFs6LTFdCiAgICAgICAgYWxsX3BpZWNlcz1bcGFydF9weV9jb2RlXSthcmdzX2xpc3QKICAgICAgICByZXR1cm4gc3BhY2luZy5qb2luKGFsbF9waWVjZXMpLHJlc3RfY29kZQogICAgcHJpbnQoIlNvbWV0aGluZydzIHdyb25nLiIpCiAgICBwcmludCgiQ3VycmVudCBjaGFyIGlzICIsYWN0aXZlX2NoYXIpCiAgICBwcmludCgiVGhlIHJlc3Qgb2YgdGhlIGNvZGUgaXMgIixyZXN0X2NvZGUpCiAgICByYWlzZSBOb3RJbXBsZW1lbnRlZEVycm9yCgppbXBvcnQgcmFuZG9tCmltcG9ydCBjb3B5CmltcG9ydCBzdHJpbmcKIyBGdW5jdGlvbiBsaWJyYXJ5LCBkZXNjcmlwdGlvbnMgb2YgZXZlcnl0aGluZy4KIyArPSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB+ICAgICBZIC0gU2V0cwojIHJlcHIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGAgICAgIFkgLSBHZW5lcmFsCmRlZiBfbm90KGEpOnJldHVybiBub3QgYSAgICAgICAgICAgICMgISAgICAgWSAtIEdlbmVyYWwKIyBfW19dICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBAICAgICBZIC0gSW50cwpkZWYgdXRmMzJfYXNjaWkoYSk6ICAgICAgICAgICAgICAgICAjICMKICAgIGlmIHR5cGUoYSk9PXR5cGUoJycpOgogICAgICAgIHV0Zl9zdHI9YQogICAgICAgIHRleHRfbnVtPTAKICAgICAgICBmb3IgY2hhciBpbiB1dGZfc3RyOgogICAgICAgICAgICB0ZXh0X251bSo9KDIqKjIwKzIqKjE2KQogICAgICAgICAgICB0ZXh0X251bSs9b3JkKGNoYXIpCiAgICAgICAgb3V0X3N0cj0nJwogICAgICAgIHdoaWxlIHRleHRfbnVtPjA6CiAgICAgICAgICAgIG5leHRfbnVtPXRleHRfbnVtJTk2CiAgICAgICAgICAgIG5leHRfY2hyPWNocihuZXh0X251bSszMSkgaWYgbmV4dF9udW0gZWxzZSAnXG4nCiAgICAgICAgICAgIG91dF9zdHI9bmV4dF9jaHIrb3V0X3N0cgogICAgICAgICAgICB0ZXh0X251bS8vPTk2CiAgICAgICAgcmV0dXJuIG91dF9zdHIKICAgIGVsc2U6CiAgICAgICAgYXNjaWlfc3RyPWFbMF0KICAgICAgICB0ZXh0X251bT0wCiAgICAgICAgZm9yIGNoYXIgaW4gYXNjaWlfc3RyOgogICAgICAgICAgICBudW09b3JkKGNoYXIpCiAgICAgICAgICAgIHRleHRfbnVtKj05NgogICAgICAgICAgICBpZiAzMjw9bnVtPD0xMjY6CiAgICAgICAgICAgICAgICB0ZXh0X251bSs9bnVtLTMxCiAgICAgICAgb3V0X3N0cj0nJwogICAgICAgIHdoaWxlIHRleHRfbnVtPjA6CiAgICAgICAgICAgIG5leHRfY2hyPWNocih0ZXh0X251bSUoMioqMjArMioqMTYpKQogICAgICAgICAgICBvdXRfc3RyPW5leHRfY2hyK291dF9zdHIKICAgICAgICAgICAgdGV4dF9udW0vLz0oMioqMjArMioqMTYpCiAgICAgICAgcmV0dXJuIG91dF9zdHIKCiMgJCBpcyBzcGVjaWFsIC0gcHl0aG9uIGxpdGVyYWwgICAgICAgICAgICAgWSAtIEdlbmVyYWwKZGVmIG1vZChhLGIpOnJldHVybiBhJWIgICAgICAgICAgICAgIyAlICAgICBZIC0gTGlzdHMsIFNldHMKIyBwb3cgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBeICAgICBZIC0gbm9uIG51bQojIGFuZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICYgICAgIFkgLSBHZW5lcmFsCmRlZiB0aW1lcyhhLGIpOnJldHVybiBhKmIgICAgICAgICAgICMgKiAgICAgWSAtIHNldHMKZGVmIF90dXBsZSgqYSk6cmV0dXJuIGEgICAgICAgICAgICAgIyAoICAgICBZIC0gZ2VuZXJhbAojICkgaXMgc3BlY2lhbCAtIGVuZCBleHRlbnNpYmxlICAgICAgICAgICAgIFkgLSBnZW5lcmFsCmRlZiBtaW51cyhhLGIpOgogICAgaWYgdHlwZShhKT09dHlwZShzZXQoKSk6CiAgICAgICAgcmV0dXJuIGEuZGlmZmVyZW5jZShiKQogICAgcmV0dXJuIGEtYiAgICAgICAgICAgICAgICAgICAgICAjIC0gICAgIFkKZGVmIG5lZyhhKTogICAgICAgICAgICAgICAgICAgICAgICAgIyBfICAgICBZCiAgICAgICAgcmV0dXJuIC1hCmRlZiBwbHVzKGEsYik6CiAgICBpZiB0eXBlKGEpPT10eXBlKHNldCgpKToKICAgICAgICByZXR1cm4gYS51bmlvbihiKQogICAgaWYgdHlwZShiKT09dHlwZShzZXQoKSk6CiAgICAgICAgcmV0dXJuIGIudW5pb24oYSkKICAgIHJldHVybiBhK2IgICAgICAgICAgICAgICAgICAgICAgIyArICAgICBZCiMgPSBkZWVwY29weSAgICAgICAgICAgICAgICAgICAgICAgICMgPSAgICAgWQpjb3B5ID0gY29weS5kZWVwY29weQpkZWYgX2xpc3QoKmEpOnJldHVybiBsaXN0KGEpICAgICAgICAjIFsgICAgIFkKIyBzZXQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB7ICAgICBZCiMgW19dICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgXSAgICAgWQojIGluICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIH0gICAgIFkKIyBvciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB8ICAgICBZCiMgYnJlYWsgb3V0IG9mIGFsbCBjb250YWluaW5nICAgICAgICMgKSAgICAgWQpkZWYgYXRfc2xpY2UoYSxiLGM9Tm9uZSk6ICAgICAgICAgICAjIDogICAgIFkKICAgIGlmIGM6CiAgICAgICAgcmV0dXJuIGFbc2xpY2UoYixjKV0KICAgIGVsc2U6CiAgICAgICAgcmV0dXJuIGFbc2xpY2UoYildCiMgXy5wb3AoKSAgICAgICAgICAgICAgICAgICAgICAgICAgICMgOyAgICAgWQpkZWYgaGVhZChhKTogICAgICAgICAgICAgICAgICAgICAgICAjICcgICAgIFkKICAgIGlmIHR5cGUoYSk9PXR5cGUoMCk6CiAgICAgICAgcmV0dXJuIGErMQogICAgcmV0dXJuIGFbMF0gIAojICIgaXMgc3BlY2lhbCAtIHN0cmluZyBsaXRlcmFsICAgICAgICAgICAgIFkKIyBQYWlyaW5nICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAsICAgICBZCmRlZiBsdChhLGIpOiAgICAgICAgICAgICAgICAgICAgICAgICMgPCAgICAgWQogICAgaWYgdHlwZShhKT09dHlwZShzZXQoKSk6CiAgICAgICAgcmV0dXJuIGEuaXNzdWJzZXQoYikgYW5kIGEhPWIKICAgIHJldHVybiBhPGIKIyAuIGlzIHNwZWNpYWwgLSBudW1iZXJzICAgICAgICAgICAgIyAuICAgICBZCmRlZiBndChhLGIpOiAgICAgICAgICAgICAgICAgICAgICAgICMgPiAgICAgWQogICAgaWYgdHlwZShhKT09dHlwZShzZXQoKSk6CiAgICAgICAgcmV0dXJuIGEuaXNzdXBlcnNldChiKSBhbmQgYSE9YgogICAgcmV0dXJuIGE+YgpkZWYgZGl2KGEsYik6cmV0dXJuIGEvL2IgICAgICAgICAgICAjIC8gICAgIFkKIyBpZiBlbHNlICAgICAgICAgICAgICAgICAgICAgICAgICAgIyA/ICAgICBZCiMgMC05IGFyZSBzcGVjaWFsIC0gbnVtYmVycyAgICAgICAgICMgMC05ICAgWQojICh4KSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjfCB8ICAgIFkKIyBhbGwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBICAgICBZCiMgLmFwcGVuZCgpICAgICAgICAgICAgICAgICAgICAgICAgICMgYSAgICAgWQojIGJyZWFrICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEIgICAgIFkKYj0iXG4iICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBiICAgICBZCiMgY2hyICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQyAgICAgWQpkZWYgX2NocihhKToKICAgIGlmIHR5cGUoYSk9PXR5cGUoMCk6CiAgICAgICAgcmV0dXJuIGNocihhKQogICAgaWYgdHlwZShhKT09dHlwZSgnJyk6CiAgICAgICAgcmV0dXJuIG9yZChhWzBdKQpkZWYgY291bnQoYSxiKTpyZXR1cm4gYS5jb3VudChiKSAgICAjIGMgICAgIFkKIyBkZWYgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBEICAgICBZCiMgdmFyaWFibGUgLSBhc3NvY2lhdGVkIHdpdGggbWFwICAgICMgZCAgICAgWQpkPScgJwojIGVsc2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEUgICAgIFkKZGVmIGxvd2VyKGEpOnJldHVybiBhLmxvd2VyKCkgICAgICAgIyBlICAgICBZCiMgZm9yICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgRiAgICAgWQpkZWYgX2ZpbHRlcihhLGIpOiAgICAgICAgICAgICAgICAgICAjIGYgICAgIFkKICAgIHJldHVybiBsaXN0KGZpbHRlcihhLGIpKQojIHZhcmlhYmxlIC0gYXNzb2NpYXRlZCB3aXRoIHJlZHVjZSAjIEcgICAgIFkKRz1zdHJpbmcuYXNjaWlfbG93ZXJjYXNlCmRlZiBndGUoYSxiKTogICAgICAgICAgICAgICAgICAgICAgICMgZyAgICAgWQogICAgaWYgdHlwZShhKT09dHlwZShzZXQoKSk6CiAgICAgICAgcmV0dXJuIGEuaXNzdXBlcnNldChiKQogICAgcmV0dXJuIGE+PWIKIyB2YXJpYWJsZSAtIGFzc29jaWF0ZWQgd2l0aCByZWR1Y2UgIyBIICAgICBZCkg9e30KZGVmIHJlYWRfZmlsZSgpOiAgICAgICAgICAgICAgICAgICAgIyBoICAgICBZCiAgICBhPSJcbiIuam9pbihvcGVuKGlucHV0KCkpKQogICAgcmV0dXJuIGEKIyBoIGFzc2lnbnMgdGhlIHRleHQgb2YgdGhlIHVzZXIgCiMgaW5wdXR0ZWQgZmlsZSB0byB0aGUgdmFyaWFibGUgZ2l2ZW4uCiMgaWYgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgSSAgICAgWQpkZWYgX3JvdW5kKGEsYj1Ob25lKTogICAgICAgICAgICAgICAjIGkgICAgIFkKICAgIGlmIGIgaXMgTm9uZToKICAgICAgICByZXR1cm4gZmxvYXQoYSkKICAgIGlmIGIgaXMgMDoKICAgICAgICByZXR1cm4gaW50KGEpCiAgICByZXR1cm4gcm91bmQoYSxiKQojIEF1dG9pbml0aWFsaXppbmcgdmFyaWFibGUgICAgICAgICAjIEogICAgIFkKZGVmIGpvaW4oYSxiKTogICAgICAgICAgICAgICAgICAgICAgIyBqICAgICBZCiAgICByZXR1cm4gYS5qb2luKGxpc3QobWFwKGxhbWJkYSBOOnN0cihOKSxiKSkpCiMgQXV0b2luaXRpYWxpemluZyB2YXJpYWJsZSAgICAgICAgICMgSyAgICAgWQprPScnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGsgICAgIFkKZGVmIGxyYW5nZShhKTogICAgICAgICAgICAgICAgICAgICAgIyBMICAgICBZCiAgICBpZiB0eXBlKGEpPT10eXBlKDApOgogICAgICAgIHJldHVybiBsaXN0KHJhbmdlKGEpKQogICAgcmV0dXJuIGxpc3QocmFuZ2UobGVuKGEpKSkKIyBsZW4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBsICAgICBZCiMgbWF4ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgTSAgICAgWQpkZWYgX21hcChhLGIpOnJldHVybiBsaXN0KG1hcChhLGIpKSAjIG0gICAgIFkKTj1Ob25lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBOICAgICBZCiMgbWluICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbiAgICAgWQpkZWYgcmNob2ljZShhKTogICAgICAgICAgICAgICAgICAgICAjIE8gICAgIFkKICAgIGlmIHR5cGUoYSk9PXR5cGUoMCk6CiAgICAgICAgcmV0dXJuIHJhbmRvbS5jaG9pY2UoX3JhbmdlKGEpKQogICAgcmV0dXJuIHJhbmRvbS5jaG9pY2UobGlzdChhKSkKIyBvcmRlciAoc29ydGVkIHdpdGgga2V5KSAgICAgICAgICAgIyBvICAgICBZCmRlZiBvcmRlcihhLGIpOgogICAgaWYgdHlwZShiKT09dHlwZSgnJyk6CiAgICAgICAgcmV0dXJuICcnLmpvaW4oc29ydGVkKGIsIGtleT1hKSkKICAgIHJldHVybiBzb3J0ZWQoYiwga2V5PWEpCmRlZiBzcGxpdChhLGI9Tm9uZSk6ICAgICAgICAgICAgICAgICMgUCAgICAgWQogICAgaWYgYjoKICAgICAgICByZXR1cm4gYS5zcGxpdChiKQogICAgZWxzZToKICAgICAgICByZXR1cm4gYS5zcGxpdCgpCmRlZiBfcHJpbnQoYSxiPSIiKTogICAgICAgICAgICAgICAgICMgcCAgICAgWQogICAgcHJpbnQoYixlbmQ9YSkKZGVmIHF1b3RpZW50KGEsYik6cmV0dXJuIGEvYiAgICAgICAgIyBRICAgICBZCmRlZiBlcXVhbChhLGIpOnJldHVybiBhPT1iICAgICAgICAgICMgcSAgICAgWQojIHJldHVybiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFIgICAgIFkKZGVmIF9yYW5nZShhLGI9Tm9uZSk6ICAgICAgICAgICAgICAgIyByICAgICBZCiAgICBpZiBiOgogICAgICAgIHJldHVybiBsaXN0KHJhbmdlKGEsYikpCiAgICBlbHNlOgogICAgICAgIHJldHVybiBsaXN0KHJhbmdlKGEpKQojIHNvcnRlZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFMgICAgIFkKZGVmIF9zdW0oYSk6CiAgICByZXR1cm4gcmVkdWNlKGxhbWJkYSBiLGM6YitjLGEpICMgcyAgICAgWQojIFQgaXMgYXNzb2NpYXRlZCB3aXRoIGZpbHRlciAgICAgICAjIFQgICAgIFkKVD0xMApkZWYgdGFpbChhKTogICAgICAgICAgICAgICAgICAgICAgICAjIHQgICAgIFkKICAgIGlmIHR5cGUoYSk9PXR5cGUoMCk6CiAgICAgICAgcmV0dXJuIGEtMQogICAgcmV0dXJuIGFbMTpdCmRlZiB1cHBlcihhKTpyZXR1cm4gYS51cHBlcigpICAgICAgICMgVSAgICAgWQpkZWYgcmVkdWNlKGEsYik6ICAgICAgICAgICAgICAgICAgICAjIHUgICAgIFkKICAgIGFjYz1iWzBdCiAgICBzZXE9YlsxOl0KICAgIHdoaWxlIGxlbihzZXEpPjA6CiAgICAgICAgaD1zZXFbMF0KICAgICAgICBhY2M9YShhY2MsaCkKICAgICAgICBzZXE9c2VxWzE6XQogICAgcmV0dXJuIGFjYwpkZWYgcmV2KGEpOiByZXR1cm4gYVs6Oi0xXSAgICAgICAgICAjIFYgICAgIFkKIyBldmFsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB2ICAgICBZCiMgd2hpbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgVyAgICAgWQojIGlucHV0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHcgICAgIFkKZGVmIGluZGV4KGEsYik6ICAgICAgICAgICAgICAgICAgICAgIyBYICAgICBZCiAgICBpZiBiIGluIGE6CiAgICAgICAgcmV0dXJuIGEuaW5kZXgoYikKICAgICMgcmVwbGljYXRlIGZ1bmN0aW9uYWxpdHkgZnJvbSBzdHIuZmluZAogICAgZWxzZToKICAgICAgICByZXR1cm4gLTEKIyBleGVjKGdlbmVyYWxfcGFyc2UgICAgICAgICAgICAgICAgIyB4ICAgICBZClk9W10gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgWSAgICAgWQojIGFueSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHkgICAgIFkKWj0wICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBaICAgICBZCmRlZiBfemlwKGEsYik6cmV0dXJuIGxpc3QoemlwKGEsYikpICMgeiAgICAgWQoKbm9faW5pdF9wYXJlbj0nZm1vdScKZW5kX3N0YXRlbWVudD0nQlInCnZhcmlhYmxlcz0nYmRHSGtOVFlaJwoKIyBUbyBkbzogZXZlbiBwcmVhc3NvY2lhdGVkIHZhcmlhYmxlcyBkZXNlcnZlIHRvIGJlIGluaXRpYWxpemVkLgojIFZhcmlhYmxlcyBjaGVhdCBzaGVldDoKIyBiID0gIlxuIgojIGQgaXMgZm9yIG1hcCwgZD0nICcKIyBHIGlzIGZvciByZWR1Y2UsIEc9c3RyaW5nLmFzY2lpX2xvd2VyY2FzZSAoYWJjLi54eXopCiMgSCBpcyBmb3IgcmVkdWNlLCBIID0ge30KIyBrID0gJycKIyBKIC0gQXV0b2luaXRpYWxpemVyIC0gY29waWVzLCBubyBzdHJpbmdpbmcuCiMgSyAtIEF1dG9pbml0aWFsaXplciAtIGNhbiBiZSBzdHJ1bmcgKEtKdyksIG5vIGNvcHkuCiMgTiA9IE5vbmUsIHNlY29uZCBvcHRpb24gdmFyaWFibGUgZm9yIG1hcCxmaWx0ZXIscmVkdWNlCiMgVCBpcyBmb3IgZmlsdGVyLCBzZWNvbmQgdmFyaWFibGUgb3B0aW9uIGZvciByZWR1Y2UsIFQ9MTAKIyBZID0gW10KIyBaID0gMAoKY190b19zPXsKICAgICdEJzooKCdkZWYgJywnOicpLDEpLAogICAgJ0UnOigoJ2Vsc2U6JyksMCksCiAgICAnRic6KCgnZm9yICcsJyBpbiAnLCc6JyksMiksCiAgICAnSSc6KCgnaWYgJywnOicpLDEpLAogICAgJ1cnOigoJ3doaWxlICcsJzonKSwxKSwKICAgIH0KIyBBcmJpdHJhcnkgZm9ybWF0IG9wZXJhdG9ycyAtIHVzZSBmb3IgYXNzaWdubWVudCwgaW5maXgsIGV0Yy4KIyBBbGwgc3Vycm91bmRpbmcgc3RyaW5ncywgYXJpdHkKY190b19pPXsKICAgICd+JzooKCcnLCcrPScsJycpLDIpLAogICAgJ0AnOigoJycsJ1snLCddJyksMiksCiAgICAnJic6KCgnKCcsJyBhbmQgJywnKScpLDIpLAogICAgJ3wnOigoJygnLCcgb3IgJywnKScpLDIpLAogICAgJz0nOigoJycsJz1jb3B5KCcsJyknKSwyKSwKICAgICddJzooKCdbJywnXScpLDEpLAogICAgJ30nOigoJygnLCcgaW4gJywnKScpLDIpLAogICAgJz8nOigoJygnLCcgaWYgJywnIGVsc2UgJywnKScpLDMpLAogICAgJywnOigoJygnLCcsJywnKScpLDIpLAogICAgJzsnOigoJycsJy5wb3AoKScsKSwxKSwKICAgICdhJzooKCcnLCcuYXBwZW5kKCcsJyknKSwyKSwKICAgICdCJzooKCdicmVhaycsKSwwKSwKICAgICdKJzooKCdKPWNvcHkoJywnKScpLDEpLAogICAgJ0snOigoJ0s9JywnJyksMSksCiAgICAnUic6KCgncmV0dXJuICcsJycpLDEpLAogICAgJ3gnOigoJ2V4ZWMoZ2VuZXJhbF9wYXJzZSgnLCcpKScpLDEpLAogICAgfQoKIyBTaW1wbGUgZnVuY3Rpb25zIG9ubHkuCiMgRXh0ZW5zaWJsZSBpcyBhbGxvd2VkLCBub3RoaW5nIGVsc2UgY29tcGxpY2F0ZWQgaXMuCiMgLTEgbWVhbnMgZXh0ZW5zaWJsZQojIG5hbWUsYXJpdHkKY190b19mPXsKICAgICdgJzooJ3JlcHInLDEpLAogICAgJyEnOignX25vdCcsMSksCiAgICAnIyc6KCd1dGYzMl9hc2NpaScsMSksCiAgICAnJSc6KCdtb2QnLDIpLAogICAgJ14nOigncG93JywyKSwKICAgICcqJzooJ3RpbWVzJywyKSwKICAgICcoJzooJ190dXBsZScsLTEpLAogICAgJy0nOignbWludXMnLDIpLAogICAgJ18nOignbmVnXzFyJywxKSwKICAgICcrJzooJ3BsdXMnLDIpLAogICAgJ1snOignX2xpc3QnLC0xKSwKICAgICd7JzooJ3NldCcsMSksCiAgICAiJyI6KCdoZWFkJywxKSwKICAgICc6JzooJ2F0X3NsaWNlJywzKSwKICAgICc8JzooJ2x0JywyKSwKICAgICc+JzooJ2d0JywyKSwKICAgICcvJzooJ2RpdicsMiksCiAgICAnICc6KCcnLDEpLAogICAgJ1x0JzooJycsMSksCiAgICAnQSc6KCdhbGwnLDEpLAogICAgJ0MnOignX2NocicsMSksCiAgICAnYyc6KCdjb3VudCcsMiksCiAgICAnZSc6KCdsb3dlcicsMSksCiAgICAnZic6KCdfZmlsdGVyKGxhbWJkYSBUOicsMiksCiAgICAnZyc6KCdndGUnLDIpLAogICAgJ2gnOigncmVhZF9maWxlJywwKSwKICAgICdpJzooJ19yb3VuZCcsMiksCiAgICAnaic6KCdqb2luJywyKSwKICAgICdMJzooJ2xyYW5nZScsMSksCiAgICAnbCc6KCdsZW4nLDEpLAogICAgJ00nOignbWF4JywxKSwKICAgICdtJzooJ19tYXAobGFtYmRhIGQ6JywyKSwKICAgICdPJzooJ3JjaG9pY2UnLDEpLAogICAgJ28nOignb3JkZXIobGFtYmRhIE46JywyKSwKICAgICdQJzooJ3NwbGl0JywyKSwKICAgICdwJzooJ19wcmludCcsMiksCiAgICAnUSc6KCdxdW90aWVudCcsMiksCiAgICAncSc6KCdlcXVhbCcsMiksCiAgICAncic6KCdfcmFuZ2UnLDIpLAogICAgJ1MnOignc29ydGVkJywxKSwKICAgICdzJzooJ19zdW0nLDEpLAogICAgJ3QnOigndGFpbCcsMSksCiAgICAnVSc6KCd1cHBlcicsMSksCiAgICAndSc6KCdyZWR1Y2UobGFtYmRhIEcsSDonLDIpLAogICAgJ1YnOigncmV2JywxKSwKICAgICd2JzooJ2V2YWwnLDEpLAogICAgJ3cnOignaW5wdXQnLDApLAogICAgJ1gnOignaW5kZXgnLDIpLAogICAgJ3onOignX3ppcCcsMiksCiAgICB9CgojIEdpdmVzIG5leHQgZnVuY3Rpb24gaGVhZGVyIHRvIHVzZSAtIGZvciBmaWx0ZXIsIG1hcCwgcmVkdWNlLgojIG1hcDogZCwgaywgYgojIGZpbHRlcjogVCwgWSwgWgojIG9yZGVyOiBOLCBaLAojIHJlZHVjZTogKEcsSCksIChOLFQpCgpuZXh0X2NfdG9fZj17CiAgICAnZic6WygnX2ZpbHRlcihsYW1iZGEgWTonLDIpLCAoJ19maWx0ZXIobGFtYmRhIFo6JywyKSxdLAogICAgJ20nOlsoJ19tYXAobGFtYmRhIGs6JywyKSwgKCdfbWFwKGxhbWJkYSBiOicsMiksXSwKICAgICdvJzpbKCdvcmRlcihsYW1iZGEgWjonLDIpLF0sCiAgICAndSc6WygncmVkdWNlKGxhbWJkYSBOLFQ6JywyKSxdLAogICAgfQoKIyBGb3IgYXV0b2luaXRpYWxpemVycy4gT25lIHNob3QsIG5vdCByb3RhdGluZy4KbmV4dF9jX3RvX2k9ewogICAgJ0onOigoJ0onKSwwKSwKICAgICdLJzooKCdLJyksMCksCiAgICB9CiAgICAKYXNzZXJ0IHNldChjX3RvX2Yua2V5cygpKSZzZXQoY190b19pLmtleXMoKSk9PXNldCgpCiMgUnVuIGl0IQpkZWYgZ2VuZXJhbF9wYXJzZShjb2RlKToKICAgIGFyZ3NfbGlzdD1bXQogICAgcGFyc2VkPSdOb3QgZW1wdHknCiAgICB3aGlsZSBwYXJzZWQgIT0gJyc6CiAgICAgICAgIyBQcmVwZW5kIHByaW50IHRvIGFueSBsaW5lIHN0YXJ0aW5nIHdpdGggYSBmdW5jdGlvbiwgdmFyIG9yIHNhZmUgaW5maXguCiAgICAgICAgaWYgbGVuKGNvZGUpPjA6CiAgICAgICAgICAgIGlmICgoY29kZVswXSBub3QgaW4gJ3AgJyBhbmQgY29kZVswXSBpbiBjX3RvX2YpIG9yCiAgICAgICAgICAgIGNvZGVbMF0gaW4gdmFyaWFibGVzIG9yCiAgICAgICAgICAgIChjb2RlWzBdIGluICdKSycgYW5kIGNfdG9faVtjb2RlWzBdXT09bmV4dF9jX3RvX2lbY29kZVswXV0pIG9yCiAgICAgICAgICAgIGNvZGVbMF0gaW4gIkAmfF0nPztcIi4wMTIzNDU2Nzg5IywiKToKICAgICAgICAgICAgICAgIGNvZGU9J3AiXFxuIicrY29kZQogICAgICAgIHBhcnNlZCxjb2RlPXBhcnNlKGNvZGUpCiAgICAgICAgIyBOZWNlc3NhcnkgZm9yIGJhY2tzbGFzaCBub3QgdG8gaW5maW5pdGUgbG9vcAogICAgICAgIGlmIGNvZGUgYW5kIGNvZGVbMF09PSdcXCc6CiAgICAgICAgICAgIGNvZGU9Y29kZVsxOl0KICAgICAgICBhcmdzX2xpc3QuYXBwZW5kKHBhcnNlZCkKICAgICMgQnVpbGQgdGhlIG91dHB1dCBzdHJpbmcuCiAgICBweV9jb2RlPSdcbicuam9pbihhcmdzX2xpc3RbOi0xXSkKICAgIHJldHVybiBweV9jb2RlCmNvZGU9aW5wdXQoKQpwcmludChjb2RlKQpweV9jb2RlPWdlbmVyYWxfcGFyc2UoY29kZSkKcHJpbnQocHlfY29kZSkKcHJpbnQoJz0nKjUwKQpleGVjKHB5X2NvZGUp