import random
import math
from enum import Enum
SEED = 6564164
MAX_MOVES = 5000
# MAX_MOVES = 3
class Player(Enum):
ALGOSIA = 0
BAJTEK = 1
def get_player(name: str) -> Player:
if name == "Algosia":
return Player.ALGOSIA
elif name == "Bajtek":
return Player.BAJTEK
else:
raise ValueError(f"Wrong player name {name}!")
class Randomizer:
def __init__(self, player: Player):
random.seed(SEED, version=2)
self.player = player
def get_rand(self) -> tuple[int, int]:
my_num = random.randint(0, 23)
his_num = random.randint(0, 23)
if self.player == Player.ALGOSIA:
return my_num, his_num
elif self.player == Player.BAJTEK:
return his_num, my_num
else:
raise ValueError(f"Invalid Player!")
class Move:
def __init__(self, ch: str):
self.ch = ch
if ch == 'P':
self.nr = 0
elif ch == 'N':
self.nr = 1
elif ch == 'K':
self.nr = 2
else:
raise ValueError(f"Wrong move {ch}!")
# 0 -> draw
# 1 -> win
# 2 -> lost
@classmethod
def beats(cls, weak, strong) -> int:
return (strong.nr - weak.nr + 3) % 3
@classmethod
def from_number(cls, nr):
nr = nr % 3
if nr == 0:
return Move('P')
elif nr == 1:
return Move('N')
elif nr == 2:
return Move('K')
else:
raise ValueError(f"Wrong move number {nr}!")
class Game:
def __init__(self):
self.diff = 0
def play(self, me: Move, him: Move):
result = Move.beats(him, me)
if result == 0:
pass
elif result == 1:
self.diff += 1
elif result == 2:
self.diff -= 1
else:
raise ValueError(f"Wrong result {ch}!")
class Secret:
def __init__(self, seq: str):
self.number = int(seq, 2)
self.remember = -1
def encode(self, base: int) -> int:
if base < 2 or base > 4:
raise ValueError(f"Incorrect base {base}!")
if self.remember != -1 and base != 3:
raise ValueError(f"Incorrect combination! {self.remember}, {base}")
if self.remember != -1:
ret = self.remember
self.remember = -1
return ret
ret = self.number % base
self.number //= base
if base == 4:
if ret == 3:
return 0
else:
self.remember = ret
return 1
return ret
@classmethod
def decode(cls, n: int, msgs: list[tuple[int, int]]) -> str:
res = 0
lazy = False
for val, base in reversed(msgs):
if 0 > val or val >= base or base < 2 or base > 6:
raise ValueError(f"Incorrect messages {val}, {base}!")
if lazy and base != 4:
raise ValueError("Cannot be lazy and base non 3!")
if lazy:
lazy = False
continue
if base == 6:
res *= 4
res += val
lazy = True
continue
if base == 4:
if val == 1:
continue
res *= 4
res += 3
continue
res *= base
res += val
return "{0:b}".format(res).zfill(n)
class Interactor:
def play(self, move: Move) -> Move:
print(move.ch, flush=True)
return Move(input())
def answer(self, result: str):
print(f"! {result}", flush=True)
def solve(n: int, player: Player, randomizer: Randomizer):
my_secret = Secret(input())
game = Game()
interactor = Interactor()
messages = []
# power = 0.0
my_status = 0.0
his_status = 0.0
was_zero = True
for i in range(MAX_MOVES):
my_num, his_num = randomizer.get_rand()
# do_skip = bool(randomizer.get_rand() % 2 == 0)
if game.diff == 0:
# power += math.log(3)
my_status += math.log(3)
his_status += math.log(3)
val = my_secret.encode(3)
my_move = Move.from_number(val + my_num)
his_move = interactor.play(my_move)
base = 3
if not was_zero:
base = 6
messages.append(((his_move.nr - his_num) % 3, base))
game.play(my_move, his_move)
was_zero = True
elif game.diff == 1: # and my_status < his_status:
# power += math.log(2)
my_status += math.log(2)
my_move = Move.from_number(his_num % 3)
his_move = interactor.play(my_move)
messages.append(((his_move.nr - his_num) % 3, 4))
game.play(my_move, his_move)
was_zero = False
elif game.diff == -1: # and his_status < my_status:
his_status += math.log(2)
val = my_secret.encode(4)
my_move = Move.from_number((val + my_num) % 3)
his_move = interactor.play(my_move)
game.play(my_move, his_move)
else:
raise ValueError(f"Incorrect game state {game.diff}!")
# raise ValueError(f"Hey, done, , {my_status}, {his_status}!")
interactor.answer(Secret.decode(n, messages))
def main():
player = get_player(input())
n, t = map(int, input().split())
# print("Hey, I got all the init!")
randomizer = Randomizer(player)
for case in range(t):
solve(n, player, randomizer)
if __name__ == '__main__':
main()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | import random import math from enum import Enum SEED = 6564164 MAX_MOVES = 5000 # MAX_MOVES = 3 class Player(Enum): ALGOSIA = 0 BAJTEK = 1 def get_player(name: str) -> Player: if name == "Algosia": return Player.ALGOSIA elif name == "Bajtek": return Player.BAJTEK else: raise ValueError(f"Wrong player name {name}!") class Randomizer: def __init__(self, player: Player): random.seed(SEED, version=2) self.player = player def get_rand(self) -> tuple[int, int]: my_num = random.randint(0, 23) his_num = random.randint(0, 23) if self.player == Player.ALGOSIA: return my_num, his_num elif self.player == Player.BAJTEK: return his_num, my_num else: raise ValueError(f"Invalid Player!") class Move: def __init__(self, ch: str): self.ch = ch if ch == 'P': self.nr = 0 elif ch == 'N': self.nr = 1 elif ch == 'K': self.nr = 2 else: raise ValueError(f"Wrong move {ch}!") # 0 -> draw # 1 -> win # 2 -> lost @classmethod def beats(cls, weak, strong) -> int: return (strong.nr - weak.nr + 3) % 3 @classmethod def from_number(cls, nr): nr = nr % 3 if nr == 0: return Move('P') elif nr == 1: return Move('N') elif nr == 2: return Move('K') else: raise ValueError(f"Wrong move number {nr}!") class Game: def __init__(self): self.diff = 0 def play(self, me: Move, him: Move): result = Move.beats(him, me) if result == 0: pass elif result == 1: self.diff += 1 elif result == 2: self.diff -= 1 else: raise ValueError(f"Wrong result {ch}!") class Secret: def __init__(self, seq: str): self.number = int(seq, 2) self.remember = -1 def encode(self, base: int) -> int: if base < 2 or base > 4: raise ValueError(f"Incorrect base {base}!") if self.remember != -1 and base != 3: raise ValueError(f"Incorrect combination! {self.remember}, {base}") if self.remember != -1: ret = self.remember self.remember = -1 return ret ret = self.number % base self.number //= base if base == 4: if ret == 3: return 0 else: self.remember = ret return 1 return ret @classmethod def decode(cls, n: int, msgs: list[tuple[int, int]]) -> str: res = 0 lazy = False for val, base in reversed(msgs): if 0 > val or val >= base or base < 2 or base > 6: raise ValueError(f"Incorrect messages {val}, {base}!") if lazy and base != 4: raise ValueError("Cannot be lazy and base non 3!") if lazy: lazy = False continue if base == 6: res *= 4 res += val lazy = True continue if base == 4: if val == 1: continue res *= 4 res += 3 continue res *= base res += val return "{0:b}".format(res).zfill(n) class Interactor: def play(self, move: Move) -> Move: print(move.ch, flush=True) return Move(input()) def answer(self, result: str): print(f"! {result}", flush=True) def solve(n: int, player: Player, randomizer: Randomizer): my_secret = Secret(input()) game = Game() interactor = Interactor() messages = [] # power = 0.0 my_status = 0.0 his_status = 0.0 was_zero = True for i in range(MAX_MOVES): my_num, his_num = randomizer.get_rand() # do_skip = bool(randomizer.get_rand() % 2 == 0) if game.diff == 0: # power += math.log(3) my_status += math.log(3) his_status += math.log(3) val = my_secret.encode(3) my_move = Move.from_number(val + my_num) his_move = interactor.play(my_move) base = 3 if not was_zero: base = 6 messages.append(((his_move.nr - his_num) % 3, base)) game.play(my_move, his_move) was_zero = True elif game.diff == 1: # and my_status < his_status: # power += math.log(2) my_status += math.log(2) my_move = Move.from_number(his_num % 3) his_move = interactor.play(my_move) messages.append(((his_move.nr - his_num) % 3, 4)) game.play(my_move, his_move) was_zero = False elif game.diff == -1: # and his_status < my_status: his_status += math.log(2) val = my_secret.encode(4) my_move = Move.from_number((val + my_num) % 3) his_move = interactor.play(my_move) game.play(my_move, his_move) else: raise ValueError(f"Incorrect game state {game.diff}!") # raise ValueError(f"Hey, done, , {my_status}, {his_status}!") interactor.answer(Secret.decode(n, messages)) def main(): player = get_player(input()) n, t = map(int, input().split()) # print("Hey, I got all the init!") randomizer = Randomizer(player) for case in range(t): solve(n, player, randomizer) if __name__ == '__main__': main() |
English