

Solving a Combination Lock Puzzle with JuMP and Julia - idunning
http://iaindunning.com/2013/combination-locks.html

======
psibi
Haskell Solution:

    
    
      [(a,b,c,d,e,f) | a <- [39, 90, 75, 15, 57], b <- [9, 2, 58, 68, 48, 64], c <- [91, 29, 55, 16, 67, 8], d <- [22, 32, 25, 40, 54, 66], e <- [41, 14, 30, 49, 01, 17], f <- [44, 63, 10, 83, 46, 03], a+b+c+d+e+f == 419 ]

~~~
pygy_
What if you want to solve another matrix?

Do you have to write another program?

~~~
FreeFull
Could just take all the numbers as command-line arguments or something
similar.

------
jamesk_au
I also find it fascinating to read the algebraic solutions of others. This
algorithm seems to rely on an open source integer problem solver called "CBC"
[1]. But is it necessary for a general 'searching solver' of that kind to be
used for this particular problem?

The way in which the problem is framed suggests there is a unique solution.
The model is presented as a square matrix subject to linear constraints. There
are 36 unknowns, being x[1][1] through to x[36][36], each of which is 0 or 1.
There is the constraint that the sum of the unknowns is 419. And there are two
constraints to ensure that only one number is chosen from each row and each
column, which together give rise to 36 constraint equations.

If any one of the latter constraints is replaced by the sum constraint, there
is a linear system of 36 equations in 36 unknowns. Is it possible for that
system to be constructed and solved directly through matrix inversion?

(For those trying the exercise at home, the number at P[1,2] appears as 90 but
from the full problem statement I think it should be 6.)

[1]: [https://projects.coin-or.org/Cbc](https://projects.coin-or.org/Cbc)

~~~
m3koval
Unfortunately not. Matrix inversion (or any type of linear algebra, really)
deals with real numbers. This problem is nearly a linear program, which can be
solved very efficiently, except that some variables are constrained to { 0, 1
}. As a result, it's an integer program, which is NP-hard. Intuitively, this
is hard because there are no derivatives (e.g. gradient, Hessian) to exploit
in discrete optimization problems.

One heuristic is to solve an IP is to relax the integer constraint to
inequality constraints, solve the LP, and round the results. However, this can
do arbitrarily poorly on most problems.

------
nly
Algebraic solutions are fascinating. I was hooked on Sage for a week or two
solving similar problems. I solved this one using brute force though:

    
    
        array<array<int, 6>, 6> tumblers
          = {{{39, 90, 75, 88, 15, 57}, {9,   2, 58, 68, 48, 64},
              {29, 55, 16, 67,  8, 91}, {40, 54, 66, 22, 32, 25},
              {49,  1, 17, 41, 14, 30}, {44, 63, 10, 83, 46,  3}}};
    
        template <typename It> bool
        solve (It tumbler, It end, int const sum) {
            if (tumbler == end)
                return (sum == 0);
            for (auto const pin: *tumbler) {
                if (solve (next(tumbler), end, sum - pin)) {
                    std::cout << pin << std::endl;
                    return true;
                }
            }
            return false;
        }
    
        int main() {
            solve (tumblers.rbegin(), tumblers.rend(), 419);
        }

------
comex
As a note, this kind of problem is NP complete in the number of locks because
the subset sum problem can be embedded into it.

------
tokipin
not quite sure i understand the problem, but here's one Mathematica approach:

    
    
      m = {{39, 90, 75, 88, 15, 57},
         {9, 2, 58, 68, 48, 64},
         {29, 55, 16, 67, 8, 91},
         {40, 54, 66, 22, 32, 25},
         {49, 1, 17, 41, 14, 30},
         {44, 63, 10, 83, 46, 3}};
    
      Select[
       Extract[m, #] & /@ Transpose[{Range[6], #}] & /@ Tuples[Range[6], 6],
       Total[#] == 419 &]

