87 lines
2.5 KiB
D
87 lines
2.5 KiB
D
import std.stdio, std.traits, std.math, std.variant;
|
|
|
|
/// Returns a string with the error, or the three digits.
|
|
Algebraic!(string, char[3]) middleThreeDigits(T)(in T n)
|
|
if (isIntegral!T) {
|
|
// Awkward code to face abs(T.min) when T is signed.
|
|
ulong ln;
|
|
static if (isSigned!T) {
|
|
if (n >= 0) {
|
|
ln = n;
|
|
} else {
|
|
if (n == T.min) {
|
|
ln = -(n + 1);
|
|
ln++;
|
|
} else {
|
|
ln = -n;
|
|
}
|
|
}
|
|
} else {
|
|
ln = n;
|
|
}
|
|
|
|
if (ln < 100)
|
|
return typeof(return)("n is too short.");
|
|
immutable uint digits = 1 + cast(uint)log10(ln);
|
|
if (digits % 2 == 0)
|
|
return typeof(return)("n must have an odd number of digits.");
|
|
|
|
// From the Reddit answer by "millstone".
|
|
int drop = (digits - 3) / 2;
|
|
while (drop-- > 0)
|
|
ln /= 10;
|
|
|
|
char[3] result = void;
|
|
result[2] = ln % 10 + '0';
|
|
ln /= 10;
|
|
result[1] = ln % 10 + '0';
|
|
ln /= 10;
|
|
result[0] = ln % 10 + '0';
|
|
return typeof(return)(result);
|
|
}
|
|
|
|
void main() {
|
|
immutable passing = [123, 12345, 1234567, 987654321, 10001,
|
|
-10001, -123, -100, 100, -12345, -8765432];
|
|
foreach (n; passing) {
|
|
auto mtd = middleThreeDigits(n);
|
|
// A string result means it didn't pass.
|
|
assert(!mtd.peek!string);
|
|
writefln("middleThreeDigits(%d): %s", n, mtd);
|
|
}
|
|
writeln();
|
|
|
|
immutable failing = [1, 2, -1, -10, 2002, -2002, 0,
|
|
15, int.min, int.max];
|
|
foreach (n; failing) {
|
|
auto mtd = middleThreeDigits(n);
|
|
assert(mtd.peek!string);
|
|
writefln("middleThreeDigits(%d): %s", n, mtd);
|
|
}
|
|
writeln();
|
|
|
|
immutable long[] passingL = [123, 12345, 1234567, 987654321, 10001,
|
|
-10001, -123, -100, 100, -12345,
|
|
-8765432, long.min, long.max];
|
|
foreach (n; passingL) {
|
|
auto mtd = middleThreeDigits(n);
|
|
assert(!mtd.peek!string);
|
|
writefln("middleThreeDigits(%d): %s", n, mtd);
|
|
}
|
|
writeln();
|
|
|
|
immutable long[] failingL = [1, 2, -1, -10, 2002, -2002, 0, 15];
|
|
foreach (n; failingL) {
|
|
auto mtd = middleThreeDigits(n);
|
|
assert(mtd.peek!string);
|
|
writefln("middleThreeDigits(%d): %s", n, mtd);
|
|
}
|
|
writeln();
|
|
|
|
{
|
|
immutable n = short.min;
|
|
auto mtd = middleThreeDigits(n);
|
|
assert(!mtd.peek!string);
|
|
writefln("middleThreeDigits(cast(short)%d): %s", n, mtd);
|
|
}
|
|
}
|