Search
Feb 11, 2012
Jos van Uden
Feb 11, 2012
H. S. Teoh
Feb 11, 2012
bearophile
Feb 11, 2012
H. S. Teoh
Feb 11, 2012
Kapps
Feb 11, 2012
Jos van Uden
```bool isKaprekar(in long n) pure nothrow
in {
assert(n > 0, "isKaprekar(n): n must be > 0");
assert(n <= uint.max, "isKaprekar(n): n must be <= uint.max");
} body {
ulong powr = n ^^ 2UL;
ulong tens = 10, r, l;
while (r < n) {
r = powr % tens;
l = powr / tens;
if (r && l + r == n)
return true;
tens *= 10;
}
return false;
}

--

A positive integer is a Kaprekar number if:

-It is 1
-The decimal representation of its square may be split once into two parts consisting of positive integers which sum to the original number. Note that a split resulting in a part consisting purely of 0s is not valid, as 0 is not considered positive.

Example: 2223 is a Kaprekar number, as 2223 * 2223 = 4941729, 4941729 may be split to 494 and 1729, and 494 + 1729 = 2223.

```
```On Sat, Feb 11, 2012 at 12:20:22PM +0100, Jos van Uden wrote:
> bool isKaprekar(in long n) pure nothrow
> in {
>     assert(n > 0, "isKaprekar(n): n must be > 0");
>     assert(n <= uint.max, "isKaprekar(n): n must be <= uint.max");
> } body {
[...]

Shouldn't you just use "in ulong n" as parameter instead of long with a contract?

T

--
The richest man is not he who has the most, but he who needs the least.
```
```H. S. Teoh:

> > bool isKaprekar(in long n) pure nothrow
> > in {
> >     assert(n > 0, "isKaprekar(n): n must be > 0");
> >     assert(n <= uint.max, "isKaprekar(n): n must be <= uint.max");
> > } body {
> [...]
>
> Shouldn't you just use "in ulong n" as parameter instead of long with a contract?

In this case the answer is probably positive.

But in general it's better to accept a signed number and then refuse the negative values in the pre-condition, otherwise if you give by mistake a negative number to the function it's not caught.

Such work-arounds are less needed in saner languages, where the ranges of integral values are verified, at compile time where possible, and at run-time otherwise. Unwanted wrap-arounds and undetected overflows in integral values are so '70 :-)

Bye,
bearophile
```
```On Sat, Feb 11, 2012 at 10:47:01AM -0500, bearophile wrote:
> H. S. Teoh:
>
> > > bool isKaprekar(in long n) pure nothrow
> > > in {
> > >     assert(n > 0, "isKaprekar(n): n must be > 0");
> > >     assert(n <= uint.max, "isKaprekar(n): n must be <= uint.max");
> > > } body {
> > [...]
> >
> > Shouldn't you just use "in ulong n" as parameter instead of long with a contract?
>
> In this case the answer is probably positive.
>
> But in general it's better to accept a signed number and then refuse the negative values in the pre-condition, otherwise if you give by mistake a negative number to the function it's not caught.
>
> Such work-arounds are less needed in saner languages, where the ranges of integral values are verified, at compile time where possible, and at run-time otherwise. Unwanted wrap-arounds and undetected overflows in integral values are so '70 :-)
[...]

Hmph. I was under the impression that D was clever enough to be able to detect overflow problems when dealing with signed->unsigned conversion.

The bad thing about taking signed long as parameter and then restrict it to 0..uint.max means that you're unnecessarily constraining the domain of the function.

T

--
Being able to learn is a great learning; being able to unlearn is a greater learning.
```
```On 11-2-2012 16:30, H. S. Teoh wrote:
> On Sat, Feb 11, 2012 at 12:20:22PM +0100, Jos van Uden wrote:
>> bool isKaprekar(in long n) pure nothrow
>> in {
>>      assert(n>  0, "isKaprekar(n): n must be>  0");
>>      assert(n<= uint.max, "isKaprekar(n): n must be<= uint.max");
>> } body {
> [...]
>
> Shouldn't you just use "in ulong n" as parameter instead of long with a
> contract?

Good question. I'm not sure which is better. My personal preference goes to (in uint n) and rely on the (self) documentation. But this is demo code and I wanted to show Ds support for contracts. Also, the contract version will at least give you a warning in debug mode. By
the way, if you use (in ulong n) you could still get in trouble
because the code only handles upto uint.max correctly due to the pow.

bool isKaprekar(in uint n) pure nothrow {
ulong powr = n ^^ 2UL;
ulong tens = 10, r, l;
while (r < n) {
r = powr % tens;
l = powr / tens;
if (r && l + r == n)
return true;
tens *= 10;
}
return false;
}

```
```On 11/02/2012 9:55 AM, H. S. Teoh wrote:
> The bad thing about taking signed long as parameter and then restrict it
> to 0..uint.max means that you're unnecessarily constraining the domain
> of the function.
>
>
> T
>

In this case, you're actually not changing the domain of the function. The domain was (0, sqrt(0 .. ulong.max)], which is smaller than long.max anyways.
```