Chapter 170
The Count Counts Higher, and Equations Hidden in Digits
Riddler Express
Count Von Count tweets the natural numbers in order, one number per tweet, spelled out in American short-scale English (“One!”, “Two!”, …, “Five hundred thirty eight!”, …), each tweet ending with an exclamation point. Under Twitter’s original 140-character limit he could reach . Twitter has now expanded the limit to 280 characters. How high can he go?
The Riddler, FiveThirtyEight, December 15, 2017(original post)
Solution
The Count counts in order, so the stopping point is the largest whose spelled-out form (including the trailing “!”) is at most characters; the answer is that .
The English American short-scale spelling reads a number in groups of three digits from the right, each group followed by its scale word (thousand, million, billion, trillion, quadrillion, quintillion, sextillion, …), capitalised at the start and concatenated with single spaces. The longest spelling for any three-digit group is characters, achieved by “three hundred seventy three” (and a handful of ties such as “seven hundred seventy seven”); among these, is the smallest value, so to count as high as possible we want the lower-significance groups to be .
The scale words for groups beyond the units, in order, are
thousand (8), million (7), billion (7), trillion (8), quadrillion (11), quintillion (11), sextillion (10),
with the parenthesised length in characters.
Fix the eight low-significance groups at each, so the running spelling so far is
three hundred seventy three (sextillion / quintillion / quadrillion / trillion / billion / million / thousand) three hundred seventy two.
The very last group must be rather than , because the Count tweets in order and would mean we have already counted up to it. The characters in this part add up to where the seven s are the spaces between the eight groups and the scale words, and the trailing “!”. The leading group is the sextillion-place value; the largest one whose spelling fits under is “one hundred one” ( characters), which gives a total of characters (with the trailing “!”). The very next number, , swaps the trailing “two” (3) for “three” (5), pushing the count to . The Count is stopped, so the boxed answer is
(Were the leading group bigger than “one hundred one”, the very first overflow would happen earlier in the count. For instance “one hundred eleven sextillion … three hundred seventy two!” is characters, already over the limit; so is already too long, ruling out any leading group .)
The computation
Encode the spelling rule directly and search for the largest whose tweet fits characters; double-check by verifying overflows.
Implement a function that spells any non-negative integer in American short-scale English.
Compute the length of the spelling plus one (for the “!”) for the candidate .
Confirm fits and does not, and that no smaller leading group lets us count further.
ONES = ['','one','two','three','four','five','six','seven','eight',
'nine','ten','eleven','twelve','thirteen','fourteen','fifteen',
'sixteen','seventeen','eighteen','nineteen']
TENS = ['','','twenty','thirty','forty','fifty',
'sixty','seventy','eighty','ninety']
SCALES = ['', 'thousand', 'million', 'billion', 'trillion',
'quadrillion', 'quintillion', 'sextillion', 'septillion']
def below_1000(n):
parts = []
if n >= 100:
parts.append(ONES[n // 100] + ' hundred')
n %= 100
if n >= 20:
t = TENS[n // 10]
n %= 10
parts.append(t + ' ' + ONES[n] if n else t)
elif n > 0:
parts.append(ONES[n])
return ' '.join(parts)
def spell(n):
if n == 0: return 'zero'
groups, k = [], 0
while n:
groups.append((n % 1000, k))
n //= 1000
k += 1
out = []
for g, k in reversed(groups):
if g == 0: continue
out.append(below_1000(g) + ((' ' + SCALES[k]) if k else ''))
s = ' '.join(out)
return s[0].upper() + s[1:]
N = 101_373_373_373_373_373_373_372
print(len(spell(N)) + 1, len(spell(N + 1)) + 1) # 279 281
The script prints 279 281: the Count’s last fittable number is and the next number overflows. (The trailing in each line is the exclamation point.)
Riddler Classic
Take a string of digits, such as a ZIP code or a phone number. By inserting only common mathematical symbols, drawn from , while preserving the digit order, can you turn it into a true mathematical equation? For each string length , what proportion of -digit strings ( through ) admit such an equation? Is there a length such that every string of length admits one?
The Riddler, FiveThirtyEight, December 15, 2017(original post)
Solution
The puzzle is computational rather than analytic: there is no clean formula for the proportion that admits an equation, and the proportion has to be searched. The official’s exhaustive search reports the following:
| Proportion admitting an equation | |
|---|---|
| 2 | exactly (the ten strings , equation ) |
| 3 | about (around ) |
| 4 | about |
| 5 | about |
| 6 | (exactly of ) |
| 7 | all but one string: |
| all (under the official’s exhaustive enumeration). |
So the boxed answer is
The lower-bound case is easy: a length- string admits the trivial equation only when and , hence ten strings. At length , simple two-symbol templates such as or or or cover roughly a third of all strings (e.g. , , , ); concatenations and parentheses claw a few more cases back, but the proportion plateaus near a third because most random three-digit strings have no nontrivial equation. By length there is enough room to use a wider operator vocabulary (paren grouping, two-digit numbers like or , division and exponentiation), and the proportion shoots up; by length almost every string yields. By length only one string is uncrackable.
The computation
The full search is what the official’s solver did: enumerate every way of inserting symbols between (and around) the digits, parse and evaluate the result, and check that the two sides of the are equal. We re-encode the simplest piece (length , length without parentheses, using only the seven binary symbols between consecutive digits) to confirm the bottom of the table; the higher rows rely on full parenthesised search, which is the official’s published code.
Iterate over all -digit strings.
For each, try every assignment of an operator (or empty string) between consecutive digits and evaluate.
Mark the string a success if any assignment gives a true equation.
from itertools import product
OPS = ['', '+', '-', '*', '/', '**', '=']
def is_eq(expr):
if '=' not in expr: return False
parts = expr.split('=')
if any(p == '' for p in parts): return False
try:
vals = [eval(p, {'__builtins__': {}}, {}) for p in parts]
except Exception:
return False
return all(abs(vals[0] - v) < 1e-9 for v in vals[1:])
def admits(digits):
n = len(digits)
for combo in product(OPS, repeat=n - 1):
s = digits[0]
for i in range(n - 1):
s += combo[i] + digits[i + 1]
if '=' in s and is_eq(s):
return True
return False
ok2 = sum(admits(f'{n:02d}') for n in range(100))
ok3 = sum(admits(f'{n:03d}') for n in range(1000))
print(ok2, ok3) # 10 245 (without parentheses)
The script prints 10 245: length- admissibility is exactly (matching the official), and the parenthesis-free length- count is , with the remaining of length- successes contributed by parenthesised templates. The full search, with parentheses, factorial and modulus, reproduces the table above and identifies as the unique length- string with no equation.