Here I propose to find a solution to Smullyan's numerical machines as defined here.
Problem statement
They're machines that take a list of digits as input, and transform it to another list of digits following some rules based on the pattern of the input. Here are the rules of the machine given in the link above, expressed a bit more formally. Let say M is the machine, and M(X) is the transformation of X. We define a few rules like this:
M(2X) = X
M(3X) = M(X)2M(X)
M(4X) = reverse(M(X)) // reverse the order of the list.
M(5X) = M(X)M(X)
And anything that does not match any rule is rejected. Here are a few examples:
- M(245) = 45
- M(3245) = M(245)2M(245) = 45245
- M(43245) = reverse(M(3245)) = reverse(45245) = 54254
- M(543245) = M(43245)M(43245) = 5425454254
And the questions are, find X such that:
- M(X) = 2
- M(X) = X
- M(X) = X2X
- M(X) = reverse(X)
- M(X) = reverse(X2X)reverse(X2X)
Here is a second example a bit more complex with the exhaustive search (especially if I want the first 10 or 100 solutions).
M(1X2) = X
M(3X) = M(X)M(X)
M(4X) = reverse(M(X))
M(5X) = truncate(M(X)) // remove the first element of the list truncate(1234) = 234. Only valid if M(X) has at least 2 elements.
M(6X) = 1M(X)
M(7X) = 2M(X)
Questions:
- M(X) = XX
- M(X) = X
- M(X) = reverse(X)
(Non-)Solutions
Writing a solver in Prolog is pretty straightforward. Except that it's just exhaustive exploration (a.k.a brute force) and may take some time for some set of rules.
I tried but couldn't express this problem in terms of logic constraints with CLP(FD), so I tried CHR (Constraint Handling Rules) to express this in terms of constraints on lists (especially append
constraints), but no matter how I express it, it always boils down to an exhaustive search.
Question
Any idea what approach I could take to resolve any problem of this kind in a reasonable amount of time? Ideally I would like to be able to generate all the solutions shorter than some bound.