#!/usr/bin/env python3
from functools import reduce
from itertools import groupby, zip_longest
from random import randint, sample
from sys import argv, exit
class Card(object):
'''トランプのオブジェクト'''
def __init__(self, suit, number):
self.suit = suit
self.number = number
# Card クラスのインスタンスの表示形式を調整する
def __repr__(self):
return f"[{self.suit}:{self.number}]"
class Player(object):
'''プレイヤーオブジェクト'''
def __init__(self, cards):
self.cards = cards
self.card = False
self.discarded = []
self.message = Message()
def drawCard(self, player2, pos):
'''カードを引く'''
self.card = player2.cards[pos]
self.cards += [self.card]
player2.cards = player2.cards[:pos] + player2.cards[pos + 1:]
return player2
def discardPair(self):
'''カードを捨てる'''
p = [j[0] for j in [list(i) for key, i in \
groupby(sorted(self.cards, key = lambda x: x.number), \
key = lambda x: x.number)] if len(j) != 2]
self.discarded = list(set(self.cards) - set(p))
self.cards = p
return self
def showCards(self, id):
return self.message.showCards(id, self.cards)
def showDiscardCards(self, id):
return self.message.showDiscardCards(id, self.discarded)
def selectCard(num):
'''num枚のカードから引くカードを決める'''
return randint(0, num - 1)
def dealCards(deck, n):
'''カードを配る'''
i = len(deck) // n
acc = [deck[x:x + i] for x in range(0, len(deck), i)]
# ここで Player クラスのインスタンスを生成する
return [Player(i[0] + [i[1]] if i[1] != None else i[0]) for i in \
zip_longest(acc[:-1], acc[-1])]
def shuffle_list(lst, n):
'''カードシャッフルする'''
return reduce(lambda x, y: sample(x, len(lst)), range(n), lst)
class Message(object):
'''メッセージ'''
def __init__(self):
self.message = {
"inputSelectCard" : "何枚目のカードを引きますか? (0 〜 {0})\n",
"showNumCard" : "プレイヤー{0}のカード: {1}枚\n",
"showCards" : "プレイヤー{0}のカード: {1}\n",
"showDiscardCards" : "プレイヤー{0}が捨てたカード: {1}\n",
"showDrawCard" : "プレイヤー{0} -> プレイヤー{1} : {2}\n",
"showResult" : "プレイヤー{0}の負けです...\n"
}
def showCards(self, id, cards):
'''手持ちのカードを表示する'''
if id == 0:
return self.message["showCards"].format(id, self.getCardsStr(cards))
else:
return self.message["showNumCard"].format(id, len(cards))
def showDiscardCards(self, id, cards):
'''捨てられたカードを表示する文字列'''
if cards == []:
return ""
else:
return self.message["showDiscardCards"].format(id, \
self.getCardsStr(cards))
def showDrawCard(self, id1, id2, card):
'''カードの交換状況を表示する文字列'''
return self.message["showDrawCard"].format(id1, id2, \
self.getCardStr(card))
def showResult(self, id):
'''ゲームの結果を表示する文字列'''
return self.message["showResult"].format(id)
def getCardsStr(self, cards):
'''Cardオブジェクトのリストを文字列に変換'''
return "".join([self.getCardStr(i) for i in cards])
def getCardStr(self, card):
'''Cardオブジェクトを文字列に変換'''
return "{0}".format(card)
def make_deck():
'''トランプのカードを作成する'''
return [Card("J", "0")] + [Card(i, "A" if j == 1 else "J" if j == 11 \
else "Q" if j == 12 else "K" if j == 13 \
else str(j)) for i in \
("D", "H", "S", "C") for j in \
range(1, 14)]
class World(object):
'''環境'''
def __init__(self, clist, pair, id1, id2, players):
self.clist = clist
self.pair = pair
self.id1 = id1
self.id2 = id2
self.players = players
def insert(self, i, j, player1, player2):
self.players[i] = player1
self.players[j] = player2
return self
def next_id(self):
self.pair = [self.id1, self.id2]
self.id1 = next_id(self.clist, self.id1 + 1, self.players)
self.id2 = next_id(self.clist, self.id1 + 1, self.players)
return self
def next_id(clist, i, players):
while True:
pos = clist[i % len(clist)]
cards = players[pos].cards
if cards != []:
return pos
i += 1
# read
def read(w):
id1, id2, players = w.id1, w.id2, w.players
k = len(players[id2].cards)
m = Message()
if id1 == 0:
return int(input(m.message["inputSelectCard"].format(k - 1)))
else:
return selectCard(k)
# eval
def world_go(exp, w):
id1, id2, players = w.id1, w.id2, w.players
player1, player2 = players[id1], players[id2]
player2 = player1.drawCard(player2, exp)
return w.insert(id1, id2, player1.discardPair(), player2).next_id()
# print
def display(w):
pair, players = w.pair, w.players
head, tail = pair[0], pair[1]
player = players[head]
m = Message()
print(m.showDrawCard(tail, head, player.card) + \
player.showDiscardCards(head) + \
"".join([j.showCards(i) for i, j in enumerate(players)]), end ="")
return w
def is_game_ends(w):
'''ゲーム終了判定'''
return w.id1 == w.id2
# 初期化
def initialize(n):
players = dealCards(shuffle_list(make_deck(), 7), n)
[print(j.showCards(i), end = "") for i, j in enumerate(players)]
[p.discardPair() for p in players]
[print(j.showDiscardCards(i), end = "") for i, j in enumerate(players)]
[print(j.showCards(i), end = "") for i, j in enumerate(players)]
return World(list(range(n)), [], 0, 1, players)
if __name__ == '__main__':
'''REPL'''
w = initialize(int(argv[1]))
m = Message()
while True:
if is_game_ends(w):
print(m.showResult(w.id1))
exit()
try:
w = display(world_go(read(w), w))
except IndexError:
print("不正な入力です")
except ValueError:
print("不正な入力です")
finally:
w
IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoKZnJvbSBmdW5jdG9vbHMgaW1wb3J0IHJlZHVjZQpmcm9tIGl0ZXJ0b29scyBpbXBvcnQgZ3JvdXBieSwgemlwX2xvbmdlc3QKZnJvbSByYW5kb20gaW1wb3J0IHJhbmRpbnQsIHNhbXBsZQpmcm9tIHN5cyBpbXBvcnQgYXJndiwgZXhpdAoKY2xhc3MgQ2FyZChvYmplY3QpOgogICAgJycn44OI44Op44Oz44OX44Gu44Kq44OW44K444Kn44Kv44OIJycnCiAgICBkZWYgX19pbml0X18oc2VsZiwgc3VpdCwgbnVtYmVyKToKICAgICAgICBzZWxmLnN1aXQgPSBzdWl0CiAgICAgICAgc2VsZi5udW1iZXIgPSBudW1iZXIKCiAgICAjIENhcmQg44Kv44Op44K544Gu44Kk44Oz44K544K/44Oz44K544Gu6KGo56S65b2i5byP44KS6Kq/5pW044GZ44KLCiAgICBkZWYgX19yZXByX18oc2VsZik6CiAgICAgICAgcmV0dXJuIGYiW3tzZWxmLnN1aXR9OntzZWxmLm51bWJlcn1dIgoKY2xhc3MgUGxheWVyKG9iamVjdCk6CiAgICAnJyfjg5fjg6zjgqTjg6Tjg7zjgqrjg5bjgrjjgqfjgq/jg4gnJycKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBjYXJkcyk6CiAgICAgICAgc2VsZi5jYXJkcyA9IGNhcmRzCiAgICAgICAgc2VsZi5jYXJkID0gRmFsc2UKICAgICAgICBzZWxmLmRpc2NhcmRlZCA9IFtdCiAgICAgICAgc2VsZi5tZXNzYWdlID0gTWVzc2FnZSgpCgogICAgZGVmIGRyYXdDYXJkKHNlbGYsIHBsYXllcjIsIHBvcyk6CiAgICAgICAgJycn44Kr44O844OJ44KS5byV44GPJycnCiAgICAgICAgc2VsZi5jYXJkID0gcGxheWVyMi5jYXJkc1twb3NdCiAgICAgICAgc2VsZi5jYXJkcyArPSBbc2VsZi5jYXJkXQogICAgICAgIHBsYXllcjIuY2FyZHMgPSBwbGF5ZXIyLmNhcmRzWzpwb3NdICsgcGxheWVyMi5jYXJkc1twb3MgKyAxOl0KICAgICAgICByZXR1cm4gcGxheWVyMgoKICAgIGRlZiBkaXNjYXJkUGFpcihzZWxmKToKICAgICAgICAnJyfjgqvjg7zjg4njgpLmjajjgabjgosnJycKICAgICAgICBwID0gW2pbMF0gZm9yIGogaW4gW2xpc3QoaSkgZm9yIGtleSwgaSBpbiBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cGJ5KHNvcnRlZChzZWxmLmNhcmRzLCBrZXkgPSBsYW1iZGEgeDogeC5udW1iZXIpLCBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleSA9IGxhbWJkYSB4OiB4Lm51bWJlcildIGlmIGxlbihqKSAhPSAyXQogICAgICAgIHNlbGYuZGlzY2FyZGVkID0gbGlzdChzZXQoc2VsZi5jYXJkcykgLSBzZXQocCkpCiAgICAgICAgc2VsZi5jYXJkcyA9IHAKICAgICAgICByZXR1cm4gc2VsZgoKICAgIGRlZiBzaG93Q2FyZHMoc2VsZiwgaWQpOgogICAgICAgIHJldHVybiBzZWxmLm1lc3NhZ2Uuc2hvd0NhcmRzKGlkLCBzZWxmLmNhcmRzKQoKICAgIGRlZiBzaG93RGlzY2FyZENhcmRzKHNlbGYsIGlkKToKICAgICAgICByZXR1cm4gc2VsZi5tZXNzYWdlLnNob3dEaXNjYXJkQ2FyZHMoaWQsIHNlbGYuZGlzY2FyZGVkKQoKZGVmIHNlbGVjdENhcmQobnVtKToKICAgICcnJ251beaemuOBruOCq+ODvOODieOBi+OCieW8leOBj+OCq+ODvOODieOCkuaxuuOCgeOCiycnJwogICAgcmV0dXJuIHJhbmRpbnQoMCwgbnVtIC0gMSkKCmRlZiBkZWFsQ2FyZHMoZGVjaywgbik6CiAgICAnJyfjgqvjg7zjg4njgpLphY3jgosnJycKICAgIGkgPSBsZW4oZGVjaykgLy8gbgogICAgYWNjID0gW2RlY2tbeDp4ICsgaV0gZm9yIHggaW4gcmFuZ2UoMCwgbGVuKGRlY2spLCBpKV0KICAgICMg44GT44GT44GnIFBsYXllciDjgq/jg6njgrnjga7jgqTjg7Pjgrnjgr/jg7PjgrnjgpLnlJ/miJDjgZnjgosKICAgIHJldHVybiBbUGxheWVyKGlbMF0gKyBbaVsxXV0gaWYgaVsxXSAhPSBOb25lIGVsc2UgaVswXSkgZm9yIGkgaW4gXAogICAgICAgICAgICB6aXBfbG9uZ2VzdChhY2NbOi0xXSwgYWNjWy0xXSldCgpkZWYgc2h1ZmZsZV9saXN0KGxzdCwgbik6CiAgICAnJyfjgqvjg7zjg4njgrfjg6Pjg4Pjg5Xjg6vjgZnjgosnJycKICAgIHJldHVybiByZWR1Y2UobGFtYmRhIHgsIHk6IHNhbXBsZSh4LCBsZW4obHN0KSksIHJhbmdlKG4pLCBsc3QpCgpjbGFzcyBNZXNzYWdlKG9iamVjdCk6CiAgICAnJyfjg6Hjg4Pjgrvjg7zjgrgnJycKICAgIGRlZiBfX2luaXRfXyhzZWxmKToKICAgICAgICBzZWxmLm1lc3NhZ2UgPSB7CiAgICAgICAgICAgICJpbnB1dFNlbGVjdENhcmQiIDogIuS9leaemuebruOBruOCq+ODvOODieOCkuW8leOBjeOBvuOBmeOBiz8gKDAg44CcIHswfSlcbiIsCiAgICAgICAgICAgICJzaG93TnVtQ2FyZCIgOiAi44OX44Os44Kk44Ok44O8ezB944Gu44Kr44O844OJOiB7MX3mnppcbiIsCiAgICAgICAgICAgICJzaG93Q2FyZHMiIDogIuODl+ODrOOCpOODpOODvHswfeOBruOCq+ODvOODiTogezF9XG4iLAogICAgICAgICAgICAic2hvd0Rpc2NhcmRDYXJkcyIgOiAi44OX44Os44Kk44Ok44O8ezB944GM5o2o44Gm44Gf44Kr44O844OJOiB7MX1cbiIsCiAgICAgICAgICAgICJzaG93RHJhd0NhcmQiIDogIuODl+ODrOOCpOODpOODvHswfSAtPiDjg5fjg6zjgqTjg6Tjg7x7MX0gOiB7Mn1cbiIsCiAgICAgICAgICAgICJzaG93UmVzdWx0IiA6ICLjg5fjg6zjgqTjg6Tjg7x7MH3jga7osqDjgZHjgafjgZkuLi5cbiIKICAgICAgICAgICAgfQoKICAgIGRlZiBzaG93Q2FyZHMoc2VsZiwgaWQsIGNhcmRzKToKICAgICAgICAnJyfmiYvmjIHjgaHjga7jgqvjg7zjg4njgpLooajnpLrjgZnjgosnJycKICAgICAgICBpZiBpZCA9PSAwOgogICAgICAgICAgICByZXR1cm4gc2VsZi5tZXNzYWdlWyJzaG93Q2FyZHMiXS5mb3JtYXQoaWQsIHNlbGYuZ2V0Q2FyZHNTdHIoY2FyZHMpKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJldHVybiBzZWxmLm1lc3NhZ2VbInNob3dOdW1DYXJkIl0uZm9ybWF0KGlkLCBsZW4oY2FyZHMpKQoKICAgIGRlZiBzaG93RGlzY2FyZENhcmRzKHNlbGYsIGlkLCBjYXJkcyk6CiAgICAgICAgJycn5o2o44Gm44KJ44KM44Gf44Kr44O844OJ44KS6KGo56S644GZ44KL5paH5a2X5YiXJycnCiAgICAgICAgaWYgY2FyZHMgPT0gW106CiAgICAgICAgICAgIHJldHVybiAiIgogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJldHVybiBzZWxmLm1lc3NhZ2VbInNob3dEaXNjYXJkQ2FyZHMiXS5mb3JtYXQoaWQsIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmdldENhcmRzU3RyKGNhcmRzKSkKCiAgICBkZWYgc2hvd0RyYXdDYXJkKHNlbGYsIGlkMSwgaWQyLCBjYXJkKToKICAgICAgICAnJyfjgqvjg7zjg4njga7kuqTmj5vnirbms4HjgpLooajnpLrjgZnjgovmloflrZfliJcnJycKICAgICAgICByZXR1cm4gc2VsZi5tZXNzYWdlWyJzaG93RHJhd0NhcmQiXS5mb3JtYXQoaWQxLCBpZDIsIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5nZXRDYXJkU3RyKGNhcmQpKQoKICAgIGRlZiBzaG93UmVzdWx0KHNlbGYsIGlkKToKICAgICAgICAnJyfjgrLjg7zjg6Djga7ntZDmnpzjgpLooajnpLrjgZnjgovmloflrZfliJcnJycKICAgICAgICByZXR1cm4gc2VsZi5tZXNzYWdlWyJzaG93UmVzdWx0Il0uZm9ybWF0KGlkKQoKICAgIGRlZiBnZXRDYXJkc1N0cihzZWxmLCBjYXJkcyk6CiAgICAgICAgJycnQ2FyZOOCquODluOCuOOCp+OCr+ODiOOBruODquOCueODiOOCkuaWh+Wtl+WIl+OBq+WkieaPmycnJwogICAgICAgIHJldHVybiAiIi5qb2luKFtzZWxmLmdldENhcmRTdHIoaSkgZm9yIGkgaW4gY2FyZHNdKQoKICAgIGRlZiBnZXRDYXJkU3RyKHNlbGYsIGNhcmQpOgogICAgICAgICcnJ0NhcmTjgqrjg5bjgrjjgqfjgq/jg4jjgpLmloflrZfliJfjgavlpInmj5snJycKICAgICAgICByZXR1cm4gInswfSIuZm9ybWF0KGNhcmQpCgpkZWYgbWFrZV9kZWNrKCk6CiAgICAnJyfjg4jjg6njg7Pjg5fjga7jgqvjg7zjg4njgpLkvZzmiJDjgZnjgosnJycKICAgIHJldHVybiBbQ2FyZCgiSiIsICIwIildICsgW0NhcmQoaSwgIkEiIGlmIGogPT0gMSBlbHNlICJKIiBpZiBqID09IDExIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSAiUSIgaWYgaiA9PSAxMiBlbHNlICJLIiBpZiBqID09IDEzIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHN0cihqKSkgZm9yIGkgaW4gXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCJEIiwgIkgiLCAiUyIsICJDIikgZm9yIGogaW4gXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2UoMSwgMTQpXQoKY2xhc3MgV29ybGQob2JqZWN0KToKICAgICcnJ+eSsOWigycnJwogICAgZGVmIF9faW5pdF9fKHNlbGYsIGNsaXN0LCBwYWlyLCBpZDEsIGlkMiwgcGxheWVycyk6CiAgICAgICAgc2VsZi5jbGlzdCA9IGNsaXN0CiAgICAgICAgc2VsZi5wYWlyID0gcGFpcgogICAgICAgIHNlbGYuaWQxID0gaWQxCiAgICAgICAgc2VsZi5pZDIgPSBpZDIKICAgICAgICBzZWxmLnBsYXllcnMgPSBwbGF5ZXJzCgogICAgZGVmIGluc2VydChzZWxmLCBpLCBqLCBwbGF5ZXIxLCBwbGF5ZXIyKToKICAgICAgICBzZWxmLnBsYXllcnNbaV0gPSBwbGF5ZXIxCiAgICAgICAgc2VsZi5wbGF5ZXJzW2pdID0gcGxheWVyMgogICAgICAgIHJldHVybiBzZWxmCgogICAgZGVmIG5leHRfaWQoc2VsZik6CiAgICAgICAgc2VsZi5wYWlyID0gW3NlbGYuaWQxLCBzZWxmLmlkMl0KICAgICAgICBzZWxmLmlkMSA9IG5leHRfaWQoc2VsZi5jbGlzdCwgc2VsZi5pZDEgKyAxLCBzZWxmLnBsYXllcnMpCiAgICAgICAgc2VsZi5pZDIgPSBuZXh0X2lkKHNlbGYuY2xpc3QsIHNlbGYuaWQxICsgMSwgc2VsZi5wbGF5ZXJzKQogICAgICAgIHJldHVybiBzZWxmCgpkZWYgbmV4dF9pZChjbGlzdCwgaSwgcGxheWVycyk6CiAgICB3aGlsZSBUcnVlOgogICAgICAgIHBvcyA9IGNsaXN0W2kgJSBsZW4oY2xpc3QpXQogICAgICAgIGNhcmRzID0gcGxheWVyc1twb3NdLmNhcmRzCiAgICAgICAgaWYgY2FyZHMgIT0gW106CiAgICAgICAgICAgIHJldHVybiBwb3MKICAgICAgICBpICs9IDEKCiMgcmVhZAoKZGVmIHJlYWQodyk6CiAgICBpZDEsIGlkMiwgcGxheWVycyA9IHcuaWQxLCB3LmlkMiwgdy5wbGF5ZXJzCiAgICBrID0gbGVuKHBsYXllcnNbaWQyXS5jYXJkcykKICAgIG0gPSBNZXNzYWdlKCkKICAgIGlmIGlkMSA9PSAwOgogICAgICAgIHJldHVybiBpbnQoaW5wdXQobS5tZXNzYWdlWyJpbnB1dFNlbGVjdENhcmQiXS5mb3JtYXQoayAtIDEpKSkKICAgIGVsc2U6CiAgICAgICAgcmV0dXJuIHNlbGVjdENhcmQoaykKCiMgZXZhbAoKZGVmIHdvcmxkX2dvKGV4cCwgdyk6CiAgICBpZDEsIGlkMiwgcGxheWVycyA9IHcuaWQxLCB3LmlkMiwgdy5wbGF5ZXJzCiAgICBwbGF5ZXIxLCBwbGF5ZXIyID0gcGxheWVyc1tpZDFdLCBwbGF5ZXJzW2lkMl0KICAgIHBsYXllcjIgPSBwbGF5ZXIxLmRyYXdDYXJkKHBsYXllcjIsIGV4cCkKICAgIHJldHVybiB3Lmluc2VydChpZDEsIGlkMiwgcGxheWVyMS5kaXNjYXJkUGFpcigpLCBwbGF5ZXIyKS5uZXh0X2lkKCkgCgojIHByaW50CgpkZWYgZGlzcGxheSh3KToKICAgIHBhaXIsIHBsYXllcnMgPSB3LnBhaXIsIHcucGxheWVycwogICAgaGVhZCwgdGFpbCA9IHBhaXJbMF0sIHBhaXJbMV0KICAgIHBsYXllciA9IHBsYXllcnNbaGVhZF0KICAgIG0gPSBNZXNzYWdlKCkKICAgIHByaW50KG0uc2hvd0RyYXdDYXJkKHRhaWwsIGhlYWQsIHBsYXllci5jYXJkKSArIFwKICAgICAgICAgIHBsYXllci5zaG93RGlzY2FyZENhcmRzKGhlYWQpICsgXAogICAgICAgICAgIiIuam9pbihbai5zaG93Q2FyZHMoaSkgZm9yIGksIGogaW4gZW51bWVyYXRlKHBsYXllcnMpXSksIGVuZCA9IiIpCiAgICByZXR1cm4gdwoKZGVmIGlzX2dhbWVfZW5kcyh3KToKICAgICcnJ+OCsuODvOODoOe1guS6huWIpOWumicnJwogICAgcmV0dXJuIHcuaWQxID09IHcuaWQyCgojIOWIneacn+WMlgoKZGVmIGluaXRpYWxpemUobik6CiAgICBwbGF5ZXJzID0gZGVhbENhcmRzKHNodWZmbGVfbGlzdChtYWtlX2RlY2soKSwgNyksIG4pCiAgICBbcHJpbnQoai5zaG93Q2FyZHMoaSksIGVuZCA9ICIiKSBmb3IgaSwgaiBpbiBlbnVtZXJhdGUocGxheWVycyldCiAgICBbcC5kaXNjYXJkUGFpcigpIGZvciBwIGluIHBsYXllcnNdCiAgICBbcHJpbnQoai5zaG93RGlzY2FyZENhcmRzKGkpLCBlbmQgPSAiIikgZm9yIGksIGogaW4gZW51bWVyYXRlKHBsYXllcnMpXQogICAgW3ByaW50KGouc2hvd0NhcmRzKGkpLCBlbmQgPSAiIikgZm9yIGksIGogaW4gZW51bWVyYXRlKHBsYXllcnMpXQogICAgcmV0dXJuIFdvcmxkKGxpc3QocmFuZ2UobikpLCBbXSwgMCwgMSwgcGxheWVycykKCmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6CiAgICAnJydSRVBMJycnCiAgICB3ID0gaW5pdGlhbGl6ZShpbnQoYXJndlsxXSkpCiAgICBtID0gTWVzc2FnZSgpCiAgICB3aGlsZSBUcnVlOgogICAgICAgIGlmIGlzX2dhbWVfZW5kcyh3KToKICAgICAgICAgICAgcHJpbnQobS5zaG93UmVzdWx0KHcuaWQxKSkKICAgICAgICAgICAgZXhpdCgpCiAgICAgICAgdHJ5OgogICAgICAgICAgICB3ID0gZGlzcGxheSh3b3JsZF9nbyhyZWFkKHcpLCB3KSkKICAgICAgICBleGNlcHQgSW5kZXhFcnJvcjoKICAgICAgICAgICAgcHJpbnQoIuS4jeato+OBquWFpeWKm+OBp+OBmSIpCiAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6CiAgICAgICAgICAgIHByaW50KCLkuI3mraPjgarlhaXlipvjgafjgZkiKQogICAgICAgIGZpbmFsbHk6CiAgICAgICAgICAgIHcK