A Q Implementation of the Classic Mastermind Game
Clone this project and start q with the following command to see a brief introduction to different solutions to the mastermind game.
Code Selection
The classic game of mastermind has the code maker choose 4 colors (with repeats) from a total of 6 colors. Other versions have been sold that increase the universe to 8 colors, but attempt to keep the complexity the same by not allowing repeated colors. A full list of the variations can be found on the mastermind wiki.
Our first task, then, is to define the set of possible codes. The
.mm.perm function allows us generate permutations with (or without)
repeat by passing a positive (or negative) parameter.
1296
Algorithm Selection
We can then choose an algorithm (say Knuth's minimax algorithm that is guaranteed to win in 5 moves) and an initial guess "1122", and we can see how the algorithm performs:
n guess score
-----------------
1296 "1122" 1 0
256 "1344" 0 2
41 "3135" 1 0
6 "3426" 1 3
1 "6432" 4 0
After starting with 1296 possibilities, it quickly narrowed the choices down to 256, then to 41, 6 and finally found the answer on 5th guess.
The list of possible algorithms are:
- .mm.minimax (Knuth's algorithm)
- .mm.irving (minimum expected size)
- .mm.maxent (maximum entropy)
- .mm.maxparts (most parts)
- .mm.maxgini (maximum gini coefficient)
Interactive Play
Alternatively, we can play the game interactively (passing in an algorithm so it can give us a hint at the best answer).
n guess score
-----------------
1296 "1122" 0 1
guess (HINT 2345): 2345
n guess score
----------------
256 "2345" 0 1
guess (HINT 3616): 3616
n guess score
---------------
27 "3616" 2 2
guess (HINT 3661): 3661
n guess score
--------------
2 "3661" 1 3
guess (HINT 6613): 6613
n guess score
-----------------
1296 "1122" 0 1
256 "2345" 0 1
27 "3616" 2 2
2 "3661" 1 3
1 "6613" 4 0
Exhaustive Play
We can see the performance of each algorithm by using it on every possible code and generating a histogram of how many turns each game took.
To speed things up, we can convert the .mm.score function into a
cache:
We can then use peach to run the games in parallel:
1| 1
2| 6
3| 62
4| 533
5| 694
We have just shown that Knuth's algorithm does indeed win in 5 moves or less.