Teaser 3298: Bletchley Park
From The Sunday Times, 7th December 2025 [link] [link]
Secret agent Robert Holmes was searching the hotel room of a foreign agent who was downstairs having breakfast.
Holmes discovered a piece of paper containing the [following] text:
DKCCVTCSZQRZYTAZXTTX
And he thought this might be a coded message about the foreign agent’s mission, so he sent it to his code-breaking experts.
They discovered that it was a message that had been scrambled by consistently replacing each letter of the alphabet with a different letter (no letter being used to replace more than one different letter). They decoded the message as a sentence containing four words, which they sent back to Holmes with spaces inserted between words. Holmes realised that his life was in imminent danger as soon as he read it.
What was the decoded message?
[teaser3298]














Jim Randell 6:33 am on 7 December 2025 Permalink |
Assuming the foreign agent communicates in English, I had a guess at to what the first two words might be, and this gave me enough letters to fill out a likely candidate for the rest of the message immediately.
Solution: The message can be decoded as: KILL HOLMES BEFORE NOON.
But the clear text could just be the less threatening: CALL HOLMES BEFORE NOON.
Or it could not involve HOLMES at all: PULL MELBA STAGE CAREER.
In fact there are lots of possible clear text substitutions consisting of four English words (although most of them don’t form a coherent sentence).
LikeLike
Frits 8:27 am on 7 December 2025 Permalink |
@Jim, I also found the solution but wonder how to make a general program that also runs in a reasonable time.
LikeLike
Jim Randell 9:59 am on 7 December 2025 Permalink |
The following program assumes that HOLMES appears somewhere in the decoded message. And then tries to split the unused cipher text into three possible words. (Which is how I attacked the puzzle manually).
Using a list of 61871 fairly common English words, the following program finds many possible ways to decipher the text (including the way I found earlier, which still seems to be the most likely candidate solution).
It runs in 5.03s (using PyPy).
from enigma import (irange, group, tuples, translate, readlines, printf) # enciphered text code = "DKCCVTCSZQRZYTAZXTTX" # read words into a dict (indexed by word length) path = "words.txt" with open(path, "r") as fh: words = group(readlines(fh, fn=str.upper, st=str.isalpha), by=len) # consistently update dict <d> mapping keys <ks> to values <vs> def update(d, ks, vs): d = dict(d) for (k, v) in zip(ks, vs): if k == v: return elif k in d: if v != d[k]: return elif v in d.values(): return else: d[k] = v return d # solve cipher text <ws> = [(<n>, <text>), ...] into <n> words # using dict <d> def solve(ws, d): # are we done? if not ws: text = translate(code, d) printf("-> {text}") else: # consider the next chunk of code (k, t) = ws[0] # look for a single word if k == 1: for x in words.get(len(t), []): d1 = update(d, t, x) if d1: solve(ws[1:], d1) elif k > 1: # solve the first word for n in irange(1, len(t) + 1 - k): for x in words.get(n, []): d1 = update(d, t[:n], x) if d1: solve([(k - 1, t[n:])] + ws[1:], d1) # look for a run of 6 different letters to be "HOLMES" for (i, vs) in enumerate(tuples(code, 6)): if len(set(vs)) != 6: continue d = dict(zip(vs, "HOLMES")) # split the text at HOLMES (a, b) = (code[:i], code[i + 6:]) if not a: solve([(3, b)], d) elif not b: solve([(3, a)], d) else: solve([(1, a), (2, b)], d) solve([(2, a), (1, b)], d)You will need to provide a list of candidate words in [[
words.txt]] (or change the definition ofpathto point to such a list).The [[
readlines()]] function is a recent addition to the enigma.py library.LikeLike