View mode: basic / threaded / horizontal-split · Log in · Help
February 11, 2012
[your code here]
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.

See also http://rosettacode.org/wiki/Kaprekar_numbers
February 11, 2012
Re: [your code here]
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.
February 11, 2012
Re: [your code here]
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
February 11, 2012
Re: [your code here]
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.
February 11, 2012
Re: [your code here]
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;
}
February 11, 2012
Re: [your code here]
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.
Top | Discussion index | About this forum | D home