CTW-6H Fixed

This program has been disqualified.


AuthorSean
Submission date2016-04-28 15:54:39.255225
Rating7371
Matches played84
Win rate76.19

Source code:

if input == "":

    import array
    import math
    log = math.log
    exp = math.exp
    log_half = log(1/2.0)
    log_third = log(1/3.0)
    log_sixth = log(1/6.0)
    log_p_self0 = log(1) - log(3)

    def safe_exp(x):
        if x <= -100:
            return 0
        if x >= 100:
            return float("inf")
        return exp(x)

    def log_add(x, y):
        if y > x:
            x, y = y, x
        d = y - x
        if d < -20:
            return x
        return x + log(1.0 + exp(d))

    def smooth(counts, x):
        return log(counts[x] + 1) - log(sum(counts) + len(counts))

    def predict_leaf(history, i):
        if i >= len(history) - 1 or i >= 16:
            return log_p_self0
        return log_add(log_p_self0, predict_leaf(history, i+1)) + log_half

    class ContextTree:
        def __init__(self, n=3):
            self.log_p_self = 0.0
            self.log_p = 0.0
            self.counts = array.array('i',(0 for _ in xrange(n)))
            self.total = 0
            self.children = None
        def update(self, history, i=0):
            x = history[i]
            if x >= len(self.counts):
                x -= 3
            self.log_p_self += smooth(self.counts, x)
            self.total += 1
            self.counts[x] += 1
            if i >= len(history) - 1 or i >= 16:
                self.log_p = self.log_p_self
                return
            if self.children is None:
                self.children = [None for _ in xrange(len(self.counts))]
            if self.children[x] is None:
                self.children[x] = ContextTree()
            self.children[x].update(history, i + 1)
            log_p_children = 0
            for child in self.children:
                if child is not None:
                    log_p_children += child.log_p
            self.log_p = log_add(self.log_p_self, log_p_children) + log_half
        def predict(self, history, i=0):
            x = history[i]
            if x >= len(self.counts):
                x -= 3
            log_p_self = self.log_p_self + smooth(self.counts, x)
            if i >= len(history) - 1 or i >= 16:
                return log_p_self
            if self.children is None or self.children[x] is None:
                log_p_children = predict_leaf(history, i + 1)
            else:
                log_p_children = self.children[x].predict(history, i + 1)
            if self.children is not None:
                for y, child in enumerate(self.children):
                    if child is not None and x != y:
                        log_p_children += child.log_p
            return log_add(log_p_self, log_p_children) + log_half

    import collections
    import random
    R, P, S = 0, 1, 2
    index = {"R": R, "P": P, "S": S}
    name = ("R", "P", "S")
    beat = (P, S, R)
    beaten = (S, R, P)
    model = ContextTree(6)
    history = collections.deque([])
    output = random.choice(name)
    counts = [0, 0, 0]
else:
    i = index[input]
    j = index[output]
    counts[i] += 1
    history.appendleft(i)
    model.update(history)
    history.appendleft(j + 3)
    model.update(history)
    log_ps = [0.0, 0.0, 0.0]
    log_t = float("-inf")
    for i in xrange(3):
        history.appendleft(i)
        log_p = model.predict(history)
        history.popleft()
        log_t = log_add(log_t, log_p)
	log_ps[i] = log_p
    ps = [safe_exp(log_p - log_t) for log_p in log_ps]
    r, p, s = ps
    total = sum(ps)
    scores = [0, 0, 0]
    for i in xrange(3):
	r = random.uniform(0, total)
	t = 0
	for j in xrange(6):
	    t += ps[j]
	    if t >= r:
		break
	scores[beat[j]] += 1
	scores[beaten[j]] -= 1
    best = max(scores)
    output = name[random.choice([i for i in xrange(3) if scores[i] == best])]