RosettaCodeData/Task/Middle-three-digits/D/middle-three-digits-2.d
Ingy döt Net db842d013d A-M baby
2013-04-10 21:29:02 -07:00

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);
}
}