How to resolve the algorithm Iterated digits squaring step by step in the D programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm Iterated digits squaring step by step in the D programming language
Table of Contents
Problem Statement
If you add the square of the digits of a Natural number (an integer bigger than zero), you always end with either 1 or 89: An example in Python:
Or, for much less credit - (showing that your algorithm and/or language is slow): This problem derives from the Project Euler problem 92. For a quick algorithm for this task see the talk page
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Iterated digits squaring step by step in the D programming language
Source code in the d programming language
import std.stdio, std.algorithm, std.range, std.functional;
uint step(uint x) pure nothrow @safe @nogc {
uint total = 0;
while (x) {
total += (x % 10) ^^ 2;
x /= 10;
}
return total;
}
uint iterate(in uint x) nothrow @safe {
return (x == 89 || x == 1) ? x : x.step.memoize!iterate;
}
void main() {
iota(1, 100_000_000).filter!(x => x.iterate == 89).count.writeln;
}
void main() nothrow @nogc {
import core.stdc.stdio: printf;
enum uint magic = 89;
enum uint limit = 100_000_000;
uint[(9 ^^ 2) * 8 + 1] lookup = void;
uint[10] squares;
foreach (immutable i, ref x; squares)
x = i ^^ 2;
foreach (immutable uint i; 1 .. lookup.length) {
uint x = i;
while (x != magic && x != 1) {
uint total = 0;
while (x) {
total += squares[(x % 10)];
x /= 10;
}
x = total;
}
lookup[i] = x == magic;
}
uint magicCount = 0;
foreach (immutable uint i; 1 .. limit) {
uint x = i;
uint total = 0;
while (x) {
total += squares[(x % 10)];
x /= 10;
}
magicCount += lookup[total];
}
printf("%u\n", magicCount);
}
import core.stdc.stdio, std.algorithm, std.range;
enum factorial = (in uint n) pure nothrow @safe @nogc
=> reduce!q{a * b}(1u, iota(1u, n + 1));
uint iLog10(in uint x) pure nothrow @safe @nogc
in {
assert(x > 0);
} body {
return (x >= 1_000_000_000) ? 9 :
(x >= 100_000_000) ? 8 :
(x >= 10_000_000) ? 7 :
(x >= 1_000_000) ? 6 :
(x >= 100_000) ? 5 :
(x >= 10_000) ? 4 :
(x >= 1_000) ? 3 :
(x >= 100) ? 2 :
(x >= 10) ? 1 : 0;
}
uint nextStep(uint x) pure nothrow @safe @nogc {
typeof(return) result = 0;
while (x > 0) {
result += (x % 10) ^^ 2;
x /= 10;
}
return result;
}
uint check(in uint[] number) pure nothrow @safe @nogc {
uint candidate = reduce!((tot, n) => tot * 10 + n)(0, number);
while (candidate != 89 && candidate != 1)
candidate = candidate.nextStep;
if (candidate == 89) {
uint[10] digitsCount;
foreach (immutable d; number)
digitsCount[d]++;
return reduce!((r, c) => r / c.factorial)
(number.length.factorial, digitsCount);
}
return 0;
}
void main() nothrow @nogc {
enum uint limit = 100_000_000;
immutable uint cacheSize = limit.iLog10;
uint[cacheSize] number;
uint result = 0;
uint i = cacheSize - 1;
while (true) {
if (i == 0 && number[i] == 9)
break;
if (i == cacheSize - 1 && number[i] < 9) {
number[i]++;
result += number.check;
} else if (number[i] == 9) {
i--;
} else {
number[i]++;
number[i + 1 .. $] = number[i];
i = cacheSize - 1;
result += number.check;
}
}
printf("%u\n", result);
}
import std.stdio, std.typecons, std.traits, std.typetuple, std.range, std.algorithm;
auto divMod(T)(T x, T y) pure nothrow @safe @nogc {
return tuple(x / y, x % y);
}
auto expand(alias F, B)(B x) pure nothrow @safe @nogc
if (isCallable!F &&
is(ParameterTypeTuple!F == TypeTuple!B)
&& __traits(isSame, TemplateOf!(ReturnType!F), Nullable)
&& isTuple!(TemplateArgsOf!(ReturnType!F)[0])
&& is(TemplateArgsOf!(TemplateArgsOf!(ReturnType!F)[0])[1] == B)) {
alias NAB = ReturnType!F;
alias AB = TemplateArgsOf!NAB[0];
alias A = AB.Types[0];
struct Expand {
bool first;
NAB last;
@property bool empty() pure nothrow @safe @nogc {
if (first) {
first = false;
popFront;
}
return last.isNull;
}
@property A front() pure nothrow @safe @nogc {
if (first) {
first = false;
popFront;
}
return last.get[0];
}
void popFront() pure nothrow @safe @nogc { last = F(last.get[1]); }
}
return Expand(true, NAB(AB(A.init, x)));
}
//------------------------------------------------
uint step(uint x) pure nothrow @safe @nogc {
Nullable!(Tuple!(uint, uint)) f(uint n) pure nothrow @safe @nogc {
return (n == 0) ? typeof(return)() : typeof(return)(divMod(n, 10u).reverse);
}
return expand!f(x).map!(x => x ^^ 2).sum;
}
uint iter(uint x) pure nothrow @nogc {
return x.recurrence!((a, n) => step(a[n - 1])).filter!(y => y.among!(1, 89)).front;
}
void main() {
iota(1u, 100_000u).filter!(n => n.iter == 89).count.writeln;
}
You may also check:How to resolve the algorithm Loops/Nested step by step in the OCaml programming language
You may also check:How to resolve the algorithm Conway's Game of Life step by step in the Rust programming language
You may also check:How to resolve the algorithm Dinesman's multiple-dwelling problem step by step in the Picat programming language
You may also check:How to resolve the algorithm Quine step by step in the PowerBASIC programming language
You may also check:How to resolve the algorithm Binary digits step by step in the PowerShell programming language