www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - [your code here]

reply Jos van Uden <user domain.invalid> writes:
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
Feb 11 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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.
Feb 11 2012
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
Feb 11 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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.
Feb 11 2012
parent Kapps <Kapps NotValidEmail.com> writes:
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.
Feb 11 2012
prev sibling parent Jos van Uden <user domain.invalid> writes:
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; }
Feb 11 2012