Teaser 3342: One dart wonder
From The Sunday Times, 11th October 2026 [link] [link]
Andy and Beth play a game of darts in which each turn consists of a single dart. They use a standard dartboard where you can score any number from 1 to 20, as well as double or treble that number. Scores of 25 and 50 are also possible. Each single-dart score (SDS) will count only if it does not repeat a previous score by either player and if it has no digit in common with the opponent’s preceding SDS. Every turn, other than the final one, must attempt the highest available valid SDS. Each player must start with a double other than a bullseye (50), and the winner must finish with a double.
In a game where the first to reach a total of 501 wins, Andy started and both players achieved the required SDS on each turn.
Who won, and what was the loser’s total at that point?
[teaser3342]








Jim Randell 7:00 am on 11 October 2026 Permalink |
Each throw in the game is completely determined (it is either the winning double, or the maximum permissible score), so we do not need explore multiple branches in the game tree. All we need to do is follow the instructions, and produce the sequence of scores for each player.
I have assumed that players must finish with an exact score (and cannot exceed their remaining total), with a dart in the double ring (so 50 does not count as a double, as specified in the puzzle text). And no-one ever misses the board (scores 0). Although we can relax these conditions to allow for other reasonable interpretations of the puzzle text, and still find the same answer. The code also catches a couple of conditions where the game cannot be completed (although these do not occur with the target value specified in the puzzle text).
This Python program runs in 67ms. (Internal runtime is 476ยตs).
from enigma import (irange, union, nsplit, empty, diff, fail, printf) # possible scores, by category and collected together singles = set(irange(1, 20)) doubles = set(2 * x for x in singles) triples = set(3 * x for x in singles) bull = { 25, 50 } scores = union([singles, doubles, triples, bull]) # could also add {0} # record digits for each possible score digits = dict((x, set(nsplit(x))) for x in scores) # play the game with players 0 and 1 rem = [501, 501] # remaining totals seq = [[], []] # scores so far i = 0 # index of first player win = 0 # winning throw? while True: other = 1 - i # index of opponent # first go for each player must be a double poss = (scores if seq[i] else doubles) # digits to avoid ds = (digits[seq[other][-1]] if seq[other] else empty) # find possible scores (unplayed, in range, and with no digits in common with opponents last score) r = rem[i] ss = set(x for x in diff(poss, *seq) if x <= r and ds.isdisjoint(digits[x])) fail(not ss, "player cannot play") if not ss: break # invalid game # can we finish? final throw must also be a double if r in ss and r in doubles: x = r win = 1 else: # play the max possible score x = max(ss) # play the score rem[i] -= x seq[i].append(x) # are we done? if win: break fail(rem[i] < 2, "player cannot finish") # next player i = other # output solution if win: printf("player {n} wins:", n="AB"[i]) printf("-> A: {seq} = {t}", seq=seq[0], t=sum(seq[0])) printf("-> B: {seq} = {t}", seq=seq[1], t=sum(seq[1]))Solution: [To Be Revealed]
LikeLike
Ruud van der Ham 5:58 pm on 11 October 2026 Permalink |
turns = dict(A=[], B=[]) scores = {*range(1, 21), *range(2, 41, 2), *range(3, 61, 3), 25, 50} doubles = {*range(2, 41, 2)} last_sds = "" player = "A" done = False while True: for score in sorted(scores, reverse=True): if sum(turns[player]) + score == 501: turns[player].append(score) print("winner= ", player) for player in "AB": print(player, turns[player], "total=", sum(turns[player])) done = True if done: break for score in sorted(scores, reverse=True): if turns[player] or score in doubles and not (set(str(score)) & set(str(last_sds))): scores.remove(score) last_sds = str(score) break turns[player].append(score) player = "A" if player == "B" else "B"LikeLike
Jim Randell 9:27 pm on 11 October 2026 Permalink |
@Ruud: Consecutive scores are not allowed to share digits, so you can’t have a sequence of scores with [57, 54, 51, 50] in the middle.
LikeLike
Ruud van der Ham 9:49 pm on 11 October 2026 Permalink |
@Jim
You are right. Thanks.
This version works as expected:
turns = dict(A=[], B=[]) scores = {*range(1, 21), *range(2, 41, 2), *range(3, 61, 3), 25, 50} doubles = {*range(2, 41, 2)} last_sds = "" player = "A" done = False while True: for score in sorted(scores, reverse=True): if sum(turns[player]) + score == 501: turns[player].append(score) print("winner= ", player) for player in "AB": print(player, turns[player], "total=", sum(turns[player])) done = True if done: break for score in sorted(scores, reverse=True): if (turns[player] or score in doubles) and not (set(str(score)) & set(str(last_sds))): scores.remove(score) last_sds = str(score) break turns[player].append(score) player = "A" if player == "B" else "B"LikeLike