Kaprekor's Constant Demonstrator

This is a demonstration of Kaprekar's Constant, using lists and procedures.

(from Kaprekar’s Constant – Math Fun Facts)

Take any four digit number (whose digits are not all identical), and do the following:

  1. Rearrange the string of digits to form the largest and smallest 4-digit numbers possible.
  2. Take these two numbers and subtract the smaller number from the larger.
  3. Use the number you obtain and repeat the above process.

What happens if you repeat the above process over and over? Let’s see…

Suppose we choose the number 3141.
4311-1134=3177.
7731-1377=6354.
6543-3456=3087.
8730-0378=8352.
8532-2358=6174.
7641-1467=6174…
The process eventually hits 6174 and then stays there!

But the more amazing thing is this: every four digit number whose digits are not all the same will eventually hit 6174, in at most 7 steps, and then stay there!

Sample run using AI2:

To allow book marking the steps in the construction of this app, I am breaking down the construction into separate posts.

Next post: The Designer

1 Like

The Designer

Reading from top to bottom, I have included

  • A customized Title bar Text value for the screen
  • A Horizontal Arrangement haAbout containing
    • An About button btnAbout, to expose or hide a WebViewer pointing to the web site where I found this topic
    • A Textbox txbInput, set to Numbers Only, for the user to input their starting number
    • A Button btnStart, for starting the calculation cycles
  • A Label lblStepCount, to summarize the number of steps taken before discovering a duplicate
  • A ListView ListView1, to show the individual steps one by one
  • A WebViewer WebViewer1, to optionally display the About web site.

The WebViewer:

The HomeUrl is set in the Designer, but the Visible attribute is turned off, for control by the btnAbout button:

This is a very economical way of alternately displaying and hiding About information, using the logical NOT block on the .Visible attribute of the WebViewer.

Next post: Variables

1 Like

Global variables:

global digits
It's necessary to capture the number of digits we are using as the standard range of our numbers, to allow for padding on either side. Without this, we would not know how many zeroes to add to our numbers when they come up short.

I set it to 4 initially, but I have set up the code to accept the length of the starting number as the standard length, to let us explore beyond 4 digits.

global history

This algorithm will be looping over the Kaprekor process repeatedly, but it needs a way to know when to stop. So we need to keep a list (history, initially empty) of all the intermediate values we have encountered in our loop, and to check it to see if our latest number is already in the list.

global latest
We need a global variable to hold the latest number in our loop, for checking against the history list. This is where we keep it across iterations.

Next post: Padding procedures

Padding procedures:

Because this logic is repeated in our code and gets a bit involved, we hide the logic inside two value procedures, for left padding with zeroes (lpad), and right padding with zeroes (rpad).

Both value procedures have the same logic, differing only in which side they add a '0' to the input number. For generality's sake, I pass them the target length as a parameter.

Here is a screen shot of a couple of test procedures and their Companion Do It results, to show what I expect from them:

(I was lazy and did not include further test cases like empty input or overly long input. I leave that to you.)

I wrapped the Do It calls in procedures to avoid yellow Blocks Editor warning about loose blocks.

Next post: Running the Loop

Running the Loop

This is the Click Event for the Start Button, btnStart.

It has initialization code to set up for the loop, further down:

We need to have:

  • The ListView ListView1 emptied out before we go adding anything to it
  • The global variable latest loaded with our input starting number
  • Our history emptied out before running the loop
  • Our number of digits set, for use in padding short numbers.

The loop will be testing if the latest number is not in our history list, so we should not be adding it to history prematurely, otherwise we would skip the loop entirely.

It takes a bit of work to set up the two descending and ascending sorted numbers for the pending subtraction, so I added two local variables (descending and ascending) with initialization code to run at the top of my while loop.

They need to be read from right to left, to see how they work.

The text split block will break a number down into a list of its digits, if you give it an empty (zero length) delimiter (at)

AI2 has a handy list sorting block to sort the list of digits into ascending order.

It also has a list block to text join the resulting list back into a piece of text interposing a delimiter (in my case, another zero length text value).

The descending number needs to have itself reversed (a text block) to be in descending order It may need trailing 0's, so it is run through the rpad function.

The ascending number is already in ascending order, so it only needs left padding with zeroes to the required number of digits.

The rest of the loop builds on these values, in three steps:

  • adding the lates value to the history list, to help stop the loop when duplication is encountered
  • Calculating the new latest number by subtracting the ascending value from the descending value, then left padding it if needed.
  • Formatting a new ListView Element from the descending, ascending, and latest values, and adding it to the ListView.

Finally, after the loop, we take the list length of the ListView Elements and display it as a nice summary of how many steps we took.

For those of you who hung in through the tutorial, here is the aia source:


Kaprekars_Constant.aia (4.9 KB)

Ideas for further work:

  • Establishing the loop length limit for different ranges (number of digits)
  • Listing the termination values for different ranges.
3 Likes