# Гласные. Их упорядочивать не нужно (они одинаковой длины, внезапно).
VOWELS = ["а", "е", "и", "о", "у", "ы", "э", "ю", "я"]
# Для генерации ADJECTIVAL (ADJECTIVE и PARTICIPLE + ADJECTIVE).
# Просто склеиваем все возможные варианты PARTICIPLE + ADJECTIVE, а потом добавляем к ним чистые ADJECTIVE.
def generate_adjectival():
adjective_suffixes = _ADJECTIVE["2"]
mix_1 = []
for s1 in _PARTICIPLE["1"]:
for s2 in adjective_suffixes:
mix_1.append(s1 + s2)
mix_2 = []
for s1 in _PARTICIPLE["2"]:
for s2 in adjective_suffixes:
mix_2.append(s1 + s2)
mix_2 += adjective_suffixes
return {
"1": mix_1,
"2": mix_2
}
# Для сортировки окончаний по длине, по убывающей, чтобы потом удобно было искать.
def sort_suffixes(constants_list):
for const in constants_list:
const["1"].sort(key=len, reverse=True)
const["2"].sort(key=len, reverse=True)
return
# У всех есть первые группы, иногда - пустые. Так мы избегаем проверок на то, есть ли свойство.
PERFECTIVE_GERUND = {
"1": ["в", "вши", "вшись"],
"2": ["ив", "ивши", "ившись", "ыв", "ывши", "ывшись"]
}
# Не используется в чистом виде, только в генерируемом ADJECTIVAL.
_ADJECTIVE = {
"1": [],
"2": ["ее", "ие", "ые", "ое", "ими", "ыми", "ей", "ий", "ый", "ой", "ем", "им", "ым", "ом", "его", "ого", "ему", "ому", "их", "ых", "ую", "юю", "ая", "яя", "ою", "ею"]
}
# Не используется в чистом виде, только в генерируемом ADJECTIVAL.
_PARTICIPLE = {
"1": ["ем", "нн", "вш", "ющ", "щ"],
"2": ["ивш", "ывш", "ующ"]
}
REFLEXIVE = {
"1": [],
"2": ["ся", "сь"]
}
VERB = {
"1": ["ла", "на", "ете", "йте", "ли", "й", "л", "ем", "н", "ло", "но", "ет", "ют", "ны", "ть", "ешь", "нно"],
"2": ["ила", "ыла", "ена", "ейте", "уйте", "ите", "или", "ыли", "ей", "уй", "ил", "ыл", "им", "ым", "ен", "ило", "ыло", "ено", "ят", "ует", "уют", "ит", "ыт", "ены", "ить", "ыть", "ишь", "ую", "ю"]
}
NOUN = {
"1": [],
"2": ["а", "ев", "ов", "ие", "ье", "е", "иями", "ями", "ами", "еи", "ии", "и", "ией", "ей", "ой", "ий", "й", "иям", "ям", "ием", "ем", "ам", "ом", "о", "у", "ах", "иях", "ях", "ы", "ь", "ию", "ью", "ю", "ия", "ья", "я"]
}
SUPERLATIVE = {
"1": [],
"2": ["ейш", "ейше"]
}
DERIVATIONAL = {
"1": [],
"2": ["ост", "ость"]
}
# Генерируем только здесь, все части уже объявлены выше.
ADJECTIVAL = generate_adjectival()
# Нормализуем слово, чтобы не возникло косяков.
def normalize(word):
word = word.lower()
word = word.replace("ё", "е")
return word
# Находим позицию после первого сочетания "гласная-согласная" в строке.
# V - vowel, C - consonant.
def find_index_after_VC(string):
v_pos = 0 # Индекс гласной в строке.
c_pos = 0 # Индекс согласной в строке.
for i, c in enumerate(string):
if (c in VOWELS):
v_pos = i
else:
c_pos = i
if (v_pos - c_pos == -1):
return c_pos + 1
return 0
# Разбиваем слово на префикс и RV-форму.
def split_rv(word):
for c in word:
if c in VOWELS:
index = word.find(c) + 1
# Разбиваем слово по позиции после первой гласной.
return [word[0:index], word[index:]]
# Возвращаем пустое RV, если гласных не нашлось.
return [word, ""]
# Разбивка RV на префикс и R2-форму.
def split_r2(rv):
if (rv[0] not in VOWELS):
# Если первая в RV - согласная, значит, в полном слове это была бы последовательность "гласная-согласная".
r1 = rv[1:]
else:
# Иначе - ищем первую такую последовательность. В обоих случаях получаем R1.
ind = find_index_after_VC(rv)
r1 = rv[ind:]
# Ищем вторую такую последовательность, получаем R2.
ind = find_index_after_VC(r1)
r2 = r1[ind:]
# Откладываем длину R2 с конца (делаем её отрицательной).
to = len(r2) * -1
# Делим RV на префикс до позиции после второй последовательности "Г-С" и после этой позиции.
return [rv[0:to], rv[to:]]
# Функция для удаления первого найденного среди `suffixes` окончания.
def drop_suffix(word, suffixes):
for suffix in suffixes["1"]:
to = len(suffix) * -1
# В первой группе - дополнительная проверка на предшествующую "а" или "я".
if (word.endswith(suffix) and (word[to-1:to] == "а" or word[to-1:to] == "я")):
return word[0:to]
for suffix in suffixes["2"]:
to = len(suffix) * -1
if (word.endswith(suffix)):
return word[0:to]
# Если никаких окончаний не удалили, возвращаем пришедшую строку.
return word
# Шаг первый.
def step_1(rv):
# Сохраняем форму, чтобы проверить, изменилась ли она после отбрасывания окончания, или ничего не отбросили.
verification = rv
# Пробуем отбросить Perfective Gerund.
rv = drop_suffix(rv, PERFECTIVE_GERUND)
if (rv != verification):
# Если это удалось - возвращаем урезанное RV.
return rv
else:
# Если нет - отбрасываем Reflexive, если есть.
rv = drop_suffix(rv, REFLEXIVE)
# Снова сохраняем для сверки.
verification = rv
# Пробуем удалить любое из перечисленных окончаний.
for suffixes in [ADJECTIVAL, VERB, NOUN]:
rv = drop_suffix(rv, suffixes)
if (rv != verification):
# Как только удалось - возвращаем усечённую форму RV.
return rv
# Если снова ничего не удалилось, возвращаем то же, что и пришло сюда.
return rv
# Шаг второй, простой. Удаляем последнюю букву, это это "и".
def step_2(rv):
if (rv[-1] == "и"):
return rv[0:-1]
else:
return rv
# Шаг третий, отбрасываем Derivational у формы R2. Тоже простой.
def step_3(r2):
r2 = drop_suffix(r2, DERIVATIONAL)
return r2
# Шаг четвёртый.
def step_4(rv):
# Пробуем выкинуть Superlative.
rv = drop_suffix(rv, SUPERLATIVE)
# Затем, если в конце удвоенная "н" или мягкий знак, удаляем последнюю букву.
if (rv[-2:] == "нн" or rv[-1] == "ь"):
rv = rv[:-1]
return rv
# Аргумент dev - для вывода отладочной информации.
def stemmer(word, dev=False):
word = normalize(word)
# Буквы до первой гласной включительно сохраняются в base, форма RV - в соответсвующую переменную.
base, rv = split_rv(word)
# Проверяем, не пусто ли RV.
if (rv == ""):
return base
dev and print("Before steps: ", rv)
rv = step_1(rv)
dev and print("After step 1: ", rv)
rv = step_2(rv)
dev and print("After step 2: ", rv)
# Ещё разок проверяем.
if (rv == ""):
return base
# Делим RV на сохраняемый префикс и r2.
prefix, r2 = split_r2(rv)
r2 = step_3(r2)
rv = prefix + r2
dev and print("After step 3: ", rv)
rv = step_4(rv)
dev and print("After step 4: ", rv)
return base + rv
# Запускаем сортировку окончаний.
sort_suffixes([
PERFECTIVE_GERUND,
ADJECTIVAL,
REFLEXIVE,
VERB,
NOUN,
SUPERLATIVE,
DERIVATIONAL
])
while True:
w = input().strip()
if (w == ""):
break
print(stemmer(w))
IyDQk9C70LDRgdC90YvQtS4g0JjRhSDRg9C/0L7RgNGP0LTQvtGH0LjQstCw0YLRjCDQvdC1INC90YPQttC90L4gKNC+0L3QuCDQvtC00LjQvdCw0LrQvtCy0L7QuSDQtNC70LjQvdGLLCDQstC90LXQt9Cw0L/QvdC+KS4KVk9XRUxTID0gWyLQsCIsICLQtSIsICLQuCIsICLQviIsICLRgyIsICLRiyIsICLRjSIsICLRjiIsICLRjyJdCgoKIyDQlNC70Y8g0LPQtdC90LXRgNCw0YbQuNC4IEFESkVDVElWQUwgKEFESkVDVElWRSDQuCBQQVJUSUNJUExFICsgQURKRUNUSVZFKS4KIyDQn9GA0L7RgdGC0L4g0YHQutC70LXQuNCy0LDQtdC8INCy0YHQtSDQstC+0LfQvNC+0LbQvdGL0LUg0LLQsNGA0LjQsNC90YLRiyBQQVJUSUNJUExFICsgQURKRUNUSVZFLCDQsCDQv9C+0YLQvtC8INC00L7QsdCw0LLQu9GP0LXQvCDQuiDQvdC40Lwg0YfQuNGB0YLRi9C1IEFESkVDVElWRS4KZGVmIGdlbmVyYXRlX2FkamVjdGl2YWwoKToKCWFkamVjdGl2ZV9zdWZmaXhlcyA9IF9BREpFQ1RJVkVbIjIiXQoJbWl4XzEgPSBbXQoJZm9yIHMxIGluIF9QQVJUSUNJUExFWyIxIl06CgkJZm9yIHMyIGluIGFkamVjdGl2ZV9zdWZmaXhlczoKCQkJbWl4XzEuYXBwZW5kKHMxICsgczIpCgltaXhfMiA9IFtdCglmb3IgczEgaW4gX1BBUlRJQ0lQTEVbIjIiXToKCQlmb3IgczIgaW4gYWRqZWN0aXZlX3N1ZmZpeGVzOgoJCQltaXhfMi5hcHBlbmQoczEgKyBzMikKCW1peF8yICs9IGFkamVjdGl2ZV9zdWZmaXhlcwoJcmV0dXJuIHsKCQkiMSI6IG1peF8xLAoJCSIyIjogbWl4XzIKCX0KCiMg0JTQu9GPINGB0L7RgNGC0LjRgNC+0LLQutC4INC+0LrQvtC90YfQsNC90LjQuSDQv9C+INC00LvQuNC90LUsINC/0L4g0YPQsdGL0LLQsNGO0YnQtdC5LCDRh9GC0L7QsdGLINC/0L7RgtC+0Lwg0YPQtNC+0LHQvdC+INCx0YvQu9C+INC40YHQutCw0YLRjC4KZGVmIHNvcnRfc3VmZml4ZXMoY29uc3RhbnRzX2xpc3QpOgoJZm9yIGNvbnN0IGluIGNvbnN0YW50c19saXN0OgoJCWNvbnN0WyIxIl0uc29ydChrZXk9bGVuLCByZXZlcnNlPVRydWUpCgkJY29uc3RbIjIiXS5zb3J0KGtleT1sZW4sIHJldmVyc2U9VHJ1ZSkKCXJldHVybgoKCiMg0KMg0LLRgdC10YUg0LXRgdGC0Ywg0L/QtdGA0LLRi9C1INCz0YDRg9C/0L/Riywg0LjQvdC+0LPQtNCwIC0g0L/Rg9GB0YLRi9C1LiDQotCw0Log0LzRiyDQuNC30LHQtdCz0LDQtdC8INC/0YDQvtCy0LXRgNC+0Log0L3QsCDRgtC+LCDQtdGB0YLRjCDQu9C4INGB0LLQvtC50YHRgtCy0L4uCgpQRVJGRUNUSVZFX0dFUlVORCA9IHsKCSIxIjogWyLQsiIsICLQstGI0LgiLCAi0LLRiNC40YHRjCJdLAoJIjIiOiBbItC40LIiLCAi0LjQstGI0LgiLCAi0LjQstGI0LjRgdGMIiwgItGL0LIiLCAi0YvQstGI0LgiLCAi0YvQstGI0LjRgdGMIl0KfQoKIyDQndC1INC40YHQv9C+0LvRjNC30YPQtdGC0YHRjyDQsiDRh9C40YHRgtC+0Lwg0LLQuNC00LUsINGC0L7Qu9GM0LrQviDQsiDQs9C10L3QtdGA0LjRgNGD0LXQvNC+0LwgQURKRUNUSVZBTC4KX0FESkVDVElWRSA9IHsKCSIxIjogW10sCgkiMiI6IFsi0LXQtSIsICLQuNC1IiwgItGL0LUiLCAi0L7QtSIsICLQuNC80LgiLCAi0YvQvNC4IiwgItC10LkiLCAi0LjQuSIsICLRi9C5IiwgItC+0LkiLCAi0LXQvCIsICLQuNC8IiwgItGL0LwiLCAi0L7QvCIsICLQtdCz0L4iLCAi0L7Qs9C+IiwgItC10LzRgyIsICLQvtC80YMiLCAi0LjRhSIsICLRi9GFIiwgItGD0Y4iLCAi0Y7RjiIsICLQsNGPIiwgItGP0Y8iLCAi0L7RjiIsICLQtdGOIl0KfQoKIyDQndC1INC40YHQv9C+0LvRjNC30YPQtdGC0YHRjyDQsiDRh9C40YHRgtC+0Lwg0LLQuNC00LUsINGC0L7Qu9GM0LrQviDQsiDQs9C10L3QtdGA0LjRgNGD0LXQvNC+0LwgQURKRUNUSVZBTC4KX1BBUlRJQ0lQTEUgPSB7CgkiMSI6IFsi0LXQvCIsICLQvdC9IiwgItCy0YgiLCAi0Y7RiSIsICLRiSJdLAoJIjIiOiBbItC40LLRiCIsICLRi9Cy0YgiLCAi0YPRjtGJIl0KfQoKUkVGTEVYSVZFID0gewoJIjEiOiBbXSwKCSIyIjogWyLRgdGPIiwgItGB0YwiXQp9CgpWRVJCID0gewoJIjEiOiBbItC70LAiLCAi0L3QsCIsICLQtdGC0LUiLCAi0LnRgtC1IiwgItC70LgiLCAi0LkiLCAi0LsiLCAi0LXQvCIsICLQvSIsICLQu9C+IiwgItC90L4iLCAi0LXRgiIsICLRjtGCIiwgItC90YsiLCAi0YLRjCIsICLQtdGI0YwiLCAi0L3QvdC+Il0sCgkiMiI6IFsi0LjQu9CwIiwgItGL0LvQsCIsICLQtdC90LAiLCAi0LXQudGC0LUiLCAi0YPQudGC0LUiLCAi0LjRgtC1IiwgItC40LvQuCIsICLRi9C70LgiLCAi0LXQuSIsICLRg9C5IiwgItC40LsiLCAi0YvQuyIsICLQuNC8IiwgItGL0LwiLCAi0LXQvSIsICLQuNC70L4iLCAi0YvQu9C+IiwgItC10L3QviIsICLRj9GCIiwgItGD0LXRgiIsICLRg9GO0YIiLCAi0LjRgiIsICLRi9GCIiwgItC10L3RiyIsICLQuNGC0YwiLCAi0YvRgtGMIiwgItC40YjRjCIsICLRg9GOIiwgItGOIl0KfQoKTk9VTiA9IHsKCSIxIjogW10sCgkiMiI6IFsi0LAiLCAi0LXQsiIsICLQvtCyIiwgItC40LUiLCAi0YzQtSIsICLQtSIsICLQuNGP0LzQuCIsICLRj9C80LgiLCAi0LDQvNC4IiwgItC10LgiLCAi0LjQuCIsICLQuCIsICLQuNC10LkiLCAi0LXQuSIsICLQvtC5IiwgItC40LkiLCAi0LkiLCAi0LjRj9C8IiwgItGP0LwiLCAi0LjQtdC8IiwgItC10LwiLCAi0LDQvCIsICLQvtC8IiwgItC+IiwgItGDIiwgItCw0YUiLCAi0LjRj9GFIiwgItGP0YUiLCAi0YsiLCAi0YwiLCAi0LjRjiIsICLRjNGOIiwgItGOIiwgItC40Y8iLCAi0YzRjyIsICLRjyJdCn0KClNVUEVSTEFUSVZFID0gewoJIjEiOiBbXSwKCSIyIjogWyLQtdC50YgiLCAi0LXQudGI0LUiXQp9CgpERVJJVkFUSU9OQUwgPSB7CgkiMSI6IFtdLAoJIjIiOiBbItC+0YHRgiIsICLQvtGB0YLRjCJdCn0KCiMg0JPQtdC90LXRgNC40YDRg9C10Lwg0YLQvtC70YzQutC+INC30LTQtdGB0YwsINCy0YHQtSDRh9Cw0YHRgtC4INGD0LbQtSDQvtCx0YrRj9Cy0LvQtdC90Ysg0LLRi9GI0LUuCkFESkVDVElWQUwgPSBnZW5lcmF0ZV9hZGplY3RpdmFsKCkKCgojINCd0L7RgNC80LDQu9C40LfRg9C10Lwg0YHQu9C+0LLQviwg0YfRgtC+0LHRiyDQvdC1INCy0L7Qt9C90LjQutC70L4g0LrQvtGB0Y/QutC+0LIuCmRlZiBub3JtYWxpemUod29yZCk6Cgl3b3JkID0gd29yZC5sb3dlcigpCgl3b3JkID0gd29yZC5yZXBsYWNlKCLRkSIsICLQtSIpCglyZXR1cm4gd29yZAoKIyDQndCw0YXQvtC00LjQvCDQv9C+0LfQuNGG0LjRjiDQv9C+0YHQu9C1INC/0LXRgNCy0L7Qs9C+INGB0L7Rh9C10YLQsNC90LjRjyAi0LPQu9Cw0YHQvdCw0Y8t0YHQvtCz0LvQsNGB0L3QsNGPIiDQsiDRgdGC0YDQvtC60LUuCiMgViAtIHZvd2VsLCBDIC0gY29uc29uYW50LgpkZWYgZmluZF9pbmRleF9hZnRlcl9WQyhzdHJpbmcpOgoJdl9wb3MgPSAwICMg0JjQvdC00LXQutGBINCz0LvQsNGB0L3QvtC5INCyINGB0YLRgNC+0LrQtS4KCWNfcG9zID0gMCAjINCY0L3QtNC10LrRgSDRgdC+0LPQu9Cw0YHQvdC+0Lkg0LIg0YHRgtGA0L7QutC1LgoJZm9yIGksIGMgaW4gZW51bWVyYXRlKHN0cmluZyk6CgkJaWYgKGMgaW4gVk9XRUxTKToKCQkJdl9wb3MgPSBpCgkJZWxzZToKCQkJY19wb3MgPSBpCgkJaWYgKHZfcG9zIC0gY19wb3MgPT0gLTEpOgoJCQlyZXR1cm4gY19wb3MgKyAxCglyZXR1cm4gMAoKIyDQoNCw0LfQsdC40LLQsNC10Lwg0YHQu9C+0LLQviDQvdCwINC/0YDQtdGE0LjQutGBINC4IFJWLdGE0L7RgNC80YMuCmRlZiBzcGxpdF9ydih3b3JkKToKCWZvciBjIGluIHdvcmQ6CgkJaWYgYyBpbiBWT1dFTFM6CgkJCWluZGV4ID0gd29yZC5maW5kKGMpICsgMQoJCQkjINCg0LDQt9Cx0LjQstCw0LXQvCDRgdC70L7QstC+INC/0L4g0L/QvtC30LjRhtC40Lgg0L/QvtGB0LvQtSDQv9C10YDQstC+0Lkg0LPQu9Cw0YHQvdC+0LkuCgkJCXJldHVybiBbd29yZFswOmluZGV4XSwgd29yZFtpbmRleDpdXQoJIyDQktC+0LfQstGA0LDRidCw0LXQvCDQv9GD0YHRgtC+0LUgUlYsINC10YHQu9C4INCz0LvQsNGB0L3Ri9GFINC90LUg0L3QsNGI0LvQvtGB0YwuCglyZXR1cm4gW3dvcmQsICIiXQoKIyDQoNCw0LfQsdC40LLQutCwIFJWINC90LAg0L/RgNC10YTQuNC60YEg0LggUjIt0YTQvtGA0LzRgy4KZGVmIHNwbGl0X3IyKHJ2KToKCWlmIChydlswXSBub3QgaW4gVk9XRUxTKToKCQkjINCV0YHQu9C4INC/0LXRgNCy0LDRjyDQsiBSViAtINGB0L7Qs9C70LDRgdC90LDRjywg0LfQvdCw0YfQuNGCLCDQsiDQv9C+0LvQvdC+0Lwg0YHQu9C+0LLQtSDRjdGC0L4g0LHRi9C70LAg0LHRiyDQv9C+0YHQu9C10LTQvtCy0LDRgtC10LvRjNC90L7RgdGC0YwgItCz0LvQsNGB0L3QsNGPLdGB0L7Qs9C70LDRgdC90LDRjyIuCgkJcjEgPSBydlsxOl0KCWVsc2U6CgkJIyDQmNC90LDRh9C1IC0g0LjRidC10Lwg0L/QtdGA0LLRg9GOINGC0LDQutGD0Y4g0L/QvtGB0LvQtdC00L7QstCw0YLQtdC70YzQvdC+0YHRgtGMLiDQkiDQvtCx0L7QuNGFINGB0LvRg9GH0LDRj9GFINC/0L7Qu9GD0YfQsNC10LwgUjEuCgkJaW5kID0gZmluZF9pbmRleF9hZnRlcl9WQyhydikKCQlyMSA9IHJ2W2luZDpdCgkjINCY0YnQtdC8INCy0YLQvtGA0YPRjiDRgtCw0LrRg9GOINC/0L7RgdC70LXQtNC+0LLQsNGC0LXQu9GM0L3QvtGB0YLRjCwg0L/QvtC70YPRh9Cw0LXQvCBSMi4KCWluZCA9IGZpbmRfaW5kZXhfYWZ0ZXJfVkMocjEpCglyMiA9IHIxW2luZDpdCgkjINCe0YLQutC70LDQtNGL0LLQsNC10Lwg0LTQu9C40L3RgyBSMiDRgSDQutC+0L3RhtCwICjQtNC10LvQsNC10Lwg0LXRkSDQvtGC0YDQuNGG0LDRgtC10LvRjNC90L7QuSkuCgl0byA9IGxlbihyMikgKiAtMQoJIyDQlNC10LvQuNC8IFJWINC90LAg0L/RgNC10YTQuNC60YEg0LTQviDQv9C+0LfQuNGG0LjQuCDQv9C+0YHQu9C1INCy0YLQvtGA0L7QuSDQv9C+0YHQu9C10LTQvtCy0LDRgtC10LvRjNC90L7RgdGC0LggItCTLdChIiDQuCDQv9C+0YHQu9C1INGN0YLQvtC5INC/0L7Qt9C40YbQuNC4LgoJcmV0dXJuIFtydlswOnRvXSwgcnZbdG86XV0KCiMg0KTRg9C90LrRhtC40Y8g0LTQu9GPINGD0LTQsNC70LXQvdC40Y8g0L/QtdGA0LLQvtCz0L4g0L3QsNC50LTQtdC90L3QvtCz0L4g0YHRgNC10LTQuCBgc3VmZml4ZXNgINC+0LrQvtC90YfQsNC90LjRjy4KZGVmIGRyb3Bfc3VmZml4KHdvcmQsIHN1ZmZpeGVzKToKCWZvciBzdWZmaXggaW4gc3VmZml4ZXNbIjEiXToKCQl0byA9IGxlbihzdWZmaXgpICogLTEKCQkjINCSINC/0LXRgNCy0L7QuSDQs9GA0YPQv9C/0LUgLSDQtNC+0L/QvtC70L3QuNGC0LXQu9GM0L3QsNGPINC/0YDQvtCy0LXRgNC60LAg0L3QsCDQv9GA0LXQtNGI0LXRgdGC0LLRg9GO0YnRg9GOICLQsCIg0LjQu9C4ICLRjyIuCgkJaWYgKHdvcmQuZW5kc3dpdGgoc3VmZml4KSBhbmQgKHdvcmRbdG8tMTp0b10gPT0gItCwIiBvciB3b3JkW3RvLTE6dG9dID09ICLRjyIpKToKCQkJcmV0dXJuIHdvcmRbMDp0b10KCWZvciBzdWZmaXggaW4gc3VmZml4ZXNbIjIiXToKCQl0byA9IGxlbihzdWZmaXgpICogLTEKCQlpZiAod29yZC5lbmRzd2l0aChzdWZmaXgpKToKCQkJcmV0dXJuIHdvcmRbMDp0b10KCSMg0JXRgdC70Lgg0L3QuNC60LDQutC40YUg0L7QutC+0L3Rh9Cw0L3QuNC5INC90LUg0YPQtNCw0LvQuNC70LgsINCy0L7Qt9Cy0YDQsNGJ0LDQtdC8INC/0YDQuNGI0LXQtNGI0YPRjiDRgdGC0YDQvtC60YMuCglyZXR1cm4gd29yZAoKCiMg0KjQsNCzINC/0LXRgNCy0YvQuS4KZGVmIHN0ZXBfMShydik6CgkjINCh0L7RhdGA0LDQvdGP0LXQvCDRhNC+0YDQvNGDLCDRh9GC0L7QsdGLINC/0YDQvtCy0LXRgNC40YLRjCwg0LjQt9C80LXQvdC40LvQsNGB0Ywg0LvQuCDQvtC90LAg0L/QvtGB0LvQtSDQvtGC0LHRgNCw0YHRi9Cy0LDQvdC40Y8g0L7QutC+0L3Rh9Cw0L3QuNGPLCDQuNC70Lgg0L3QuNGH0LXQs9C+INC90LUg0L7RgtCx0YDQvtGB0LjQu9C4LgoJdmVyaWZpY2F0aW9uID0gcnYKCSMg0J/RgNC+0LHRg9C10Lwg0L7RgtCx0YDQvtGB0LjRgtGMIFBlcmZlY3RpdmUgR2VydW5kLgoJcnYgPSBkcm9wX3N1ZmZpeChydiwgUEVSRkVDVElWRV9HRVJVTkQpCglpZiAocnYgIT0gdmVyaWZpY2F0aW9uKToKCQkjINCV0YHQu9C4INGN0YLQviDRg9C00LDQu9C+0YHRjCAtINCy0L7Qt9Cy0YDQsNGJ0LDQtdC8INGD0YDQtdC30LDQvdC90L7QtSBSVi4KCQlyZXR1cm4gcnYKCWVsc2U6CgkJIyDQldGB0LvQuCDQvdC10YIgLSDQvtGC0LHRgNCw0YHRi9Cy0LDQtdC8IFJlZmxleGl2ZSwg0LXRgdC70Lgg0LXRgdGC0YwuCgkJcnYgPSBkcm9wX3N1ZmZpeChydiwgUkVGTEVYSVZFKQoJCSMg0KHQvdC+0LLQsCDRgdC+0YXRgNCw0L3Rj9C10Lwg0LTQu9GPINGB0LLQtdGA0LrQuC4KCQl2ZXJpZmljYXRpb24gPSBydgoJCSMg0J/RgNC+0LHRg9C10Lwg0YPQtNCw0LvQuNGC0Ywg0LvRjtCx0L7QtSDQuNC3INC/0LXRgNC10YfQuNGB0LvQtdC90L3Ri9GFINC+0LrQvtC90YfQsNC90LjQuS4KCQlmb3Igc3VmZml4ZXMgaW4gW0FESkVDVElWQUwsIFZFUkIsIE5PVU5dOgoJCQlydiA9IGRyb3Bfc3VmZml4KHJ2LCBzdWZmaXhlcykKCQkJaWYgKHJ2ICE9IHZlcmlmaWNhdGlvbik6CgkJCQkjINCa0LDQuiDRgtC+0LvRjNC60L4g0YPQtNCw0LvQvtGB0YwgLSDQstC+0LfQstGA0LDRidCw0LXQvCDRg9GB0LXRh9GR0L3QvdGD0Y4g0YTQvtGA0LzRgyBSVi4KCQkJCXJldHVybiBydgoJIyDQldGB0LvQuCDRgdC90L7QstCwINC90LjRh9C10LPQviDQvdC1INGD0LTQsNC70LjQu9C+0YHRjCwg0LLQvtC30LLRgNCw0YnQsNC10Lwg0YLQviDQttC1LCDRh9GC0L4g0Lgg0L/RgNC40YjQu9C+INGB0Y7QtNCwLgoJcmV0dXJuIHJ2CgojINCo0LDQsyDQstGC0L7RgNC+0LksINC/0YDQvtGB0YLQvtC5LiDQo9C00LDQu9GP0LXQvCDQv9C+0YHQu9C10LTQvdGO0Y4g0LHRg9C60LLRgywg0Y3RgtC+INGN0YLQviAi0LgiLgpkZWYgc3RlcF8yKHJ2KToKCWlmIChydlstMV0gPT0gItC4Iik6CgkJcmV0dXJuIHJ2WzA6LTFdCgllbHNlOgoJCXJldHVybiBydgoKIyDQqNCw0LMg0YLRgNC10YLQuNC5LCDQvtGC0LHRgNCw0YHRi9Cy0LDQtdC8IERlcml2YXRpb25hbCDRgyDRhNC+0YDQvNGLIFIyLiDQotC+0LbQtSDQv9GA0L7RgdGC0L7QuS4KZGVmIHN0ZXBfMyhyMik6CglyMiA9IGRyb3Bfc3VmZml4KHIyLCBERVJJVkFUSU9OQUwpCglyZXR1cm4gcjIKCiMg0KjQsNCzINGH0LXRgtCy0ZHRgNGC0YvQuS4KZGVmIHN0ZXBfNChydik6CgkjINCf0YDQvtCx0YPQtdC8INCy0YvQutC40L3Rg9GC0YwgU3VwZXJsYXRpdmUuCglydiA9IGRyb3Bfc3VmZml4KHJ2LCBTVVBFUkxBVElWRSkKCSMg0JfQsNGC0LXQvCwg0LXRgdC70Lgg0LIg0LrQvtC90YbQtSDRg9C00LLQvtC10L3QvdCw0Y8gItC9IiDQuNC70Lgg0LzRj9Cz0LrQuNC5INC30L3QsNC6LCDRg9C00LDQu9GP0LXQvCDQv9C+0YHQu9C10LTQvdGO0Y4g0LHRg9C60LLRgy4KCWlmIChydlstMjpdID09ICLQvdC9IiBvciBydlstMV0gPT0gItGMIik6CgkJcnYgPSBydls6LTFdCglyZXR1cm4gcnYKCgojINCQ0YDQs9GD0LzQtdC90YIgZGV2IC0g0LTQu9GPINCy0YvQstC+0LTQsCDQvtGC0LvQsNC00L7Rh9C90L7QuSDQuNC90YTQvtGA0LzQsNGG0LjQuC4KZGVmIHN0ZW1tZXIod29yZCwgZGV2PUZhbHNlKToKCgl3b3JkID0gbm9ybWFsaXplKHdvcmQpCgoJIyDQkdGD0LrQstGLINC00L4g0L/QtdGA0LLQvtC5INCz0LvQsNGB0L3QvtC5INCy0LrQu9GO0YfQuNGC0LXQu9GM0L3QviDRgdC+0YXRgNCw0L3Rj9GO0YLRgdGPINCyIGJhc2UsINGE0L7RgNC80LAgUlYgLSDQsiDRgdC+0L7RgtCy0LXRgtGB0LLRg9GO0YnRg9GOINC/0LXRgNC10LzQtdC90L3Rg9GOLgoJYmFzZSwgcnYgPSBzcGxpdF9ydih3b3JkKQoKCSMg0J/RgNC+0LLQtdGA0Y/QtdC8LCDQvdC1INC/0YPRgdGC0L4g0LvQuCBSVi4KCWlmIChydiA9PSAiIik6CgkJcmV0dXJuIGJhc2UKCglkZXYgYW5kIHByaW50KCJCZWZvcmUgc3RlcHM6ICIsIHJ2KQoJcnYgPSBzdGVwXzEocnYpCglkZXYgYW5kIHByaW50KCJBZnRlciBzdGVwIDE6ICIsIHJ2KQoJcnYgPSBzdGVwXzIocnYpCglkZXYgYW5kIHByaW50KCJBZnRlciBzdGVwIDI6ICIsIHJ2KQoKCSMg0JXRidGRINGA0LDQt9C+0Log0L/RgNC+0LLQtdGA0Y/QtdC8LgoJaWYgKHJ2ID09ICIiKToKCQlyZXR1cm4gYmFzZQoKCSMg0JTQtdC70LjQvCBSViDQvdCwINGB0L7RhdGA0LDQvdGP0LXQvNGL0Lkg0L/RgNC10YTQuNC60YEg0LggcjIuCglwcmVmaXgsIHIyID0gc3BsaXRfcjIocnYpCglyMiA9IHN0ZXBfMyhyMikKCXJ2ID0gcHJlZml4ICsgcjIKCWRldiBhbmQgcHJpbnQoIkFmdGVyIHN0ZXAgMzogIiwgcnYpCgoJcnYgPSBzdGVwXzQocnYpCglkZXYgYW5kIHByaW50KCJBZnRlciBzdGVwIDQ6ICIsIHJ2KQoKCXJldHVybiBiYXNlICsgcnYKCgojINCX0LDQv9GD0YHQutCw0LXQvCDRgdC+0YDRgtC40YDQvtCy0LrRgyDQvtC60L7QvdGH0LDQvdC40LkuCnNvcnRfc3VmZml4ZXMoWwoJUEVSRkVDVElWRV9HRVJVTkQsCglBREpFQ1RJVkFMLAoJUkVGTEVYSVZFLAoJVkVSQiwKCU5PVU4sCglTVVBFUkxBVElWRSwKCURFUklWQVRJT05BTApdKQoKCndoaWxlIFRydWU6Cgl3ID0gaW5wdXQoKS5zdHJpcCgpCglpZiAodyA9PSAiIik6CgkJYnJlYWsKCXByaW50KHN0ZW1tZXIodykpCg==