Kaprekar's Constant in JavaScript
Tags: javascript, math, algorithms, beginners
Published: 2022-05-07 23:33:18

So I was scrolling TikTok's the other day, as one does, when I saw the number `6174` featured in one of the videos. Turns out this is a special number called Kaprekar's constant, named after Indian mathematician [D. R. Kaprekar](https://en.wikipedia.org/wiki/D._R._Kaprekar).

Start with a four-digit number with at least two different digits. If a number has less than four digits we can pad it with zeros. For example, `42` becomes `0042`.

1. Arrange the digits from largest to smallest and again from smallest to largest to get maximum and minimum values.
2. Subtract minimum from maximum.
3. Repeat these steps. 

The result will always converge to `6174` after a small number of iterations.

For example,

> `628`
> `8620 - 268 = 8352`
> `8532 - 2358 = 6174`

It's tedious to do this work by hand, though. Let's write some code to explore Kaprekar's algorithm further!

## From Concept to Code

The core algorithm may be implemented in JavaScript as follows.

First we convert a given number to a string [padded with leading zeros](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart):

```javascript
> var num = 423;
> num.toString().padStart(4, '0');
'0423'
```

Then we split the digits into an array so we can arrange them into our minimum and maximum numbers. The array operations are performed in-place, so a new array is created for each value:

```javascript
> var min = num.split('').sort()
[ '0', '2', '3', '4' ]
> var max = num.split('').sort().reverse()
[ '4', '3', '2', '0' ]
```

Finally we use `join` to convert each array back into a string and `parseInt` to convert those back to numbers so we can subtract the values:

```javascript
> parseInt(min.join(''))
234
> parseInt(max.join(''))
4320
```

## JavaScript Implementation

The final code incorporates a `validate` function to reject numbers without multiple digits and runs our algorithm automatically using a random four-digit number:

{% runkit %}
validate = function (num) {
  for (var i = 0; i < 10000; i += 1111) {
    if (num == i) {
      return false;
    }
  }
  return true;
}

kaprekar = function (num) {
  if (!validate(num)) {
    console.log("Invalid number " + num);
    return;
  }
  console.log(num);
  while (num != 6174) {
    var str = num.toString().padStart(4, '0');
    var max = parseInt(str.split('').sort().reverse().join(''));
    var min = parseInt(str.split('').sort().join(''));
    num = max - min;
    console.log(num);
  }
}

var n = Math.random() * 10000 | 0; // from https://stackoverflow.com/a/61696576
kaprekar(n);
{% endrunkit %}

## But wait, there's more!

Here is a variation of the program that generates a histogram of many iterations it takes to reach `6174` for all four-digit numbers. 

{% runkit %}
counts = {};

validate = function(num) {
  for (var i = 0; i < 10000; i += 1111) {
    if (num == i) {
      return false;
    }
  }
  return true;
}

kaprekar = function(num) {
  var count = 0;
  if (!validate(num)) {
    return;
  }
  while(num != 6174) {
    str = num.toString().padStart(4, '0');
    max = parseInt(str.split('').sort().reverse().join(''));
    min = parseInt(str.split('').sort().join(''));
    num = max - min;
    count++;
  }
  counts[count] = counts[count] || 0;
  counts[count]++;
}

for (var i = 1; i < 10000; i++) {
  kaprekar(i); 
}
console.log(counts);
{% endrunkit %}

Running this code you can see we reach `6174` after at most seven iterations:

```javascript
{ '0': 1,
  '1': 383,
  '2': 576,
  '3': 2400,
  '4': 1272,
  '5': 1518,
  '6': 1656,
  '7': 2184 }
```

## Conclusion

And that's it! Hope you enjoyed this fun little tidbit. 

Please feel free to leave your thoughts in the comments :sunny: :smile: :thumbsup: