Sunday Times Teaser 3027 – Long Shot
by Andrew Skidmore
Published Sunday September 27 2020 (link)
Callum and Liam play a simple dice game together using standard dice (numbered 1 to 6). A first round merely determines how many dice (up to a maximum of three) each player can use in the second round. The winner is the player with the highest total on their dice in the second round.
In a recent game Callum was able to throw more dice than Liam in the second round but his total still gave Liam a chance to win. If Liam had been able to throw a different number of dice (no more than three), his chance of winning would be a whole number of times greater.
What was Callum’s score in the final round?
4 Comments
Leave one →
-
Brian Gladman permalink12345678910111213141516171819202122232425262728293031323334353637383940from math import gcd# generate three arrays in which s2c[n][s] / 216 is the# probability of a score <s> using <n> dice (n in 1..3)s2c = [[], [0] * 7, [0] * 13, [0] * 19]for a in range(1, 7):s2c[1][a] += 36for b in range(1, 7):s2c[2][a + b] += 6for c in range(1, 7):s2c[3][a + b + c] += 1# return the probability (as string) from chance (x) in 216def prob(x):g = gcd(x, 216)return f"{x // g}/{216 // g}"# the number of dice for Callumfor cd in (2, 3):# consider Callum's scores that give Liam a chance of winningfor cs in range(cd, 6 * (cd - 1)):# consider Liam's results with fewer dice than Callumfor ld in range(1, cd):# find Liam's probability of winningc1 = sum(c for s, c in enumerate(s2c[ld], 0) if s > cs)if c1:# consider Liam's score with more dicefor lm in range(cd, 4):# find Liam's probability of winning this timec2 = sum(c for s, c in enumerate(s2c[lm], 0) if s > cs)# this probability is an integer multiple of the earlier oneif c2 % c1 == 0:print(f"Callam's score {cs} ({cd} dice) => "f"Liam: {ld} dice ({prob(c1)}), {lm} dice ({prob(c2)})")
-
Frits permalink123456789101112131415161718192021222324252627282930313233343536373839404142from itertools import product as prod, accumulatefrom collections import Counter# generate cumulative sum list for n dicedef genList(n):# make dictionary of sum values of n dicea = list(Counter(sum(t) for t in prod(range(1, 7), repeat=n)).values())[1:]# get the cumulative sum of a lista = list(accumulate([1] + a))a.reverse()# add leading and trailing zeroesreturn [0] * n + a[1:] + [0]cumsum = [[]] * 4for i in range(1, 4):cumsum[i] = genList(i)# Assume Liam throws n times and has x possibilities of throwing higher# than Callum.# So Liam's first throw being higher has chance x / 6^n.# If Liam would have been allowed to throw more dice then he would have# had y possibilities of throwing higher than Callum.# His second chance is (y / 6^m ) / (x / 6^n) times greater# which equals y * 6^n / (x * 6^m) = y / (x * 6^(m-n))# so y must be a multiple of 6^(m-n)# Liam threw n dicefor n in range(1, 3):to = (n - 1) * 6 + 7 # upper limit range cumsum[m]# check for Liam throwing more dicefor m in range(n + 1, 4):fr = m + 1 # lower limit range cumsum[m]d = 6 ** (m - n) # divisor, 6 or 36# check for multiple of 6^(m-n)for i, csm in {(a, b) for a, b in enumerate(cumsum[m][fr:to])if b % d == 0}:# Formula: cumsum[m] entry / 6^m = K * cumsum[n] entry / 6^nif csm % (6**(m - n) * cumsum[n][i + fr]) == 0:print(f"Score Callum Final round: {i + fr}")
-
Erling Torkildsen permalink1234567891011121314151617181920212223242526272829303132333435363738394041from itertools import product, accumulate# List possible scores according to number of dice thrownD1 = list(range(1, 7))D2 = list((sum(s) for s in product(D1, D1)))D3 = list((sum(s) for s in product(D1, D1, D1)))# Frequencies for the possible sumsFrq2, Frq3 = list(), list()# Calculate frequencies for beating given 'score' with given# number of dice. Return are scaled to fit common denominator.def P(score, dice):if dice == 1:return aFrq1[score] * len(D2)if dice == 2:return aFrq2[score] * len(D1)if dice == 3:return aFrq3[score]# Accumulate frequencies for possible (and impossible scores)# for each set of diceaFrq1 = [0] * (max(D2) + 1) + D1aFrq1.reverse()for s2 in range(min(D2), max(D2) + 1):Frq2.append(D2.count(s2))aFrq2 = [0] * 7 + list(accumulate(Frq2)) + [len(D2)]aFrq2.reverse()for s3 in range(min(D3), max(D3) + 1):Frq3.append(D3.count(s3))aFrq3 = [0] + list(accumulate(Frq3)) + [len(D3)] * 2aFrq3.reverse()# Look for solution with different number of dicefor sc in range(min(D2), max(D2) + 1):a, b, c = P(sc, 1), P(sc, 2), P(sc, 3)for n in range(2, 21):if (a > 0 and n * a == b or n * a == c) or n * b == c:print(f"Score = {sc}, factor = {n}")
-
John Z permalink1234567891011121314151617181920212223242526272829303132333435# Ways to throw a number with 1, 2, 3 dicetots = [[0 for i in range(19)] for j in range(4)]for i in range(1, 7):tots[1][i] += 1for j in range(1, 7):tots[2][i + j] += 1for k in range(1, 7):tots[3][i + j + k] += 1# consider Callum's scores that give Liam a chance to winfor i in range(2, 12):# consider Callum's number of dicefor c in (2, 3):# consider Liam's number of dice (less than Callum's)for j in range(1, c):if tots[j][i + 1] > 0:# Liam's chances of winning with this number of dices1 = sum(tots[j][i + 1:])# Liam's number of dice when allowed morefor k in range(j + 1, 4):# Liam's chances of winning now, which must be an integer# multiple of the earlier chance when adjusted for the# different number of dice involvedm, r = divmod(sum(tots[k][i + 1:]), s1 * 6 ** (k - j))if r == 0 and m > 1:print(f"Callum rolls {i} with {c} dice, Liam rolls {j} "f"(and then {k}) giving a probability ratio of {m}.")