Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
First solution in Uncategorized category for Battle Dice by blabaster
from collections import defaultdict, Counter
def battle_probability(dice, x, y):
x_, y_ = x, y
dice = Counter(((s.count('A'), s.count('D')) for s in dice))
rolls = [None, dice]
for i in range(max(x, y) - 1):
dices = Counter()
for (a, d), ad in dice.items():
for (aa, dd), aadd in rolls[-1].items():
dices[a + aa, d + dd] += ad * aadd
rolls.append(dices)
pairs = dict()
for x in range(1, x_ + 1):
for y in range(1, y_ + 1):
dices = Counter()
for (ax, dx), xx in rolls[x].items():
for (ay, dy), yy in rolls[y].items():
x1, y1 = max(min(x, x + dx - ay), 0), max(min(y, y + dy - ax), 0)
if x1 < x or y1 < y:
dices[x1, y1] += xx * yy
scale = sum(dices.values())
pairs[x, y] = [(x1, y1, v / scale) for (x1, y1), v in dices.items()]
nxt, win = {(x_, y_): 1.}, 0.
while nxt:
cur, nxt = nxt, defaultdict(float)
for (x, y), xyprb in cur.items():
for x1, y1, dicesprb in pairs[x, y]:
if x1:
if y1:
nxt[x1, y1] += xyprb * dicesprb
else:
win += xyprb * dicesprb
return win
July 4, 2014