#Output from this script:
# Using keepThrees expected score is 1.75 (2943216 total points from 1679616 possible outcomes)
# Using keepDoubles expected score is 1.81 (1225 total points from 676 possible outcomes)
# Using stratThree expected score is 1.94 (47046 total points from 24266 possible outcomes)
from itertools import *
faces = [1,2,3,4,5,6]
def score(dice):
"""Calculate the score for a set of dice"""
total = 0
for i in [1,2,3]:
if dice.count(i) > 2:
total += (dice.count(i) + i - 3)
return total
def keepThrees(dice):
"""Keep any 3s, reroll everything else"""
keepers = []
for die in diceAfterOneRoll:
if die == 3:
keepers.append(die)
return keepers
def keepDoubles(dice):
"""Keep 2s and/or 3s if we have at least a pair of them"""
keepers = []
for value in [2,3]:
if dice.count(value) >= 2:
keepers += [value]*dice.count(value)
return keepers
def stratThreeSecondRoll(dice):
"""The improved second roll strategy that is part of 'strat 3'"""
twos = dice.count(2)
threes = dice.count(3)
if twos == 3 and threes == 3:
return dice
elif twos >= 3:
return [2]*twos
else:
return [3]*threes
# The three strategies - name, first roll strategy, second roll strategy
keepStrategies = [['keepThrees', [keepThrees, keepThrees]],
['keepDoubles', [keepDoubles, keepDoubles]],
['stratThree', [keepDoubles, stratThreeSecondRoll]]]
# Test all dice rolls for each strategy
for name, keepFunctions in keepStrategies:
total = 0
count = 0
diceAfterOneRoll = (2,2,3,3,6,6)
keepersAfterOneRoll = keepFunctions[0](diceAfterOneRoll)
numberToRoll = 6 - len(keepersAfterOneRoll)
# Loop through all possible second throws
for rerolledDice in product(faces, repeat=numberToRoll):
diceAfterTwoRolls = tuple(sorted(rerolledDice+tuple(keepersAfterOneRoll)))
keepersAfterTwoRolls = keepFunctions[1](diceAfterTwoRolls)
numberToRollAfterTwoRolls = 6 - len(keepersAfterTwoRolls)
# Loop through all possible third throws
for rererolledDice in product(faces, repeat=numberToRollAfterTwoRolls):
diceAfterThreeRolls = tuple(sorted(rererolledDice+tuple(keepersAfterTwoRolls)))
total += score(diceAfterThreeRolls)
count += 1
print 'Using %s expected score is %0.2f (%d total points from %d possible outcomes)'%(name, 1.0*total/count, total, count)
I091dHB1dCBmcm9tIHRoaXMgc2NyaXB0OgojIFVzaW5nIGtlZXBUaHJlZXMgZXhwZWN0ZWQgc2NvcmUgaXMgMS43NSAoMjk0MzIxNiB0b3RhbCBwb2ludHMgZnJvbSAxNjc5NjE2IHBvc3NpYmxlIG91dGNvbWVzKQojIFVzaW5nIGtlZXBEb3VibGVzIGV4cGVjdGVkIHNjb3JlIGlzIDEuODEgKDEyMjUgdG90YWwgcG9pbnRzIGZyb20gNjc2IHBvc3NpYmxlIG91dGNvbWVzKQojIFVzaW5nIHN0cmF0VGhyZWUgZXhwZWN0ZWQgc2NvcmUgaXMgMS45NCAoNDcwNDYgdG90YWwgcG9pbnRzIGZyb20gMjQyNjYgcG9zc2libGUgb3V0Y29tZXMpCgpmcm9tIGl0ZXJ0b29scyBpbXBvcnQgKgoKZmFjZXMgPSBbMSwyLDMsNCw1LDZdCgpkZWYgc2NvcmUoZGljZSk6CgkiIiJDYWxjdWxhdGUgdGhlIHNjb3JlIGZvciBhIHNldCBvZiBkaWNlIiIiCgl0b3RhbCA9IDAKCWZvciBpIGluIFsxLDIsM106CgkJaWYgZGljZS5jb3VudChpKSA+IDI6CgkJCXRvdGFsICs9IChkaWNlLmNvdW50KGkpICsgaSAtIDMpCglyZXR1cm4gdG90YWwKCmRlZiBrZWVwVGhyZWVzKGRpY2UpOgoJIiIiS2VlcCBhbnkgM3MsIHJlcm9sbCBldmVyeXRoaW5nIGVsc2UiIiIKCWtlZXBlcnMgPSBbXQoJZm9yIGRpZSBpbiBkaWNlQWZ0ZXJPbmVSb2xsOgoJCWlmIGRpZSA9PSAzOgoJCQlrZWVwZXJzLmFwcGVuZChkaWUpCglyZXR1cm4ga2VlcGVycwoKZGVmIGtlZXBEb3VibGVzKGRpY2UpOgoJIiIiS2VlcCAycyBhbmQvb3IgM3MgaWYgd2UgaGF2ZSBhdCBsZWFzdCBhIHBhaXIgb2YgdGhlbSIiIgoJa2VlcGVycyA9IFtdCglmb3IgdmFsdWUgaW4gWzIsM106CgkJaWYgZGljZS5jb3VudCh2YWx1ZSkgPj0gMjoKCQkJa2VlcGVycyArPSBbdmFsdWVdKmRpY2UuY291bnQodmFsdWUpCglyZXR1cm4ga2VlcGVycwoKZGVmIHN0cmF0VGhyZWVTZWNvbmRSb2xsKGRpY2UpOgoJIiIiVGhlIGltcHJvdmVkIHNlY29uZCByb2xsIHN0cmF0ZWd5IHRoYXQgaXMgcGFydCBvZiAnc3RyYXQgMyciIiIKCXR3b3MgPSBkaWNlLmNvdW50KDIpCgl0aHJlZXMgPSBkaWNlLmNvdW50KDMpCglpZiB0d29zID09IDMgYW5kIHRocmVlcyA9PSAzOgoJCXJldHVybiBkaWNlCgllbGlmIHR3b3MgPj0gMzoKCQlyZXR1cm4gWzJdKnR3b3MKCWVsc2U6CgkJcmV0dXJuIFszXSp0aHJlZXMKCiMgVGhlIHRocmVlIHN0cmF0ZWdpZXMgLSBuYW1lLCBmaXJzdCByb2xsIHN0cmF0ZWd5LCBzZWNvbmQgcm9sbCBzdHJhdGVneQprZWVwU3RyYXRlZ2llcyA9IFtbJ2tlZXBUaHJlZXMnLCBba2VlcFRocmVlcywga2VlcFRocmVlc11dLAogICAgICAgICAgICAgICAgICBbJ2tlZXBEb3VibGVzJywgW2tlZXBEb3VibGVzLCBrZWVwRG91Ymxlc11dLAogICAgICAgICAgICAgICAgICBbJ3N0cmF0VGhyZWUnLCBba2VlcERvdWJsZXMsIHN0cmF0VGhyZWVTZWNvbmRSb2xsXV1dCgojIFRlc3QgYWxsIGRpY2Ugcm9sbHMgZm9yIGVhY2ggc3RyYXRlZ3kKZm9yIG5hbWUsIGtlZXBGdW5jdGlvbnMgaW4ga2VlcFN0cmF0ZWdpZXM6Cgl0b3RhbCA9IDAKCWNvdW50ID0gMAoJZGljZUFmdGVyT25lUm9sbCA9ICgyLDIsMywzLDYsNikKCWtlZXBlcnNBZnRlck9uZVJvbGwgPSBrZWVwRnVuY3Rpb25zWzBdKGRpY2VBZnRlck9uZVJvbGwpCgludW1iZXJUb1JvbGwgPSA2IC0gbGVuKGtlZXBlcnNBZnRlck9uZVJvbGwpCgkjIExvb3AgdGhyb3VnaCBhbGwgcG9zc2libGUgc2Vjb25kIHRocm93cwoJZm9yIHJlcm9sbGVkRGljZSBpbiBwcm9kdWN0KGZhY2VzLCByZXBlYXQ9bnVtYmVyVG9Sb2xsKToKCQlkaWNlQWZ0ZXJUd29Sb2xscyA9IHR1cGxlKHNvcnRlZChyZXJvbGxlZERpY2UrdHVwbGUoa2VlcGVyc0FmdGVyT25lUm9sbCkpKQoJCWtlZXBlcnNBZnRlclR3b1JvbGxzID0ga2VlcEZ1bmN0aW9uc1sxXShkaWNlQWZ0ZXJUd29Sb2xscykKCQludW1iZXJUb1JvbGxBZnRlclR3b1JvbGxzID0gNiAtIGxlbihrZWVwZXJzQWZ0ZXJUd29Sb2xscykKCQkjIExvb3AgdGhyb3VnaCBhbGwgcG9zc2libGUgdGhpcmQgdGhyb3dzCgkJZm9yIHJlcmVyb2xsZWREaWNlIGluIHByb2R1Y3QoZmFjZXMsIHJlcGVhdD1udW1iZXJUb1JvbGxBZnRlclR3b1JvbGxzKToKCQkJZGljZUFmdGVyVGhyZWVSb2xscyA9IHR1cGxlKHNvcnRlZChyZXJlcm9sbGVkRGljZSt0dXBsZShrZWVwZXJzQWZ0ZXJUd29Sb2xscykpKQoJCQl0b3RhbCArPSBzY29yZShkaWNlQWZ0ZXJUaHJlZVJvbGxzKQoJCQljb3VudCArPSAxCgoJcHJpbnQgJ1VzaW5nICVzIGV4cGVjdGVkIHNjb3JlIGlzICUwLjJmICglZCB0b3RhbCBwb2ludHMgZnJvbSAlZCBwb3NzaWJsZSBvdXRjb21lcyknJShuYW1lLCAxLjAqdG90YWwvY291bnQsIHRvdGFsLCBjb3VudCkK