All Euler problems
Project Euler

Truncatable Primes

Find the sum of the only eleven primes that are both truncatable from left to right and right to left. Single-digit primes (2, 3, 5, 7) are excluded.

Source sync Apr 19, 2026
Problem #0037
Level Level 01
Solved By 81,569
Languages C++, Python
Answer 748317
Length 431 words
number_theorymodular_arithmeticbrute_force

Problem Statement

This archive keeps the full statement, math, and original media on the page.

The number \(3797\) has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: \(3797\), \(797\), \(97\), and \(7\). Similarly we can work from right to left: \(3797\), \(379\), \(37\), and \(3\).

Find the sum of the only eleven primes that are both truncatable from left to right and right to left.

NOTE: \(2\), \(3\), \(5\), and \(7\) are not considered to be truncatable primes.

Problem 37: Truncatable Primes

Mathematical Development

Definitions

Definition 1. Let pp be a prime with decimal representation d1d2dkd_1 d_2 \cdots d_k where k2k \ge 2. Define:

  • Ri(p)=d1d2diR_i(p) = \overline{d_1 d_2 \cdots d_i} for 1ik1 \le i \le k (right-truncations).
  • Li(p)=didi+1dkL_i(p) = \overline{d_i d_{i+1} \cdots d_k} for 1ik1 \le i \le k (left-truncations).

Definition 2. A prime pp with k2k \ge 2 digits is right-truncatable if Ri(p)R_i(p) is prime for every 1ik1 \le i \le k. It is left-truncatable if Li(p)L_i(p) is prime for every 1ik1 \le i \le k. It is (two-sided) truncatable if it is both.

Theoretical Development

Theorem 1 (Digit constraints). Let p=d1d2dkp = d_1 d_2 \cdots d_k be a truncatable prime with k2k \ge 2. Then:

  1. d1{2,3,5,7}d_1 \in \{2, 3, 5, 7\}.
  2. dk{3,7}d_k \in \{3, 7\}.
  3. di{1,3,7,9}d_i \in \{1, 3, 7, 9\} for all 2ik12 \le i \le k-1.

Proof.

(1) The right-truncation R1(p)=d1R_1(p) = d_1 must be prime, so d1{2,3,5,7}d_1 \in \{2, 3, 5, 7\}.

(2) The left-truncation Lk(p)=dkL_k(p) = d_k must be prime, so dk{2,3,5,7}d_k \in \{2, 3, 5, 7\}. Suppose dk=2d_k = 2. Then pp is even and p10p \ge 10 (since k2k \ge 2), hence pp is composite — contradiction. Similarly, dk=5d_k = 5 implies 5p5 \mid p with p>5p > 5, contradiction. Therefore dk{3,7}d_k \in \{3, 7\}.

(3) For 2ik12 \le i \le k-1, the right-truncation Ri(p)=d1diR_i(p) = \overline{d_1 \cdots d_i} is a prime with i2i \ge 2 digits. The units digit of Ri(p)R_i(p) is did_i. A multi-digit prime cannot end in {0,2,4,5,6,8}\{0, 2, 4, 5, 6, 8\} (it would be divisible by 2 or 5). Hence di{1,3,7,9}d_i \in \{1, 3, 7, 9\}. \blacksquare

Theorem 2 (Finiteness of right-truncatable primes). The set of right-truncatable primes is finite. In particular, R=83|\mathcal{R}| = 83.

Proof. Right-truncatable primes are constructed by a tree-growth process: the roots are {2,3,5,7}\{2, 3, 5, 7\}, and each node pp spawns children {10p+d:d{1,3,7,9},  10p+d is prime}\{10p + d : d \in \{1, 3, 7, 9\},\; 10p + d \text{ is prime}\}. Each level has branching factor at most 4. By the prime number theorem, π(x)x/lnx\pi(x) \sim x / \ln x, so the density of primes among kk-digit numbers is O(1/k)O(1/k). For sufficiently large kk, no extensions remain prime, and every branch terminates. Complete enumeration yields exactly 83 right-truncatable primes, the largest being 73,939,13373{,}939{,}133. \blacksquare

Corollary 2.1. The set of truncatable primes is finite, since every truncatable prime is right-truncatable.

Theorem 3 (Complete classification). There are exactly 11 truncatable primes:

T={23,37,53,73,313,317,373,797,3137,3797,739397}.\mathcal{T} = \{23,\, 37,\, 53,\, 73,\, 313,\, 317,\, 373,\, 797,\, 3137,\, 3797,\, 739397\}.

Proof. By Theorem 2, all truncatable primes lie within the 83 right-truncatable primes. Testing each for left-truncatability (Definition 2) yields exactly the 11 elements of T\mathcal{T}. Alternatively, a sieve-based exhaustive search over all primes below 10610^6 (which suffices since 739397<106739397 < 10^6) confirms the same set. \blacksquare

Lemma 1 (Verification example). p=3797p = 3797 is truncatable.

Proof. Right-truncations: 37973793733797 \to 379 \to 37 \to 3, all prime. Left-truncations: 37977979773797 \to 797 \to 97 \to 7, all prime. \blacksquare

Editorial

We precompute all primes below a search bound with the Sieve of Eratosthenes, then scan the primes from 11 upward. For each prime, we test every right truncation and every left truncation against the sieve table; if both families remain prime, the number is truncatable and contributes to the running sum. The search stops once the known total of eleven truncatable primes has been found.

Pseudocode

Algorithm: Sum of Left- and Right-truncatable Primes
Require: A prime search bound large enough to contain all 11 truncatable primes.
Ensure: The sum of the eleven primes that remain prime under every left and right truncation.
1: Build a sieve and prime lookup table on the search range.
2: Initialize found ← 0 and total ← 0.
3: For each prime p ≥ 11 in increasing order, generate all left truncations and all right truncations of p.
4: If every truncation is prime, update found ← found + 1 and total ← total + p.
5: When found = 11, return total.

Complexity Analysis

Proposition. The algorithm runs in O(NloglogN+π(N)log10N)O(N \log \log N + \pi(N) \cdot \log_{10} N) time and O(N)O(N) space.

Proof. The Sieve of Eratosthenes computes all primes below NN in O(NloglogN)O(N \log \log N) time and O(N)O(N) space. For each of the π(N)\pi(N) primes (where π(106)=78,498\pi(10^6) = 78{,}498), both truncation checks iterate over at most log10N+17\lfloor \log_{10} N \rfloor + 1 \le 7 truncations, each requiring O(1)O(1) arithmetic and an O(1)O(1) primality lookup. Total post-sieve work: O(π(N)log10N)=O(78,4987)5.5×105O(\pi(N) \cdot \log_{10} N) = O(78{,}498 \cdot 7) \approx 5.5 \times 10^5. The sieve dominates: O(NloglogN)O(N \log \log N). \blacksquare

Answer

748317\boxed{748317}

Code

Each problem page includes the exact C++ and Python source files from the local archive.

C++ project_euler/problem_037/solution.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    const int LIMIT = 1000000;
    vector<bool> is_prime(LIMIT, true);
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i * i < LIMIT; i++)
        if (is_prime[i])
            for (int j = i * i; j < LIMIT; j += i)
                is_prime[j] = false;

    auto isRightTruncatable = [&](int n) -> bool {
        while (n >= 10) {
            n /= 10;
            if (n >= LIMIT || !is_prime[n]) return false;
        }
        return is_prime[n];
    };

    auto isLeftTruncatable = [&](int n) -> bool {
        int pow = 10;
        while (pow < n) {
            if (!is_prime[n % pow]) return false;
            pow *= 10;
        }
        return true;
    };

    int count = 0;
    long long total = 0;
    for (int i = 11; i < LIMIT && count < 11; i++) {
        if (!is_prime[i]) continue;
        if (isRightTruncatable(i) && isLeftTruncatable(i)) {
            total += i;
            count++;
        }
    }

    cout << total << endl;
    return 0;
}