in maths, python, tutorial

Recreational Maths in Python

Share Button

This post is for all the developers and mathematicians out there that are curious to explore and visualize the bizarre properties of numbers. Although Maths plays an important role in today’s technology, many people likes to abuse it for recreational purposes. Part of the appeal of Recreational Maths lies in the challenge to discover something new. Despite what many believe, finding mathematical patterns is very easy; it’s discovering something useful that is incredibly challenging. If you’re up for such a challenge, this tutorial will teach you how to use Python to calculate some of the most infamous numerical sequences.

Part 0. Unlimited precision

If you are familiar with Python, it is not uncommon to discover native features which would be challenging to replicate in other languages. One of the most intriguing is the way Python handles long integers. While standard ints have a 32bit precision, longs can store arbitrarily big integers. This feature is native in Python, and does not requires any additional piece of code: when an  int becomes too large, it is automatically cast to long. Compared to Java or C#, Python is perfect to work with very long numbers. The best hidden features of Python have been discussed in the tutorial The Top 5 Hidden Features of Python.

Part 1. Working with digits

Many numerical sequences which are classified as recreational Maths work by manipulating the digits of a number. Converting a number in the list of its digits is surprisingly easy in Python:

The number is firstly converted into a string using str(n); it is then passed into map which converts each character of the string into an integer.

Narcissistic numbers

Let’s use this to calculate Narcissistic numbers (OEIS A005188); a number of d digits is narcissistic if it’s equal to the sum of the d^{th} power of its digits. For instance, 153 is narcissistic since 153=1^3+5^3+3^3. These numbers are rather useless and they are “very suitable for puzzle columns and likely to amuse amateurs, but there is nothing in them which appeals to the mathematician” (G. H. Hardy, 1993).

The following code checks whether a number is narcissistic or not:

The for loop can be replaced by a map function, which calculates the d^{th} power of each digit:

To calculate the sequence you can simply leave this piece of code running:

Kaprekar numbers

A slightly more interesting sequence is the one made of Kaprekar numbers (OEIS A006886). Consider an n-digit number. Square it and add the right n digits to the left n or n-1 digits. If the resultant sum is equal to the original number, then it is a Keprekar number. 9 satisfies this property, since 9^2=81 and 8+1= 9 itself. Similarly 297^2=88209 and 88+209=297.

What makes it more interesting is that it requires to split a number into digits and then to join them. Once again, Python offers a very elegant way of doing this:

What we have to do now is to split the left and right side of the digits into two separate lists. To get the left  n elements of a list d in Python one can write d[:-n]; for the right  n elements d[-n:] can be used instead.

Step 2. Working with sequences

Some numbers requires a more complex approach. This is the case for happy numbers (OEIS A007770). Finding if a number is happy or sad (not happy) requires an iterative computation. Let’s start with the happification, a process in which you take the digits of a number, square and sum them up:

    \[happy\left( 13\right)=1^2+3^2=10\]

A number is happy if repeating this process leads to 1. In this example, 13 is indeed happy, since happy\left( 10\right)=1. An interesting property of the happification is that numbers either end up at 1, or they get stuck in a loop made of 41637588914542 and 20. Numberphile has covered this in a video in which Matt Parker coined the term melancoil.

The function is_happy determines whether a number is happy or not; it keeps happifying the number until it gets 1 or a loop:

It’s important to remember that despite Python’s ability to work with arbitrarily large numbers, the function is_happy cannot. This is because Python has a recursion depth limit. You can extend it using:

Another alternative is to avoid recursion altogether:

Since we are storing the numbers in a list, the function is again limited by the amount of memory available. A further improvement is to remove any memory requirement by hard-coding the melancoil numbers in the function:

The above function works only because all the sad numbers eventually end up in the melancoil loop.

Step 3. Visualising graphs

The happification process naturally links numbers to each other. The result is a network graph which can be hard to see within the Python console. The best way to show the relationships between them is to visualise them with a graph. This is discussed in the tutorial Interactive Graphs in the Browser. You can see the result in the interactive graph below:

You can find a high resolution version (2000x2000px, first 1000 numbers) here: PNG, SVG, HTML.

Step 4. Parallel computation

If the sequence you are trying to calculate works on very big numbers, it might take longer and longer to run. Calculating several numbers in parallel can help speed up the process, especially if you have multiple cores. There are several ways to implement parallel computation in Python; this example relies on the joblib package:

Line 5 opens a with section which creates four parallel processes. Every process has overhead, so it’s important to use a reasonable number; using too many processes can actually slow down your calculations. Within the parallel block, the computation is done with the function parallel, which is fed four tasks. The function delayed allows the user to specify the name of the function that will be executed separately. Evaluating results forces the program to wait until all of the processes are completed.

It is important to notice that in order for this code to work, everything has to be inside a __main__ section; this is because when the processes start they will execute the current file again.

Conclusion

This tutorial has shown how Python can be used effectively to calculate numerical sequences of arbitrary length. Recreational Maths is a very intriguing field, which can sometimes produce beautiful things such as Conway’s Game of Life. I strongly encourage you to explore the bizarre properties of numbers, and see if you can find something new.

If you are interested in this topic, you might also find the following tutorials interesting:

📧 Stay updated

A new tutorial is released every week.

💖 Support this blog

This websites exists thanks to the contribution of patrons on Patreon. If you think these posts have either helped or inspired you, please consider supporting this blog.

Paypal
Ko-fi
Twitter_logo

Write a Comment

Comment

  1. What’s the point of linking to the previous article (“5 hidden features of Python”) when it’s password-protected?

Webmentions

  • Interactive Graphs in the Browser - Alan Zucconi May 15, 2016

    Recreational math problems are valuable to learning how to solve problems (by reducing complexity and confusion to the simplest possible elements), and to learning computer science and programming. In the world of numbers, there are some well-known (and not so well-known) sets of numbers that have special properties. Check out some of these number curiosities: http://www.glennwestmore.com.au/category/number-curiosities/

  • Links of the Week, W46 2015 | One More Game-Dev and Programming Blog May 15, 2016

    Recreational math problems are valuable to learning how to solve problems (by reducing complexity and confusion to the simplest possible elements), and to learning computer science and programming. In the world of numbers, there are some well-known (and not so well-known) sets of numbers that have special properties. Check out some of these number curiosities: http://www.glennwestmore.com.au/category/number-curiosities/