Names Scores
Given a text file of over five thousand first names, sort the names into lexicographic (alphabetical) order. Define the alphabetical value of a name as the sum of the positional values of its lette...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Using
For example, when the list is sorted into alphabetical order, COLIN, which is worth \(3 + 15 + 12 + 9 + 14 = 53\), is the \(938\)th name in the list. So, COLIN would obtain a score of \(938 \times 53 = 49714\).
What is the total of all the name scores in the file?
Problem 22: Names Scores
Mathematical Development
Definitions
Definition 1 (Letter Value). For an uppercase Latin letter , define
where returns the ASCII codepoint. This yields .
Definition 2 (Alphabetical Value). For a name over the alphabet , the alphabetical value is
Definition 3 (Name Score). Let be the names in lexicographic order. The name score of is .
Theorems and Proofs
Theorem 1 (Well-Definedness). The total score is uniquely determined by the input set of names.
Proof. The lexicographic order on (finite strings over a totally ordered alphabet ) is a total order: for strings , compare character-by-character at the first differing position, with shorter strings preceding longer ones if one is a prefix of the other. Since the input names are distinct (an assumption from the problem data), the sorted sequence is unique. Each depends only on the string , and the index depends only on the sorted order. Therefore is uniquely determined.
Lemma 1 (Bounds on ). For any name of length with characters in ,
Proof. Each character contributes at least and at most to the sum. The bounds follow by summing over all characters.
Lemma 2 (ASCII and Dictionary Order). Lexicographic comparison of ASCII-encoded uppercase Latin strings coincides with standard dictionary order.
Proof. The ASCII codes of are , which is a strictly increasing sequence. Lexicographic order is defined by the order on individual characters, so ASCII byte comparison produces the same total order as alphabetical comparison.
Editorial
We read the quoted names, sort them lexicographically, and then evaluate each name score in sorted order. For position , we compute the alphabetical value of the name by summing its letter values and multiply by before adding to the running total. This is sufficient because the problem definition depends only on the sorted order and those per-name letter sums.
Pseudocode
Algorithm: Total of Name Scores
Require: A finite list of quoted names.
Ensure: The sum of all name scores after lexicographic sorting.
1: Read the names, remove quotation marks, and sort the resulting list lexicographically.
2: Initialize total ← 0.
3: For each position j and corresponding name w in the sorted list, compute value(w) ← sum of the letter positions in w.
4: Update total ← total + j · value(w).
5: Return total.
Complexity Analysis
Proposition. The algorithm runs in time and space, where is the number of names and is the maximum name length.
Proof. Sorting strings by comparison-based sort requires comparisons, each costing character inspections in the worst case, for a total of . The subsequent linear scan computes for each name in time, contributing total, which is dominated by the sorting step. Storage for all names of length at most requires space.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
int main() {
ifstream fin("names.txt");
if (!fin.is_open()) {
cerr << "Error: names.txt not found." << endl;
return 1;
}
string content((istreambuf_iterator<char>(fin)), istreambuf_iterator<char>());
fin.close();
vector<string> names;
string cur;
bool in_quote = false;
for (char c : content) {
if (c == '"') {
in_quote = !in_quote;
if (!in_quote && !cur.empty()) {
names.push_back(cur);
cur.clear();
}
} else if (in_quote) {
cur += c;
}
}
sort(names.begin(), names.end());
long long total = 0;
for (int i = 0; i < (int)names.size(); i++) {
int alpha = 0;
for (char c : names[i])
alpha += c - 'A' + 1;
total += (long long)(i + 1) * alpha;
}
cout << total << endl;
return 0;
}
import os
def solve():
script_dir = os.path.dirname(os.path.abspath(__file__))
filepath = os.path.join(script_dir, 'names.txt')
if not os.path.exists(filepath):
filepath = 'names.txt'
if not os.path.exists(filepath):
try:
import urllib.request
url = "https://projecteuler.net/resources/documents/0022_names.txt"
urllib.request.urlretrieve(url, filepath)
except Exception:
print("Error: names.txt not found.")
return
with open(filepath, 'r') as f:
content = f.read()
names = sorted(name.strip('"') for name in content.strip().split(','))
total = sum((i + 1) * sum(ord(c) - 64 for c in name) for i, name in enumerate(names))
print(total)