#!/usr/bin/python3
_cache = {}
def sums(addends, sum):
"""Return list of tuples of @addends addends that sums up to @sum."""
global _cache
if addends < 1 or sum < addends:
return []
if (addends, sum) not in _cache:
result = [] if addends > 1 else [(sum,)]
for d in reversed(range(1, sum)):
result.extend([(d,) + a for a in sums(addends-1, sum-d) if len(a) == 0 or d >= a[0]])
_cache[addends, sum] = result
return _cache[addends, sum]
def compare(dieA, dieB):
"""Return sum over all possible die game results.
Die A wins: +1, die B wins -1, tie: 0."""
return sum([1 if a > b else -1 for a in dieA for b in dieB if a != b])
def iterate():
"""Return the best die for me if opponent has die X with given probability (distribution[X]).
Then update distribution to linear (0: worst die, max: best die (max chosen in such a way that probs add up to one))
or uniformly choose k-best dice."""
global dice, distribution, score
score = {}
for myDie in dice:
score[myDie] = 0
for otherDie in dice:
score[myDie] += compare(myDie, otherDie) * distribution[otherDie]
dice = sorted(dice, key=lambda die: score[die], reverse=True)
#distribution = {die: 2*i/len(dice)**2 for i, die in enumerate(reversed(dice), 1)}
best = 3
distribution = {die: 1/best if die in dice[:best] else 0 for i, die in enumerate(reversed(dice), 1)}
def reportAll():
global score, dice
for die in dice:
print("{}\t{}\t".format(die, score[die]), distribution[die])
# initialize to uniform distribution
dice = sums(6, 27)
distribution = {die: 1/len(dice) for die in dice}
score = {die: 0 for die in dice}
# iterate and print best die
for _ in range(20):
die = dice[0]
print("{}\t{}\t".format(die, score[die]), distribution[die])
iterate()
IyEvdXNyL2Jpbi9weXRob24zCgpfY2FjaGUgPSB7fQpkZWYgc3VtcyhhZGRlbmRzLCBzdW0pOgogICAgIiIiUmV0dXJuIGxpc3Qgb2YgdHVwbGVzIG9mIEBhZGRlbmRzIGFkZGVuZHMgdGhhdCBzdW1zIHVwIHRvIEBzdW0uIiIiCiAgICBnbG9iYWwgX2NhY2hlCiAgICBpZiBhZGRlbmRzIDwgMSBvciBzdW0gPCBhZGRlbmRzOgogICAgICAgIHJldHVybiBbXQogICAgaWYgKGFkZGVuZHMsIHN1bSkgbm90IGluIF9jYWNoZToKICAgICAgICByZXN1bHQgPSBbXSBpZiBhZGRlbmRzID4gMSBlbHNlIFsoc3VtLCldCiAgICAgICAgZm9yIGQgaW4gcmV2ZXJzZWQocmFuZ2UoMSwgc3VtKSk6ICAgICAgICAgICAgCiAgICAgICAgICAgIHJlc3VsdC5leHRlbmQoWyhkLCkgKyBhIGZvciBhIGluIHN1bXMoYWRkZW5kcy0xLCBzdW0tZCkgaWYgbGVuKGEpID09IDAgb3IgZCA+PSBhWzBdXSkKICAgICAgICBfY2FjaGVbYWRkZW5kcywgc3VtXSA9IHJlc3VsdAogICAgcmV0dXJuIF9jYWNoZVthZGRlbmRzLCBzdW1dCiAgICAKZGVmIGNvbXBhcmUoZGllQSwgZGllQik6CiAgICAiIiJSZXR1cm4gc3VtIG92ZXIgYWxsIHBvc3NpYmxlIGRpZSBnYW1lIHJlc3VsdHMuCiAgICBEaWUgQSB3aW5zOiArMSwgZGllIEIgd2lucyAtMSwgdGllOiAwLiIiIgogICAgcmV0dXJuIHN1bShbMSBpZiBhID4gYiBlbHNlIC0xIGZvciBhIGluIGRpZUEgZm9yIGIgaW4gZGllQiBpZiBhICE9IGJdKQoKCgpkZWYgaXRlcmF0ZSgpOgogICAgIiIiUmV0dXJuIHRoZSBiZXN0IGRpZSBmb3IgbWUgaWYgb3Bwb25lbnQgaGFzIGRpZSBYIHdpdGggZ2l2ZW4gcHJvYmFiaWxpdHkgKGRpc3RyaWJ1dGlvbltYXSkuCiAgICBUaGVuIHVwZGF0ZSBkaXN0cmlidXRpb24gdG8gbGluZWFyICgwOiB3b3JzdCBkaWUsIG1heDogYmVzdCBkaWUgKG1heCBjaG9zZW4gaW4gc3VjaCBhIHdheSB0aGF0IHByb2JzIGFkZCB1cCB0byBvbmUpKQogICAgIG9yIHVuaWZvcm1seSBjaG9vc2Ugay1iZXN0IGRpY2UuIiIiCiAgICBnbG9iYWwgZGljZSwgZGlzdHJpYnV0aW9uLCBzY29yZQogICAgc2NvcmUgPSB7fQogICAgZm9yIG15RGllIGluIGRpY2U6CiAgICAgICAgc2NvcmVbbXlEaWVdID0gMAogICAgICAgIGZvciBvdGhlckRpZSBpbiBkaWNlOgogICAgICAgICAgICBzY29yZVtteURpZV0gKz0gY29tcGFyZShteURpZSwgb3RoZXJEaWUpICogZGlzdHJpYnV0aW9uW290aGVyRGllXQogICAgZGljZSA9IHNvcnRlZChkaWNlLCBrZXk9bGFtYmRhIGRpZTogc2NvcmVbZGllXSwgcmV2ZXJzZT1UcnVlKQogICAgI2Rpc3RyaWJ1dGlvbiA9IHtkaWU6IDIqaS9sZW4oZGljZSkqKjIgZm9yIGksIGRpZSBpbiBlbnVtZXJhdGUocmV2ZXJzZWQoZGljZSksIDEpfQogICAgYmVzdCA9IDMKICAgIGRpc3RyaWJ1dGlvbiA9IHtkaWU6IDEvYmVzdCBpZiBkaWUgaW4gZGljZVs6YmVzdF0gZWxzZSAwIGZvciBpLCBkaWUgaW4gZW51bWVyYXRlKHJldmVyc2VkKGRpY2UpLCAxKX0KICAgIApkZWYgcmVwb3J0QWxsKCk6CiAgICBnbG9iYWwgc2NvcmUsIGRpY2UKICAgIGZvciBkaWUgaW4gZGljZToKICAgICAgICBwcmludCgie31cdHt9XHQiLmZvcm1hdChkaWUsIHNjb3JlW2RpZV0pLCBkaXN0cmlidXRpb25bZGllXSkKCiMgaW5pdGlhbGl6ZSB0byB1bmlmb3JtIGRpc3RyaWJ1dGlvbgpkaWNlID0gc3Vtcyg2LCAyNykKZGlzdHJpYnV0aW9uID0ge2RpZTogMS9sZW4oZGljZSkgZm9yIGRpZSBpbiBkaWNlfQpzY29yZSA9IHtkaWU6IDAgZm9yIGRpZSBpbiBkaWNlfQoKIyBpdGVyYXRlIGFuZCBwcmludCBiZXN0IGRpZQpmb3IgXyBpbiByYW5nZSgyMCk6CiAgICBkaWUgPSBkaWNlWzBdCiAgICBwcmludCgie31cdHt9XHQiLmZvcm1hdChkaWUsIHNjb3JlW2RpZV0pLCBkaXN0cmlidXRpb25bZGllXSkKICAgIGl0ZXJhdGUoKQ==