ILP Part 37 — Send more money

This is the thirty seventh part of the ILP series. For your convenience you can find other parts in the table of contents in Part 1 – Boolean algebra

Today we are going to solve “Send more money” problem. We have the following addition:

    \begin{gather*} \begin{array}{lccccc} & & S & E & N & D \\ + & & M & O & R & E \\ \hline \\ = & M & O & N & E & Y \end{array} \end{gather*}

Each letter represents exactly one digit in ten-based system. We need to find out numbers.
You can try to solve this on a piece of paper. The solution is;

    \begin{gather*} \begin{array}{lccccc} & & 9 & 5 & 6 & 7 \\ + & & 1 & 0 & 8 & 5 \\ \hline \\ = & 1 & 0 & 6 & 5 & 2 \end{array} \end{gather*}

We can solve this in ILP in at least two different ways. Let’s go.

First solution

The most obvious way is to define digit variables, make sure, that they are different and that the first digit of a number is not zero:

    \begin{gather*} S, E, N, D, M, O, R, Y \in \{0, 1, 2, 3, 4, 5, 6, 7, 8, 9\}\\ S, M \ge 1 \\ S \neq E\\ S \neq N\\ S \neq D\\ S \neq M\\ S \neq O\\ S \neq R\\ S \neq Y\\ E \neq N\\ E \neq D\\ E \neq M\\ E \neq O\\ E \neq R\\ E \neq Y\\ N \neq D\\ N \neq M\\ N \neq O\\ N \neq R\\ N \neq Y\\ D \neq M\\ D \neq O\\ D \neq R\\ D \neq Y\\ M \neq O\\ M \neq R\\ M \neq Y\\ O \neq R\\ O \neq Y\\ R \neq Y \end{gather*}

Finally, we need to add final addition constraint:

    \begin{gather*} 1000S + 100E + 10N + D + 1000M + 100O + 10R + E = 10000M + 1000O + 100N + 10E + Y \end{gather*}

This approach leads us right to the solution. Easy.

Second solution

We can do this the long way by simulating long addition. We define variables in the same way as in previous solution, however, this time we add digits one by one. First, we add lowest digits:

    \begin{gather*} (D + E) \% 10 = Y \end{gather*}

We add D and E, divide the result by 10 and calculate the remainder. This remainder must be equal to Y.
Next, we add N and R. This time we need to include carry:

    \begin{gather*} \left(\left((D + E) / 10 \right) + N + R\right) \% 10 = E \end{gather*}

We carry on with this method to calculate other digits:

    \begin{gather*} \left(\left(\left(\left((D + E) / 10 \right) + N + R\right) / 10\right) + E + O\right) \% 10 = N\\ \left(\left(\left(\left(\left(\left((D + E) / 10 \right) + N + R\right) / 10\right) + E + O\right) / 10\right) + S + M\right) \% 10 = O\\ \left(\left(\left(\left(\left(\left((D + E) / 10 \right) + N + R\right) / 10\right) + E + O\right) / 10\right) + S + M\right) / 10 = M\\ \end{gather*}

This leads to the same solution, however, it is harder to read and a bit slower.

Summary

As we can see, quite often there are multiple ways to represent calculations in ILP. Generally we should stick to more declarative approach and just define the problem as in first solution, however, sometimes we are able to rewrite imperative solution almost with no changes to linear problems. In next few parts we will see how to implement more imperative constructs: we will implement basic data structure, use it to simulate non-deterministic Turing machine, and finally solve even more sophisticated riddles.