Thursday, 5 February 2026

Why Is 313131 An Interesting Number?


Recently a friend of mine who was staying at a hotel revealed that the six digit security code for the room was 313131. This looked like an easy code to crack and I was reminded of a post that I'd made recently titled Passcodes and Repeated Digits in November of 2025. Figure 1 shows the probabilities for the number of distinct digits chosen:


Figure 1

So the code 313131 is indeed easy to crack, requiring only a maximum of 62 attempts or 31 attempts on average. However, what was of most interest to me regarding 313131 was its prime factorisation:$$ 313131=3 \times 7 \times 13 \times 31 \times 37$$If we rearrange the order of multiplication we get the following:$$ 313131=7 \times 3 \times 13 \times 31 \times 37$$Concatenating these digits we get the number \(73133137\) which is palindromic.

Naturally, I wondered how many other numbers share this property and so I set Gemini to investigate this with the following prompt:

Write a program in Python, tailored for insertion into SageMathCell or a Jupyter notebook, that identifies all composite numbers from 4 up to a user chosen upper limit with the property that the prime factors, when arranged in a suitable order and then concatenated, produce a palindromic number. The default upper limit can be set to 40000. An example of such a number would be 313131 = 3 x 7 x 13 x 31 x 37 that can written as 7 x 3 x 13 x 31 x 37 to produce the palindromic number 73133137 when concatenated. The output of the program should be a table showing number and factorisation followed by a comma separated list of the qualifying numbers.

Naturally this a processor intensive process and my Jupyter notebook struggled mightily to generate the list of suitable numbers. After some time, I decided to restrict the range to between 28000 and 29000 and after further modifications by Gemini, I was able to achieve the following list of numbers:

28072, 28125, 28194, 28224, 28242, 28273, 28308, 28322, 28332, 28416, 28431, 28448, 28585, 28589, 28593, 28601, 28602, 28609, 28620, 28672, 28685, 28692, 28750, 28800, 28812, 28847, 28951

Figure 2 shows the details:


Figure 2

I've incorporated this algorithm into my daily search program that has become somewhat impressive if I do say so myself. See Figure 3 for the results of 28067, my diurnal age today.


Figure 3

The output is generated by the same program but I've just restricted the range to my daily number, rather lazy but it does the job. Remember the prime factorisation takes multiplicity into account. For completeness I'll include the Python code:

import sys

def get_prime_factors(n):
    """Returns a list of prime factors of n."""
    factors = []
    d = 2
    temp = n
    while d * d <= temp:
        while temp % d == 0:
            factors.append(d)
            temp //= d
        d += 1
    if temp > 1:
        factors.append(temp)
    return factors

def is_palindrome(s):
    """Checks if a string is a palindrome."""
    return s == s[::-1]

def distinct_permutations(iterable):
    """
    Yields unique permutations of items in iterable.
    This handles repeated elements efficiently (e.g., [2, 2, 3])
    without generating all n! redundant combinations.
    """
    # Sort the list to start with the lexicographically first permutation
    s = sorted(iterable)
    yield tuple(s)
    
    n = len(s)
    while True:
        # 1. Find the largest index i such that s[i] < s[i+1]
        i = n - 2
        while i >= 0 and s[i] >= s[i+1]:
            i -= 1
        
        if i == -1:
            return # All permutations generated
        
        # 2. Find the largest index j such that s[i] < s[j]
        j = n - 1
        while s[j] <= s[i]:
            j -= 1
        
        # 3. Swap s[i] and s[j]
        s[i], s[j] = s[j], s[i]
        
        # 4. Reverse the sequence from s[i+1] up to the end
        s[i+1:] = s[i+1:][::-1]
        
        yield tuple(s)

def find_palindromic_composites(start_n, end_n):
    results = []
    actual_start = max(4, start_n)

    for n in range(actual_start, end_n + 1):
        factors = get_prime_factors(n)
        
        # Skip primes
        if len(factors) < 2:
            continue
            
        found_property = False
        winning_perm = None
        winning_concat = None
        
        # Use the optimized generator instead of itertools.permutations
        for p in distinct_permutations(factors):
            concat_str = "".join(map(str, p))
            
            if is_palindrome(concat_str):
                found_property = True
                winning_perm = p
                winning_concat = concat_str
                break 
        
        if found_property:
            fact_str = " x ".join(map(str, winning_perm))
            results.append((n, fact_str, winning_concat))

    return results

# --- Configuration ---
LOWER_BOUND = 28000
UPPER_BOUND = 29000

# --- Main Execution ---
print(f"Searching for composite numbers between {LOWER_BOUND} and {UPPER_BOUND}...")
print("-" * 80)
print(f"{'Number':<8} | {'Valid Factor Ordering':<35} | {'Resulting Palindrome'}")
print("-" * 80)

qualifying_numbers = find_palindromic_composites(LOWER_BOUND, UPPER_BOUND)

if not qualifying_numbers:
    print(f"No qualifying numbers found in the range {LOWER_BOUND} to {UPPER_BOUND}.")
else:
    for num, factor_str, pal_str in qualifying_numbers:
        print(f"{num:<8} | {factor_str:<35} | {pal_str}")

    print("-" * 80)
    print("\nComma separated list of qualifying numbers:")
    print(", ".join(str(r[0]) for r in qualifying_numbers))

Tuesday, 3 February 2026

Why Is 29 Special?

 This little puzzle appeared in Puzzle A Day.

What is the only number that, when written in typed letters as all capitals, is made up of exactly the same number of straight-line segments as the value of the number itself? For example, FIVE uses 10 straight lines, so it cannot be the answer. (Ignore any hyphens in the spelled-out number.)

I asked Gemini to create a table for the number of straight line segments in each letter of the English alphabet and then solve the puzzle.

Based on a standard analysis of the straight line segments in the uppercase English alphabet (using a typical sans-serif block font), here is the breakdown.

Table of Straight Line Segments per Letter

LetterSegmentsShape Breakdown
A3Two diagonal, one horizontal
B1One vertical (curves do not count)
C0All curved
D1One vertical
E4One vertical, three horizontal
F3One vertical, two horizontal
G1One short horizontal shelf
H3Two vertical, one horizontal
I1One vertical
J0Typically a hook (though some fonts use 1 vertical)
K3One vertical, two diagonal
L2One vertical, one horizontal
M4Two vertical, two diagonal
N3Two vertical, one diagonal
O0All curved
P1One vertical
Q1One short diagonal tail
R2One vertical, one diagonal leg
S0All curved
T2One vertical, one horizontal
U0Typically a curve (block versions may have 2 vertical)
V2Two diagonal
W4Four diagonal
X2Two diagonal
Y3Two diagonal, one vertical (or three meeting at center)
Z3Two horizontal, one diagonal

The Numbers That Match

Using the values from the table above, we can deduce which integers (when written as English words) have a value equal to their total number of straight line segments.

There are exactly two integers that satisfy this condition:

1. SIXTEEN

  • S (0) + I (1) + X (2) + T (2) + E (4) + E (4) + N (3)

  • Calculation: $0 + 1 + 2 + 2 + 4 + 4 + 3 = \mathbf{16}$

  • Result: The word "SIXTEEN" is made of 16 straight lines, which equals its value.

2. TWENTY NINE

  • TWENTY: T (2) + W (4) + E (4) + N (3) + T (2) + Y (3) = 18

  • NINE: N (3) + I (1) + N (3) + E (4) = 11

  • Calculation: $18 + 11 = \mathbf{29}$

  • Result: The words "TWENTY NINE" are made of 29 straight lines, which equals its value.

**************************

In the answer supplied to the puzzle, only 29 is listed and not 16 as well. Why I'm not sure but the letters of 29 are made up ONLY of straight line segments whereas 16 contains the curved letter S.