RosettaCodeData/Task/Aliquot-sequence-classifica.../D/aliquot-sequence-classifica...

52 lines
1.6 KiB
D

import std.stdio, std.range, std.algorithm, std.typecons, std.conv;
auto properDivisors(in ulong n) pure nothrow @safe /*@nogc*/ {
return iota(1UL, (n + 1) / 2 + 1).filter!(x => n % x == 0 && n != x);
}
enum pDivsSum = (in ulong n) pure nothrow @safe /*@nogc*/ =>
n.properDivisors.sum;
auto aliquot(in ulong n,
in size_t maxLen=16,
in ulong maxTerm=2UL^^47) pure nothrow @safe {
if (n == 0)
return tuple("Terminating", [0UL]);
ulong[] s = [n];
size_t sLen = 1;
ulong newN = n;
while (sLen <= maxLen && newN < maxTerm) {
newN = s.back.pDivsSum;
if (s.canFind(newN)) {
if (s[0] == newN) {
if (sLen == 1) {
return tuple("Perfect", s);
} else if (sLen == 2) {
return tuple("Amicable", s);
} else
return tuple(text("Sociable of length ", sLen), s);
} else if (s.back == newN) {
return tuple("Aspiring", s);
} else
return tuple(text("Cyclic back to ", newN), s);
} else if (newN == 0) {
return tuple("Terminating", s ~ 0);
} else {
s ~= newN;
sLen++;
}
}
return tuple("Non-terminating", s);
}
void main() {
foreach (immutable n; 1 .. 11)
writefln("%s: %s", n.aliquot[]);
writeln;
foreach (immutable n; [11, 12, 28, 496, 220, 1184, 12496, 1264460,
790, 909, 562, 1064, 1488])
writefln("%s: %s", n.aliquot[]);
}