Study Guide: Project Euler
Solutions
#1
Various solutions, all running in under one second:
RPL+
≪ 0 =sum
1 999 FOR i
i 3 mod 0 ==
i 5 mod 0 ==
or
IF THEN i =+sum END
NEXT
sum
≫
or (RPL+ alt)
≪ 1000 3 5 → n a b ≪
--n
a b lcm =c
n n a mod - =na
n n b mod - =nb
n n c mod - =nc
'(na*((na/a)+1) + nb*((nb/b)+1) - nc*((nc/c)+1) )/2' EVAL
≫≫
or (closed-form, classic RPL)
≪ 1000 → n '((n-1)*(((n-1)/3)+1)+(n-5)*(((n-5)/5)+1)-(n-10)*(((n-10)/15)+1))/2' ≫
or (classic RPL)
≪ 0. 1. 999.
FOR I
IF I 3. MOD 0. ==
THEN I +
ELSE
IF I 5. MOD 0. ==
THEN I +
END
END
NEXT
≫
or (JavaScript; fastest)
function () { /*as is*/
var sum = 0;
for (var i = 0; i<1000; i++)
if (i%3 === 0 || i%5 === 0)
sum += i;
return sum;
}
#2
≪ 0 =sum
1 1
DO
DUP ROT + =:val
IF val isEven THEN val =+sum END
UNTIL
val>4e6
END
DROP DROP
sum
≫
#3
≪ 600851475143 factors head ≫
or (GolfScript/MorphEngine)
600851475143factors head
#4
≪ -1 =r @ palindrome result
999 11 / floor 11 * =i
WHILE
i 100 >
i 999 * r > @ potential for bigger r?
and
REPEAT
100 999 FOR j
i j * →STR =s
1 =a s size =b
DO s[a] s[b] ++a --b
UNTIL ≠ =:cmp a b ≥ OR
END
IF cmp NOT THEN r i j * max =r END
NEXT
i 11 - =i
END
r
≫
[ND1: 4s; CalcPad/Mac: 0.6s]
#5
≪ 1..20 vlcm ≫
or (using range)
≪ 1 20 range vlcm ≫
or (using fold operator)
≪ 1 20 range [lcm] fold ≫
or (using classic RPL commands)
≪ 1 20 range ≪ LCM ≫ STREAM ≫
or (GolfScript/MorphEngine)
21,tail{lcm}*
#6
≪ 1..100 =v
v total squared
v squared total
-
≫
or (using classic RPL commands)
≪ 1 100 range =v
v ≪ + ≫ STREAM SQ
v SQ ≪ + ≫ STREAM
-
≫
or (GolfScript/MorphEngine)
101,tail.{+}*SQSQ{+}*-
#7
≪ 1.1e5 primes 10001 at ≫
[ND1: 1.9s; CalcPad/Mac: 0.1s]
or (a bit slower)
≪ 2 1 10000 START NEXTPRIME NEXT≫
[ND1: 2.5s; CalcPad/Mac: 0.2s]
or (GolfScript/MorphEngine)
2{NEXTPRIME}10000*
#8
≪ #8_data fromString split
5 ≪ * * * * ≫ DOSUBS
vmax
≫
[ND1: 1.2s; CalcPad/Mac: 0.08s]
or (GolfScript/MorphEngine)
→{2{max}DOSUBS+}1-*
#8_data
"7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
#9
function () { /*as is*/
for (var a=1;a<500;a++)
for (var b=1;b<500;b++)
if (a*a+b*b == (1000-a-b)*(1000-a-b))
return a*b*(1000-a-b);
}
#10
≪ 2e6 primes total ≫
[ND1: 41s; CalcPad/Mac: 2.6s]
or
≪ 2e6 primes { + } STREAM ≫
[ND1: 55s; CalcPad/Mac: 3.5s]
or (JavaScript)
function () {
var sum = 0, p = primes(2e6);
for (var i=p.length-1; i>=0; i--)
sum += p[i];
return sum;
}
[ND1: 43s; CalcPad/Mac: 2.6s]
or (GolfScript/MorphEngine)
2000000primes{+}*
#11
≪ #11_data =m
0 @ max product kept on stack
m
m transpose concat
m diagonals concat
m flip diagonals concat
1
≪ 4 [ * * * MAX ] DOSUBS ≫
DOSUBS
≫
#11_data
[[8,2,22,97,38,15,0,40,0,75,4,5,7,78,52,12,50,77,91,8],[49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,4,56,62,0],[81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,3,49,13,36,65],[52,70,95,23,4,60,11,42,69,24,68,56,1,32,56,71,37,2,36,91],[22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80],[24,47,32,60,99,3,45,2,44,75,33,53,78,36,84,20,35,17,12,50],[32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70],[67,26,20,68,2,62,12,20,95,63,94,39,63,8,40,91,66,49,94,21],[24,55,58,5,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72],[21,36,23,9,75,0,76,44,20,45,35,14,0,61,33,97,34,31,33,95],[78,17,53,28,22,75,31,67,15,94,3,80,4,62,16,14,9,53,56,92],[16,39,5,42,96,35,31,47,55,58,88,24,0,17,54,24,36,29,85,57],[86,56,0,48,35,71,89,7,5,44,44,37,44,60,21,58,51,54,17,58],[19,80,81,68,5,94,47,69,28,73,92,13,86,52,17,77,4,89,55,40],[4,52,8,83,97,35,99,16,7,97,57,32,16,26,26,79,33,27,98,66],[88,36,68,87,57,62,20,72,3,46,33,67,46,55,12,32,63,93,53,69],[4,42,16,73,38,25,39,11,24,94,72,18,8,46,29,32,40,62,76,36],[20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,4,36,16],[20,73,35,29,78,31,90,1,74,31,49,71,48,86,81,16,23,57,5,54],[1,70,54,71,83,51,54,69,16,92,33,48,61,43,52,1,89,19,67,48]]
#12
≪ 1 =counter
0 =num
DO
counter =+num
++counter
UNTIL
ndivs(num)>500
END
num
≫
[ND1: 6.6s; CalcPad/Mac: 0.5s]
#13
≪ #13_data
total →STR 1 10 SUB STR→
≫
#13_data
function () {
var data = requestURL("http://naivedesign.com/redist/PE_13_data.txt").split("");
return data.map(function(x){return BigNum.fromString(x);});
}
#14
function () { /*as is*/
var longest = 0, index = 0;
var cache = []; cache[1] = 0;
for (var i=2; i<1e6; i++) {
var cur = i, steps = 0;
while (cur != 1 && cur >= i) {
cur = (cur % 2 ? (3*cur+1) : (cur/2));
++steps;
}
if (cur < i)
steps += cache[cur];
cache[i] = steps;
if (steps > longest) {
longest = steps;
index = i;
}
}
return index;
}
[ND1: 8s; CalcPad/Mac: 0.4s]
or (in RPL+)
≪ 0 =longest
[] =cache @ length of chain at num
0 =cache[1] @ length for num 1
2 1e6 1 - FOR i
i
0 =steps
DO
IF DUP isEven
THEN 2 / ELSE 3 * ++ END
++steps
UNTIL
DUP =:cur i <
END
DROP
cache[cur] =+steps
steps =cache[i]
IF steps longest >
THEN steps =longest i =index END
NEXT
index
≫
[impractically slow; CalcPad/Mac: 253s]
#15
≪ 20 → x 'round((x*2)!/(x!^2), 0)' ≫
or
≪ 20 → x ≪ x 2 * ! x ! 2 ^ / 0 RND ≫≫
#16
≪ 2 1000 →big ^ split total ≫
#18
≪ #18_data OBJ→
2 SWAP START
2 ≪ MAX ≫ DOSUBS
+
NEXT
≫
or (GolfScript/MorphEngine)
→{2{max}DOSUBS+}1-*
#18_data
[75,[95,64],[17,47,82],[18,35,87,10],[20,4,82,47,65],[19,1,23,75,3,34],[88,2,77,73,7,63,67],[99,65,4,28,6,16,70,92],[41,41,26,56,83,40,80,70,33],[41,48,72,33,47,32,37,16,94,29],[53,71,44,65,25,43,91,52,97,51,14],[70,11,33,28,77,73,17,78,39,68,17,57],[91,71,52,38,17,14,91,43,58,50,27,29,48],[63,66,4,68,89,53,67,30,73,16,69,87,40,31],[4,62,98,27,23,9,70,98,73,93,38,53,60,4,23]]
#19
≪ floor(12*100/7) ≫
#20
≪ 100 ! split total ≫
or (ignorant of split and total, using a loop)
≪ 100 ! →STR =s
0 =sum
1 s SIZE FOR i
s[i] STR→ =+sum
NEXT
sum
≫
or (using list processing)
≪ 100 ! →STR
split
{ STR→ } MAP
{ + } STREAM
≫
#21
function () {
function isAmicable(a) {
function d(n) {
var divs = calculator.functions.divs(n);
divs.pop();
return calculator.functions.vector.total(divs);
}
var b = d(a);
return (b != a && d(b) == a);
}
var sum = 0;
for (var i=2; i<10000; i++)
if (isAmicable(i))
sum += i;
return sum;
}
[ND1: 1.5s; CalcPad/Mac: 0.1s]
#22
≪ #22_data { →STR } MAP
SORT
split
1 { NSUB SWAP
1 { NUM 64 - } DOSUBS
total *
} DOSUBS
total
≫
[ND1: 22s; CalcPad/Mac: 1.8s]
#22_data
function () {
var data = requestURL("http://projecteuler.net/project/names.txt");
return eval("(" + "[" + data + "]" + ")");
}
#23
function () { /*as is*/
var F = calculator.functions;
var abundants = [];
for (var i=1; i<28123; i++)
if (F.vector.total(F.divs(i)) > i*2)
abundants.push(i);
var count = abundants.length;
var arr = [];
for (var i=0; i<count; i++)
for (var j=0; j<=i; j++)
arr[abundants[i]+abundants[j]] = true;
var sum = 0;
for (var i=0; i<28123+1000; i++)
if (!arr[i]) sum += i;
return sum;
}
[ND1: 21s; CalcPad/Mac: 1.7s]
#24
≪ "2" "013456789" permutate 1e6-9!*2 at + fromString ≫
[ND1: 20s; CalcPad/Mac: 1.0s]
#25
Closed-form solution
≪ ceil((1000-1+log(√5))/log((1+√5)/2)) ≫
or (using evaluation of traditional algebraic expression; note; spaces allowed in expression)
≪ 'ceil((1000-1+log(√5)) / log((1+√5)/2))' EVAL≫
or (brute-force; very slow)
≪ 1 =count
0 1 →big
DO
DUP ROT +
++count
UNTIL
DUP →STR size 1000 >=
END
DROP DROP
count
≫
#28
≪ 1001 → n '(4*n^3+3*n^2+8*n-9)/6'≫
#29
≪ 2 100 FOR a
2 100 FOR b
a b ^
NEXT
NEXT
99 99 * fromElements
removeDuplicates
size
≫
[ND1: 11.5s; CalcPad/Mac: 1.3s]
#30
≪ 0 =sum
10 200000 FOR i
i split DUP SQ SQ * total
IF i == THEN i =+sum END
NEXT
sum
≫
[ND1: 2.5m; CalcPad/Mac: 10.9s]
#33
function () {
var r = new Fraction(1);
for (var i=12; i<=99; i++) {
var n = split(i);
for (var j=i+1; j<=99; j++) {
var d = split(j);
if (n[1]==d[0] && i/j == n[0]/d[1])
r=r.multiply(new Fraction(i,j));
}
}
return r;
}
or (in RPL+)
≪ whole =r
12 99 FOR i
i split =n
i 1 + 99 FOR j
j split =d
IF n[2] d[1] == THEN
IF i j / n[1] d[2] / == THEN
i j →fract =*r
END
END
NEXT
NEXT
r
≫
[ND1: 2.3s; CalcPad/Mac: 0.15s]
#34
≪ 0 =sum
10 50000 FOR i
i split ! total
IF i == THEN i =+sum END
NEXT
sum
≫
[ND1: 45s; CalcPad/Mac: 3.6s]
#40
function () { /*as is*/
var s = "", p = 1;
for (var i=1; s.length<1e6; i++)
s += i;
for (var i=0; i<7; i++)
p *= s[Math.pow(10, i)-1];
return p;
}
#41
≪ 123456 permutate rsort =p
1 p size FOR i
p[i] 7000000 + =:x isPrime IFTB
NEXT
x
≫
#42
≪ #42_data { →STR } MAP
split
1 {
{ NUM 64 - } MAP
total
8 * incr √ decr 2 / @ inv triangle
fract not { true } IFT
} DOSUBS
size
≫
[ND1: 7.5s; CalcPad/Mac: 0.7s]
#42_data
function () {
var data = requestURL("http://projecteuler.net/project/words.txt");
return eval("(" + "[" + data + "]" + ")");
}
#47
≪ 1 =c false =foundIt
DO
c factors size
IF 8 == THEN c 1 + factors size
IF 8 == THEN c 2 + factors size
IF 8 == THEN c 3 + factors size
IF 8 == THEN true =foundIt END
END END END
++c
UNTIL foundIt
END
c decr
≫
[ND1: 123s; CalcPad/Mac: 9s]
#48
Classic RPL
≪ 1e10 R→I MODSTO
0
1 1000 FOR i
i R→I DUP POWMOD +
NEXT
1e10 R→I MOD
≫
[ND1: 3.8s; CalcPad/Mac: 0.3s]
#53
≪ 0 =count
23 100 FOR n
3 n 3 - FOR r
n r COMB
IF 1e6 > THEN ++count END
NEXT
NEXT
count
≫
[ND1: 5.3s; CalcPad/Mac: 0.4s]
#56
≪ 0 =m
80 100 FOR a
80 100 FOR b
a b toBigNum ^ split total
m max =m
NEXT
NEXT
m
≫
[ND1: 7.4s; CalcPad/Mac: 0.6s]
#57
≪ 0 =count
big0 =p0
big1 =p1
1 1000 START
big2 p1 * p0 + =:p @ Pell number
p1 + =:n @ numerator
IF size p size > THEN ++count END
p1 =p0
p =p1
NEXT
count
≫
[ND1: 30s; CalcPad/Mac: 2.5s]
or (in JavaScript; note: same speed)
function () {
var sum = 0;
var p0 = big0, p1 = big1;
for (var i=0; i<1000; i++) {
var p = BigNum["+"](BigNum["*"](big2, p1), p0); // Pell number
var n = BigNum["+"](p, p1); // numerator
if (String(n).length > String(p).length)
++sum;
p0 = p1; p1 = p;
}
return sum;
}
[ND1: 30s; CalcPad/Mac: 2.5s]
#63
≪ 0 =sum
1 9 FOR i
'floor(1/(1-log(i)))' EVAL =+sum
NEXT
sum
≫
#64
≪ 2..10000
[toSqrtCF period isEven not] map
total
≫
[ND1: 5.5s; CalcPad/Mac: 0.4s]
#67
≪ #67_data OBJ→
2 SWAP START
2 ≪ MAX ≫ DOSUBS
ADD
NEXT
V→
≫
#67_data
function () {
var data = requestURL("http://projecteuler.net/project/triangle.txt").split("");
data.pop(); // remove empty row
return data.map(function(x){return x.split(" ").map(function(x){return +x;});});
}
#69
function () { /*as is*/
var M = 1000001;
function phi(x) {
if(x <= 1) return 1;
var f = fact[x];
if(f == 1) return x-1;
var p = 1, fp = 1;
while((x /= f) % f == 0) { p++; fp *= f; }
return phi(x)*(f-1)*fp;
}
var fact = [];
for(var i=0; i<M; i++) fact[i]=1;
for(var i=2; i<M; i++)
if(fact[i]==1)
for(var k=i+i; k<M; k+=i) if(fact[k]==1) fact[k]=i;
var mn, mx = 0;
for(var n=2; n<M; n++) {
var val = n/phi(n);
if (val > mx) { mx = val; mn = n; }
}
return mn;
}
[ND1: 11s; CalcPad/Mac: 0.9s]
#71
≪ 1e6 → n 'int((n-5)/7)*3+2' ≫
#72
function () { /*as is*/
var M = 1000001;
function phi(x) {
if(x <= 1) return 1;
var f = fact[x];
if(f == 1) return x-1;
var p = 1, fp = 1;
while((x /= f) % f == 0) { p++; fp *= f; }
return phi(x)*(f-1)*fp;
}
var fact = [];
for(var i=0; i<M; i++) fact[i]=1;
for(var i=2; i<M; i++)
if(fact[i]==1)
for(var k=i+i; k<M; k+=i) if(fact[k]==1) fact[k]=i;
var s = 0;
for(var i=2; i<M; i++) s += phi(i);
return s;
}
[ND1: 10s; CalcPad/Mac: 0.9s]
or (in RPL+)
≪ 2..1e6 phi total ≫
[ND1: 94s; CalcPad/Mac: 5.1s]
#76
(Requires the Number Theory shared folder, which defines “p”, a function to compute the number of partitions of an integer)
≪ 100 NT.p 1 - ≫
or (using immediate algebraic expression syntax)
≪ NT.p(100)-1 ≫
#77
function () {
function part(a, b) {
if (a == 0)
return 1;
else if (a < 0 || b == 0)
return 0;
else return (part(a, b-1) +
part(a-ps[b], b));
}
var ps = primes(5000);
ps.unshift(0);
var i=1;
while (part(++i, ps.length-1) <= 5000)
;
return i;
}
[ND1: 2s; CalcPad/Mac: 0.2s]
#80
≪ 1..100 squareFree
99 setBigFPrecision toBigF √ split
[total] MAP
total
≫
[ND1: 82s; CalcPad/Mac: 7.3s]
or (not using array processing, but a regular loop)
≪ 99 setBigFPrecision
0 =sum
1 100 FOR i
IF i √ fract THEN
i toBigF √
split total =+sum
END
NEXT
sum
≫
[ND1: 82s; CalcPad/Mac: 7.3s]
or (using ContinuedFraction)
≪ 99 setBigFPrecision
0 =sum
1 100 FOR i
IF i √ fract THEN
i toSqrtCF @ convert to CF
toNumber @ get decimals
split @ into array of digits
total =+sum
END
NEXT
sum
≫
[ND1: 82s; CalcPad/Mac: 7.3s]
#87
≪ 50e6 √ primes =p
p SQ =p2
p2 p * 75 resize =p3
p2 SQ 25 resize =p4
p2 p3 [+] combine [ 50e6 <= ] filter
removeDuplicates =p23
p23 p4 [+] combine [ 50e6 <= ] filter
removeDuplicates
size
≫
[ND1: not practical; CalcPad/Mac: 18s]
#97
≪ 2 7830457 1e10 modpow 28433 * 1 + 1e10 mod ≫
#100
≪ 1 =:x =y
WHILE y<1e12
REPEAT
x =xx
3*x+2*y-2 =x
4*xx+3*y-3 =y
END
x
≫
#102
≪ #102_data
≪ V→ →V2 =a →V2 =b →V2 =c
a b cross last sign =s
b c cross last sign s ==
c a cross last sign s == and ≫ MAP
total
≫
#102_data
function () {
var data = requestURL("http://projecteuler.net/project/triangles.txt").split("\r\n");
data.pop(); // remove empty row
return data.map(function(x){return x.split(",").map(function(x){return +x;});}
);
}
#119
≪ []
2 =a DO
2 10 FOR b
a b ^ =:val
split total a == { val + } IFT
NEXT
++a
UNTIL DUP SIZE 31 ==
END
sort
30 GET
≫
#120
≪ 0 =sum
3 1000 FOR a
a DUP isEven { 2 - } { 1 - } IFTE
a * =+sum
NEXT
sum
≫
or
≪ 0 =sum
3 1000 FOR a
a^2-(2-mod(a,2))*a =+sum
NEXT
sum
≫
#123
≪ 300e3 primes DUP ≪ =p
2*N*p>1e10
≫ 7038 =offset find pos ++
≫
[ND1: 7.5s; CalcPad/Mac: 0.5s]
#124
≪ 1..100000 DUP
radical SWAP
2 [ @tag ] DOLIST
sort
10000 at tag
≫
[ND1: ~31m; CalcPad/Mac: 126s]
#131
≪ 1e6 =top
0 =sum
1 top FOR n
3*n*n+3*n+1 =:n top >= IFTB
n isPrime =+sum
NEXT
sum
≫
#188
≪ 8 =nDigits
1777 toBig =base
1855 =expo
10 toBig nDigits pow =m
base
1 expo-1 START
base @swap m modpow
NEXT
≫
[ND1: 14.5s; CalcPad/Mac: 1.1s]
Overview
Most solutions have been developed in RPL+. This guide is recommended if you want to pick up the language.
For several problems, solutions in more than one language, or taking different approaches, are shown. Run-times are reported for each, so you can see how they compare speed-wise. Note that a variety of styles are explored in these solutions. Many more variations are possible. (RPL+ can look like RPN or algebraic notation, for example.)
Run-times for CalcPad/Mac, an upcoming product that will allow WiFi folder sharing with ND1, are also included. This is to give you an idea of how MorphEngine performs on a desktop system.
The code is available for download into ND1: tap Project Euler under My Data | Downloadables.
(c) 2011-2012 Naive Design. All rights reserved.