All Euler problems
Project Euler

Coded Triangle Numbers

The n -th triangle number is T_n = (n(n+1))/(2). By converting each letter in a word to its alphabetical position (A=1, B=2,..., Z=26) and summing, we obtain a word value. A word is a triangle word...

Source sync Apr 19, 2026
Problem #0042
Level Level 01
Solved By 81,967
Languages C++, Python
Answer 162
Length 363 words
geometrybrute_forcearithmetic

Problem Statement

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

The \(n^{th}\) term of the sequence of triangle numbers is given by, \(t_n = \frac 12n(n+1)\); so the first ten triangle numbers are: \[1, 3, 6, 10, 15, 21, 28, 36, 45, 55, \dots \] By converting each letter in a word to a number corresponding to its alphabetical position and adding these values we form a word value. For example, the word value for SKY is \(19 + 11 + 25 = 55 = t_{10}\). If the word value is a triangle number then we shall call the word a triangle word.

Using words.txt (right click and ’Save Link/Target As...’), a 16K text file containing nearly two-thousand common English words, how many are triangle words?

Problem 42: Coded Triangle Numbers

Mathematical Development

Definitions

Definition 1. The alphabetical value of a letter c{A,,Z}c \in \{\text{A}, \ldots, \text{Z}\} is pos(c)=ord(c)ord(A)+1{1,2,,26}\operatorname{pos}(c) = \operatorname{ord}(c) - \operatorname{ord}(\text{A}) + 1 \in \{1, 2, \ldots, 26\}.

Definition 2. The word value of a word w=c1c2cLw = c_1 c_2 \cdots c_L is V(w)=i=1Lpos(ci)V(w) = \sum_{i=1}^{L} \operatorname{pos}(c_i).

Definition 3. A positive integer vv is a triangular number if v=Tn=n(n+1)2v = T_n = \frac{n(n+1)}{2} for some nZ+n \in \mathbb{Z}^+.

Theoretical Development

Theorem 1 (Triangular number characterization). A positive integer vv is triangular if and only if 8v+18v + 1 is a perfect square.

Proof. (\Rightarrow) Suppose v=n(n+1)2v = \frac{n(n+1)}{2} for some nZ+n \in \mathbb{Z}^+. Then

8v+1=4n(n+1)+1=4n2+4n+1=(2n+1)2,8v + 1 = 4n(n+1) + 1 = 4n^2 + 4n + 1 = (2n+1)^2,

which is a perfect square.

(\Leftarrow) Suppose 8v+1=m28v + 1 = m^2 for some mZ+m \in \mathbb{Z}^+. Since 8v+11(mod8)8v + 1 \equiv 1 \pmod{8} and even squares satisfy m20m^2 \equiv 0 or 4(mod8)4 \pmod{8}, we conclude mm is odd. Write m=2n+1m = 2n + 1 for some nZ0n \in \mathbb{Z}_{\geq 0}. Then

8v+1=(2n+1)2=4n2+4n+1    v=n(n+1)2=Tn.8v + 1 = (2n+1)^2 = 4n^2 + 4n + 1 \implies v = \frac{n(n+1)}{2} = T_n.

Since v1v \geq 1, we have n1n \geq 1, confirming vv is triangular. \square

Corollary 1 (Constant-time test). The triangular number test requires O(1)O(1) arithmetic operations: compute Δ=8v+1\Delta = 8v + 1, take the integer square root s=Δs = \lfloor \sqrt{\Delta} \rfloor, and verify s2=Δs^2 = \Delta.

Proof. Immediate from Theorem 1. The integer square root and one multiplication-comparison suffice. \square

Lemma 1 (Word value bounds). For a non-empty word of length LL, the word value satisfies LV(w)26LL \leq V(w) \leq 26L.

Proof. Each letter contributes at least pos(A)=1\operatorname{pos}(\text{A}) = 1 and at most pos(Z)=26\operatorname{pos}(\text{Z}) = 26. Summing over LL letters gives LV(w)26LL \leq V(w) \leq 26L. \square

Remark. For the Project Euler word list, the maximum word length is 1414 (e.g., “SIMULTANEOUSLY”), giving V(w)2614=364V(w) \leq 26 \cdot 14 = 364. The largest triangle number not exceeding 364364 is T26=351T_{26} = 351, so we need only consider triangle numbers T1,T2,,T26T_1, T_2, \ldots, T_{26}.

Editorial

We read the word list, compute the value of each word by summing the alphabetical positions of its letters, and test the resulting integer with the triangular-number criterion from Theorem 1. Every word whose value satisfies that criterion contributes one to the running count, and the final count is the number of triangle words in the file.

Pseudocode

Algorithm: Counting Triangle Words
Require: A finite word list over the alphabet {A, B, ..., Z}.
Ensure: The number of words whose alphabetical values are triangular numbers.
1: Read the word list and initialize count ← 0.
2: For each word w in the list, compute its word value v ← sum of the letter positions in w.
3: Test whether 8v + 1 is a perfect square.
4: If the test succeeds, increment count.
5: Return count.

Complexity Analysis

Proposition (Time complexity). The algorithm runs in O(WLˉ)O(W \cdot \bar{L}) time, where WW is the number of words and Lˉ\bar{L} is the average word length.

Proof. For each of the WW words, computing the word value requires summing LiL_i letter values, where LiL_i is the length of the ii-th word. The triangular number test is O(1)O(1) by Corollary 1. Total time:

i=1WO(Li)=O ⁣(i=1WLi)=O(WLˉ).\sum_{i=1}^{W} O(L_i) = O\!\left(\sum_{i=1}^{W} L_i\right) = O(W \cdot \bar{L}).

\square

Proposition (Space complexity). The algorithm uses O(WLˉ)O(W \cdot \bar{L}) space for storing the word list, plus O(1)O(1) auxiliary space.

Answer

162\boxed{162}

Code

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

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

bool is_triangular(int v) {
    // v is triangular iff 8v+1 is a perfect square (Theorem 1).
    if (v <= 0) return v == 0;
    long long disc = 1 + 8LL * v;
    long long s = (long long)sqrt((double)disc);
    while (s * s < disc) s++;
    while (s * s > disc) s--;
    return s * s == disc;
}

int word_value(const string& w) {
    int val = 0;
    for (char c : w) {
        if (c >= 'A' && c <= 'Z') val += c - 'A' + 1;
    }
    return val;
}

int main() {
    vector<string> candidates = {
        "words.txt",
        "0042_words.txt",
        "project_euler/problem_042/words.txt",
        "project_euler/problem_042/0042_words.txt"
    };

    ifstream fin;
    for (const auto& path : candidates) {
        fin.open(path);
        if (fin.is_open()) {
            break;
        }
        fin.clear();
    }

    if (!fin.is_open()) {
        cerr << "Could not locate the Problem 42 word list." << endl;
        return 1;
    }

    string line;
    getline(fin, line);
    fin.close();

    int count = 0;
    stringstream ss(line);
    string token;
    while (getline(ss, token, ',')) {
        string word;
        for (char c : token) {
            if (c != '"') word += c;
        }
        if (is_triangular(word_value(word))) {
            count++;
        }
    }

    cout << count << endl;
    return 0;
}