MiniZinc cryptarithms improved

Previously, I posted an experiment in solving cryptarithms with Python and MiniZinc. I've just put an improved version on GitHub, since I figured out how to generalize the problem somewhat--Python now just converts your problem into a dictionary and feeds that to an existing script that doesn't have to change. This new model still has some rough edges--artifacts of the learning process--but it works well enough.

Kaprekar Process

The AMS Page a Day Calendar for January 17 discusses the Kaprekar Process:

D.R. Kaprekar discovered an interesting phenomenon that occurs when one takes a four-digit number, such that all four digits are not equal, and computes the difference between its decreasing and increasing rearrangements. He found that within seven iterations of this process you will always reach the number 6174, and this process became known as the Kaprekar Process.

-- Ellis, R., & Lewis, J. (2017). Investigations into the Kaprekar Process. Rose-Hulman Undergraduate Mathematics Journal, 3(2). https://scholar.rose-hulman.edu/rhumj/vol3/iss2/4

It's easy enough to do this calculation in Python

def kaprekar(x): 
    i = 0
    xs = []
    while True:
        xs.append(x)
        if x in (6174,0):
            return (i, xs)
        i+=1
        while x < 1000: x = x * 10
        x = list(str(x))
        x1 = int(''.join(sorted(x)))
        x2 = int(''.join(sorted(x, reverse=True)))
        #print(''.join(x), x1, x2)
        x = max([x1, x2]) - min([x1, x2])
>>> kaprekar(2021)
(3, [2021, 2088, 8532, 6174])
>>> kaprekar(4627)  
(7, [4627, 5175, 5994, 5355, 1998, 8082, 8532, 6174])

We can also verify that at most seven iterations are required to reach 6174:

Kaprekar process graph
>>> ks = [kaprekar(x) for x in range(1,9999)]
>>> max([cnt for cnt, hist in ks]) 
7
>>> from collections import Counter
>>> Counter([x[0] for x in ks]).most_common()
[(3, 2400), (7, 2184), (6, 1656), (5, 1518), (4, 1272), (2, 576), (1, 391), (0, 1)]

And finally, for the sake of having an image on this post:

>>> sns.set_theme(style="whitegrid")
>>> sns.countplot(x=[x[0] for x in ks], color=(.3, .7, .3), alpha=.8, saturation=.3)

About Me

Developer at Brown University Library specializing in instructional design and technology, Python-based data science, and XML-driven web development.

Tags