The Numbers Game – part 2
In this previous post I described how and why I started on this project, and detailed my “proof of concept” version, written in Python. I was quite pleased with this version, but it had a few drawbacks.
- It requires a Python IDE to interpret and run the code. I use IDLE in windows.
- It doesn’t have a very friendly user interface, and what user interface there is has to be hand held a bit, there is little validation of the numbers entered.
- It is very slow, taking up to 20 minutes to calculate the full results. It comes up with solutions within 10 seconds in almost all cases, but the full calculation of nearly 31 million sets of numbers signs and brackets takes a looooong time.
There are two versions I would like to move on to from this first version. Eventually I would like to write a web based solution, with a graphical interface in a web page, and a server based calculation in the background, similar to my online Sudoku Solver. This uses PHP to calculate the solution, which is great for normal puzzles, but super hard puzzles can time out due to server limits. I produced another version like the one below for this program too.
The second is a windows version, written in Free pascal using the Lazarus IDE (an open source Delphi clone). Free pascal compiles into a normal .exe file, and is portable between windows computers. Lazarus and Free pascal can also be used to develop Linux programs and Android apps if you have the skills, so portable versions for these platforms would also be possible, even if there is no real need for these versions. Let’s be honest though, there is no need for any of these versions. Anybody interested in these programs will have written their own by now.
This page is about the Windows .exe version I have developed. This is a bit of an exercise in GUI design and optimisation of code, and at this stage is just a framework for future development.
This version immediately has some advantages over the original version.
- It is a .exe file that is portable across windows computers, with no need for other software to be installed.
- It has a rudimentary GUI with validation of numbers entered.
- First results take a few seconds, and the first 10 results stay on screen while the remaining results are calculated and displayed (taking another 2 minutes or so)
As you can see in the screenshot, the user interface is mouse driven. The six numbers are selected from an array of available numbers. When a number is selected, it becomes unavailable for selection again. Two buttons are provided for each of the little numbers, to allow two to be selected. Six numbers have to be selected before the Solve button is enabled. The Undo button removes the last selected number. The target number is selected by clicking the hundreds, tens and units buttons until the number required is entered. If a number is entered in error, clicking on alternate numbers will change it. A number greater than 99 must be entered for the Solve button to be enabled.
The selected numbers and target are displayed, as the disabled buttons can be difficult to distinguish.
When Solve is clicked, the solve process starts to calculate results. Each successively closer calculation (closer than 10 away) will be displayed in the top results box, until a match is found, and the remaining lines of the 10 available will be filled with match combinations, and its number within the total calculations shown. When the 10 lines are filled, successful matches will be shown in a rolling display in the second box, until completion, when the total lines displayed (including near misses) will be shown. A progress bar shows the progress graphically.
The code differs a little from the original version. As part of the program set up, three arrays are created. Each of these arrays could be hard coded, but to allow for future optimisation, I chose to generate them up front, at negligible cost in time.
The first array is all the permutations of the digits 1 2 3 4 5 6, and 720 numbers between 123456 and 654321 are generated. Each digit of these numbers is used as an index to select the digit to be used in the iteration through the calculation. This may be an unnecessary extra step but it made the code much simpler. Later versions may go back to a more normal method.
The second array is the combinations of 5 signs to be applied to the numbers in the calculations. There are 4 signs, and each of the 5 sign positions can use any of the 4 signs, so 4 are possible in the fisrt position, and for each of the 4, any of the 4 can be used in the second and so on. So the number of combinations is 4x4x4x4x4 or 1024. Five minus signs or 5 divide signs will never produce a match so could be left out, as could 5 multiplication signs if the target is prime. These exceptions add to the complexity of testing, so I leave them in.
Finally, see the previous post for the description of how Reverse Polish Notation (RPN) is used to position the signs and numbers into all the valid combinations (which is a remarkably low 42 different ways). The final array is generated in a very similar way to the Python program.
The actual calculation happens in a very similar way also. Python has some great tools built into it, which Free Pascal does not. One of these is itertools which handles generating permutations, and parsing through nested arrays, the second tool is automatic stack processing. RPN is based on stacks, and the main process uses two main stacks and the code was much simplified in the Python version. However, in the Free Pascal version I did both these processes the hard way, with flags, counts and normal array processing. In the end it was remarkably simple, the sort of stuff I spent a lot of time doing back in the 1970s when working on my Higher National Diploma in Computer Studies (when I wasn’t writing code in 3 languages to manipulate dates into usable formats)!
Download a version of the software here in zipped format.