Author | Sean |
Submission date | 2018-08-31 07:18:56.956360 |
Rating | 7777 |
Matches played | 278 |
Win rate | 75.18 |
Use rpsrunner.py to play unranked matches on your computer.
if input == "":
import collections
import math
import random
gamma = random.gammavariate
sqrt = math.sqrt
log = math.log
moves = R, P, S = 0, 1, 2
index = {"R": R, "P": P, "S": S}
good_against = (P, S, R)
bad_against = (S, R, P)
name = ("R", "P", "S")
third = 1. / 3
hash_codes = [random.randint(0, 0xFFFFFFFF) for _ in range(40)]
def belief(counts):
counts = [random.gammavariate(n, 1) for n in counts]
t = sum(counts)
return [n / t for n in counts]
class MarkovPredictor:
def __init__(self):
self.table = {}
def update(self, h):
hash_code = 0
s = h[-1]
bound = min(11, len(h))
for d in range(2, bound):
c = h[-d]
hash_code ^= hash_codes[3 * d + c]
self.table[hash_code] = s
def predict(self, h):
seen = 0
hash_code = 0
bound = min(11, len(h)+1)
for d in range(2, bound):
c = h[-(d-1)]
hash_code ^= hash_codes[3 * d + c]
if hash_code in self.table:
seen = self.table[hash_code]
else:
break
return seen
class FrequencyPredictor:
def __init__(self, k=1):
self.k=k
self.counts = [third] * 3
def update(self, h):
self.counts[h[-1]] += 1
for i, _ in enumerate(self.counts):
self.counts[i] *= self.k
def predict(self, h):
p = belief(self.counts)
scores = [p[bad_against[m]] - p[good_against[m]] for m in moves]
return scores.index(max(scores))
class MetaPredictor:
def __init__(self, predictor):
self.predictor = predictor()
self.self_predictor = predictor()
self.prediction = None
self.self_prediction = None
self.counts = [[third] * 3 for _ in range(6)]
def update(self, h0, h1):
s = h0[-1]
if self.prediction is not None:
p = self.prediction
for i, counts in enumerate(self.counts):
if i == 3:
p = self.self_prediction
m = (p + i) % 3
counts[(s - m) % 3] += 1
self.predictor.update(h0)
self.self_predictor.update(h1)
def predictions(self, h0, h1):
self.prediction = self.predictor.predict(h0)
self.self_prediction = self.self_predictor.predict(h1)
p = self.prediction
for i, counts in enumerate(self.counts):
if i == 3:
p = self.self_prediction
m = (p + i) % 3
n = [0] * 3
for d in range(3):
n[(m + d) % 3] = counts[d]
yield n
class RandomPredictor:
def __init__(self):
pass
def update(self, h0, h1):
pass
def predictions(self, h0, h1):
yield [third] * 3
class PredictionBlender:
def __init__(self, predictors):
self.predictors = predictors
self.counts = None
self.predictions = None
def update(self, h0, h1):
s = h0[-1]
if self.predictions is not None:
for i, counts in enumerate(self.predictions):
self.counts[i] += counts[s]
for predictor in self.predictors:
predictor.update(h0, h1)
def predict(self, h0, h1):
self.predictions = []
for predictor in self.predictors:
for counts in predictor.predictions(h0, h1):
self.predictions.append(counts)
if self.counts is None:
n = len(self.predictions)
self.counts = [0.5] * n
random_predictions = [belief(counts) for counts in self.predictions]
weights = belief(self.counts)
p = [0] * 3
for q, w in zip(random_predictions, weights):
for i in range(3):
p[i] += w * q[i]
scores = [p[bad_against[m]] - p[good_against[m]] for m in moves]
return scores.index(max(scores))
predictors = [
MetaPredictor(MarkovPredictor),
MetaPredictor(FrequencyPredictor),
MetaPredictor(lambda: FrequencyPredictor(k=0.99)),
MetaPredictor(lambda: FrequencyPredictor(k=0.9)),
MetaPredictor(lambda: FrequencyPredictor(k=0.8)),
MetaPredictor(lambda: FrequencyPredictor(k=0.5)),
RandomPredictor()
]
model = PredictionBlender(predictors)
h0 = []
h1 = []
output = random.choice(name)
else:
us = index[output]
them = index[input]
h0.append(them)
h1.append(us)
model.update(h0, h1)
h0.append(us)
h1.append(them)
output = name[model.predict(h0, h1)]