Skip to content
Vamshi Jandhyala

Books · The Riddler

Chapter 159

Can You Unravel These Number Strings?

Riddler Express

Six numbers are given in sequence: 1, 11, 21, 1211, 111221, 3122111,\ 11,\ 21,\ 1211,\ 111221,\ 312211. What is the next number?

The Riddler, FiveThirtyEight, August 18, 2017(original post)

Solution

This is the look-and-say sequence: each term describes its predecessor digit by digit, by reading aloud the consecutive runs as “kk copies of dd”.

Apply the rule to the sixth term: 312211    one 313one 111two 2s22two 1s21  =  13112221.312211 \;\longrightarrow\; \underbrace{\text{one $3$}}_{13}\, \underbrace{\text{one $1$}}_{11}\, \underbrace{\text{two $2$s}}_{22}\, \underbrace{\text{two $1$s}}_{21} \;=\; 13112221.

13112221.\boxed{\,13112221.\,}

A standing fact about this sequence (due to John Conway): consecutive terms grow by a constant factor in the limit, namely Conway’s constant λ1.3036\lambda \approx 1.3036, the only positive real root of a degree-7171 polynomial. The sequence never contains a digit other than 11, 22, or 33 once those are the only digits that appear (Conway’s “cosmological theorem”), so the look-and-say can never trigger itself into using a 44 or larger.

The computation

Encode the look-and-say rule directly: walk the string, count each run, emit “count digit” pairs. Apply seven times from the seed 11 and check the seventh iterate.

  1. Start with the string “11”.

  2. To advance: scan the current string left to right, finding maximal runs of equal digits.

  3. For each run of kk copies of digit dd, emit the two-digit pair kdkd.

  4. Iterate.

def look_and_say(s):
    out = []
    i = 0
    while i < len(s):
        j = i
        while j < len(s) and s[j] == s[i]:
            j += 1
        out.append(str(j - i))
        out.append(s[i])
        i = j
    return "".join(out)

s = "1"
for _ in range(6):
    s = look_and_say(s)
print(s)                                         # 13112221
# match against the six given terms plus our answer
seq = ["1"]
for _ in range(6):
    seq.append(look_and_say(seq[-1]))
print(seq)
# ['1', '11', '21', '1211', '111221', '312211', '13112221']

The seventh iterate is 1311222113112221, agreeing with the boxed answer.

Riddler Classic

Take the self-referential string 333 2 333 2 333 2 33 2 333 2 333 2 333 2 33 2 ,333\ 2\ 333\ 2\ 333\ 2\ 33\ 2\ 333\ 2\ 333\ 2\ 333\ 2\ 33\ 2\ \ldots, where each digit (ignoring spaces) gives the count of consecutive 33s before the next 22. The first digit, 33, says there are three 33s before the first 22; the second digit, 33, says there are three 33s between the first and second 22s; and so on. What is the limiting ratio of 33s to 22s in the infinite string?

The Riddler, FiveThirtyEight, August 18, 2017(original post)

Solution

Define a recursive construction. Generation 11 is the single digit “33”. Generation n+1n + 1 is obtained from generation nn by replacing each digit using the rule it imposes on the string: a 33 in generation nn says “three 33s follow before a 22”, so it expands to the block 3332\textbf{3332}; a 22 in generation nn says “two 33s before a 22”, so it expands to 332\textbf{332}. Each expansion contributes one 22 (the terminating one), and either three or two 33s.

Let TnT_n and WnW_n denote the count of 33s and 22s in generation nn. The expansion rule gives the linear recursion Tn+1=3Tn+2Wn,Wn+1=Tn+Wn.\begin{aligned} T_{n+1} &= 3\,T_n + 2\,W_n, \\ W_{n+1} &= T_n + W_n. \end{aligned} Each generation nn digit produces exactly one 22 in the next generation (the explicit terminator of its block), giving the WW recursion; and a 33 contributes three 33s while a 22 contributes two, giving the TT recursion.

Let rn=Tn/Wnr_n = T_n / W_n. Dividing the two recursions, rn+1=3Tn+2WnTn+Wn=3rn+2rn+1.r_{n+1} = \frac{3 T_n + 2 W_n}{T_n + W_n} = \frac{3 r_n + 2}{r_n + 1}. This is a Möbius (linear-fractional) iteration. Its fixed points satisfy r=(3r+2)/(r+1)r = (3r + 2)/(r + 1), that is r2+r=3r+2r^2 + r = 3r + 2, i.e., r22r2=0r^2 - 2r - 2 = 0. The positive root is r=1+32.7321.r = 1 + \sqrt{3} \approx 2.7321. The other root 13<01 - \sqrt{3} < 0 is irrelevant since counts are positive. The map f(r)=(3r+2)/(r+1)f(r) = (3r + 2)/(r + 1) has derivative f(r)=1/(r+1)2f'(r) = 1/(r + 1)^2; at the positive fixed point r=1+3r = 1 + \sqrt{3} this is 1/(2+3)20.0721/(2 + \sqrt{3})^2 \approx 0.072, which is less than 11 in absolute value, so the fixed point is an attractor and rn1+3r_n \to 1 + \sqrt{3} from any positive start.

The infinite string is the limit of these generations (each generation is a strict prefix of the next), so the overall ratio of 33s to 22s is r=1+32.7321.\boxed{\,r = 1 + \sqrt{3} \approx 2.7321.\,}

The computation

Iterate the actual substitution rule on strings: start with “33”, and at each step replace every 33 by 33323332 and every 22 by 332332. Confirm that the empirical ratio Tn/WnT_n / W_n converges to 1+31 + \sqrt{3}.

  1. Seed with the single character “33”.

  2. At each step, build the next-generation string by concatenating 33323332 for each 33 and 332332 for each 22.

  3. Track counts of 33s and 22s and form the ratio.

import math
s = "3"
for n in range(1, 12):
    s = "".join("3332" if c == "3" else "332" for c in s)
    t, w = s.count("3"), s.count("2")
    print(n + 1, t, w, round(t / w, 6))
# generation 12 ratio prints ~2.732050
print("target:", 1 + math.sqrt(3))               # 2.732050807568877

By generation 1212 the empirical Tn/WnT_n / W_n matches 1+31 + \sqrt{3} to six decimals.