I followed the ins and outs of DMD since early 2004 when the "Great Divide" Phobos/Tango debate was still prevalent.
I ❤️ D and mostly Math'n code too!
pe-dlang/
├── pe-common/ # Shared library
│ └── source/euler/
│ ├── common.d # runSolution template
│ ├── math.d # isPrime, sieve, nthPrime, reverseDigits, isPalindrome,
│ │ # largestPrimeFactor, mod, fib, matMul, matVecMul, matPow
│ └── numerics.d # Solver, Method, SolveResult — root-finding
│ # (Newton-Raphson, Brent-Dekker, TOMS 748, ITP)
├── pe-XXXX/ # One DUB package per problem
│ ├── dub.json
│ └── source/app.d
├── build-all.ps1 # Build all solutions in one shot
├── run-all.ps1 # Run all solutions in one shot
└── clean-all.ps1 # Clean all solutions in one shot
Each pe-XXXX/ directory is a self-contained DUB package that depends on pe-common via a local path.
Single solution — run from inside the problem directory:
cd pe-0001
dub run
dub run --build=release # optimisedAll solutions at once — run from the repo root:
.\build-all.ps1 # debug build
.\build-all.ps1 -Release # release build
.\build-all.ps1 -ShowOutput # print dub output for every solutionRun all solutions at once:
.\run-all.ps1 # debug build + run
.\run-all.ps1 -Release # release build + run
.\run-all.ps1 -ShowOutput # also print dub build messages on successClean all solutions at once:
.\clean-all.ps1 # remove build artifacts
.\clean-all.ps1 -ShowOutput # print dub output for every solution| Symbol | Description |
|---|---|
runSolution!(solver, N)() |
Starts a timer, calls solver(), prints the answer and elapsed time |
| Symbol | Description |
|---|---|
isPrime(n) |
Trial division primality test — O(√n), works on any integral type |
sieve(n) |
Sieve of Eratosthenes — returns bool[0..n], O(n log log n) |
nthPrime!T(n) |
Returns the nth prime as type T (default int), sized by Rosser's bound |
reverseDigits(n) |
Reverses the decimal digits of an integer |
isPalindrome(n) |
Returns true if n == reverseDigits(n) |
largestPrimeFactor(n) |
Returns the largest prime factor of n |
mod(a, b) |
True modulo — always non-negative, unlike D's % remainder |
fib!T(n) |
nth Fibonacci number as type T (default BigInt); use fib!long(n) for n ≤ 93 |
matMul(A, B, modulus) |
2×2 matrix multiplication mod modulus |
matVecMul(M, v, modulus) |
2×2 matrix × 2-vector multiplication mod modulus |
matPow(M, n, modulus) |
2×2 matrix power M^n mod modulus; n may be any integral type or BigInt |
| Symbol | Description |
|---|---|
Method |
Enum selecting the algorithm: NewtonRaphson, Brent, Toms748, Itp |
label(m) |
Returns a human-readable name for a Method value |
SolveResult |
Result struct — method (Method), root (double), evals (size_t) |
Solver(method, a, b, func) |
Configures a root-finding solve for f(r) = 0 on [a, b]; func is a double delegate(double) |
Solver.solve() |
Runs the selected algorithm and returns a SolveResult |
Every app.d follows the same pattern:
// Problem title
// https://projecteuler.net/problem=N
import ...;
import euler.math : ...; // math utilities as needed
import euler.numerics : ...; // root-finding as needed
import euler.common : runSolution;
// helper functions if any
auto solve() {
// ...
return answer;
}
void main() { runSolution!(solve, N)(); }runSolution handles the timer and output format:
Project Euler #N
Answer: 12345
Elapsed time: 3 milliseconds.
| # | Title | Approach |
|---|---|---|
| 1 | Multiples of 3 or 5 | Range filter and sum |
| 2 | Even Fibonacci Numbers | Even-only recurrence E(n) = 4·E(n−1) + E(n−2), starting 2, 8 — skips all odd terms |
| 3 | Largest Prime Factor | Trial-division factorisation |
| 4 | Largest Palindrome Product | Cartesian product of 3-digit numbers, palindrome filter |
| 5 | Smallest Multiple | LCM reduction over 1..20 |
| 6 | Sum Square Difference | (Σn)² − Σ(n²) via range pipelines |
| 7 | 10001st Prime | Sieve bounded by Rosser's theorem p_n < n(ln n + ln ln n) |
| 8 | Largest Product in a Series | Sliding 13-digit window, maximise product |
| 9 | Special Pythagorean Triplet | Nested search with a+b+c=1000, a²+b²=c² |
| 10 | Summation of Primes | Trial division filter and sum below 2M |
| 14 | Longest Collatz Sequence | Memoised iterative Collatz chain |
| 15 | Lattice Paths | Combinatorics — C(2n, n) = C(40, 20) |
| 19 | Counting Sundays | Date library — count first-of-month Sundays 1901–2000 |
| 20 | Factorial Digit Sum | BigInt 100!, then digit sum |
| 28 | Number Spiral Diagonals | Closed form: (4n³ + 3n² + 8n − 9) / 6 |
| 31 | Coin Sums | Unbounded knapsack DP |
| 38 | Pandigital Multiples | Search n × 100002; verify 9-digit pandigital |
| 39 | Integer Right Triangles | Closed-form a = p(p−2b) / 2(p−b) eliminates inner loop |
| 40 | Champernowne's Constant | Concatenate integers; index positions 10⁰..10⁶ and multiply |
| 47 | Distinct Primes Factors | Omega sieve counts distinct prime factors; scan for 4 consecutive |
| 48 | Self Powers | BigInt Σ(nⁿ), n=1..1000, mod 10¹⁰ |
| 49 | Prime Permutations | Arithmetic progression step 3330 among digit-permutation primes |
| 50 | Consecutive Prime Sum | Sliding sum of consecutive primes; track longest prime-valued sum |
| 55 | Lychrel Numbers | Reverse-and-add up to 50 times; no palindrome ⇒ Lychrel |
| 56 | Powerful Digit Sum | Maximise digit sum of aᵇ (BigInt) for a, b < 100 |
| 60 | Prime Pair Sets | 5-clique in prime-pair graph: any two concatenate to a prime |
| 63 | Powerful Digit Counts | dⁿ has n digits iff n ≤ ⌊1 / (1 − log₁₀ d)⌋; sum over d = 1..9 |
| 76 | Counting Summations | Partition DP — p(100) − 1 |
| 91 | Right Triangles with Integer Coordinates | Dot-product perpendicularity check on three vertex pairs |
| 97 | Large Non-Mersenne Prime | Modular exponentiation: 28433·2^7830457 + 1 mod 10¹⁰ |
| 206 | Concealed Square | sqrt bounds + alternating-digit pattern check, step 10 |
| 345 | Matrix Sum | Bitmask DP — optimal column assignment over 15×15 matrix |
| 455 | Powers With Trailing Digits | Fixed-point iteration k = nᵏ mod 10⁹ until stable |
| 800 | Hybrid Integers | Log-space: q·log p + p·log q ≤ E·log B; binary search on q |
| 808 | Reversible Prime Squares | Find primes p where both p² and rev(p²) are squares of primes |
| 820 | Nth Digit of Reciprocals | nth digit of 1/k = (10ⁿ mod 10k) / k via modular exponentiation |
| 849 | The Tournament | DP score distribution over 100 rounds, mod 10⁹+7 |
| 940 | Two-Dimensional Recurrence | Matrix exponentiation on two coupled recurrences; sum A(f_i, f_j) over 2 ≤ i, j ≤ 50 with Fibonacci indices |
