A Neat Problem

Here’s a neat game, with a really neat solution. I’ll post the solution later, but this post shows a Haskell implementation of the game. I first encountered this game as a puzzle in a game (an otherwise unremarkable one) called Keepsake by The Adventure Company.

The game looks like this. There are five displays, which display the letters A through E. The letters cycle through that sequence, wrapping back to A at the end. There are also five buttons, which are numbered 1 through 5. Each of the button changes each display my some random amount (from zero to four steps forward). Pressing a button five times consecutively will always get things back to where they were before it was pressed. The goal is to get from the (randomly chosen) starting point to the (randomly chosen) ending point.

For example, if the starting point were ABCDE, the target were EDBDE, and button 3 advanced the first and third dials by two and the second by 1 (what I’ll call a “signature” of [2, 1, 2, 0, 0]), then the correct answer could be obtained by pushing button 3 twice. The first press would change it to CCEDE, and the second to EDBDE (because the third dial wraps).

Three fundamental pieces of information are used to define instances of this problem. There is a starting display, a target display, and the actions of each of the five buttons. The program chooses random values for these three, prints the target, and then starts processing moves by the user.

There is one quirk, though. We want the problem to have a solution. Clearly there are some random matrices for which the problem has no solution. (For a trivial example, imagine a matrix of all zeros; then it’s impossible to change the display.) It turns out that, for reasons I will explain when I post the solution, it is sufficient for the matrix to have a non-zero (mod 5) determinant. So here’s the code to calculate the determinant (by cofactor expansion along the first column)

Putting all of this together gives an implementation of the puzzle. The puzzle can be fun to play with, but there’s also a neat straight-forward mathematical technique for finding the solution, which I’ll post in a few days. Until then, have fun!

It’s not tough to deterministically generate a nonsingular random matrix. My Haskell-fu is a lamentably weak so I’ll have to describe it.

Create 5 matrices with the following procedure. Initialize the matrix to zero, then fill in (if this is matrix #i) row i with random values. Then set the diagonal to all ones.

Multiply all 5 of these matrices together (in any order), and you get a nonsingular matrix that’s nice and random. I’m not willing to warrant that it’s absolutely uniform, but I think it would be fine for a game.

Alternatively, you could generate a bunch of row-operation matrices and multiply them together. A row-operation matrix is an identity matrix with exactly one of the off-diagonal entries set to a random nonzero value.