HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Solve 6 simultaneous equations for 8 variables puzzle with Java

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
equationswithjavasimultaneousforsolvevariablespuzzle

Problem

I came across this mathematical puzzle, where one really cool answer was a python script to brute force answers.

Here's my take, which is essentially a translation of that to Java:

```
public class TerribleMath {

public static void main(String[] args) {
findAndPrintSolutions(1, 20);
}

private static void findAndPrintSolutions(int from, int to) {
for (int a = from; a < to; a++) {
for (int b = from; b < to; b++) {
for (int c = from; c < to; c++) {
for (int d = from; d < to; d++) {
for (int e = from; e < to; e++) {
for (int f = from; f < to; f++) {
for (int g = from; g < to; g++) {
for (int h = from; h < to; h++) {
if (isSolution(a, b, c, d, e, f, g, h))
printSolution(new int[] { a, b, c, d, e, f, g, h });
}
}
}
}
}
}
}
}
}

private static boolean isSolution(int a, int b, int c, int d, int e, int f, int g, int h) {
if (a + b - 9 != 4)
return false;
if ((c - d) * e != 4)
return false;
if (f + g - h != 4)
return false;
if ((a + c) / f != 4)
return false;
if ((b - d) * g != 4)
return false;
if (9 - e - h != 4)
return false;
return true;
}

private static void printSolution(int[] variables) {
StringBuilder output = new StringBuilder();
for (int variable : variables) {
output.append(variable + ", ");
}
output.deleteCharAt(output.length() - 1);
output.deleteCharAt(output.length() - 1);
System.out.println(output.toString());

Solution

If willing to mix the solution checking logic into the candidate generation logic, we can do better if we drop the requirement that we brute force the entire answer.

private static void findAndPrintSolutions(int from, int to) {
    for (int a = from; a  b || b > to) {
            continue;
        }

        for (int c = from; c  f || f > to) {
                continue;
            }

            for (int d = from; d  e || e > to) {
                    continue;
                }

                // if (b - d) * g == 4
                int g = 4 / (b - d);
                if (from > g || g > to) {
                    continue;
                }

                // if 9 - e - h == 4
                int h = 5 - e;
                if (from > h || h > to) {
                    continue;
                }

                if (isSolution(a, b, c, d, e, f, g, h)) {
                    printSolution(new int[] { a, b, c, d, e, f, g, h });
                }
            }
        }
    }
}


This would drop us from 25,600,000,000 iterations of the innermost loop to 8000 with a modest increase in complexity per iteration. This works because the equations in the solution checker tell us constraints that we can use to determine some of the variables if we have others (comments in the code with more specific explanations). With sufficient algebra you might eliminate one of the remaining three loops as well. Note that we have an additional equation that we are not using (f + g - h == 4).

Added logic to verify that the calculated variables are within the from/to range. This doesn't seem to have been necessary for this particular problem, but that seems likely to have been just luck. I think that you could probably demonstrate that by setting from to 1 and to to 6.

Code Snippets

private static void findAndPrintSolutions(int from, int to) {
    for (int a = from; a < to; a++) {
        // if a + b - 9 == 4, then 
        int b = 13 - a;
        if (from > b || b > to) {
            continue;
        }

        for (int c = from; c < to; c++) {
            // if (a + c) / f == 4
            int f = (a + c) / 4;
            if (from > f || f > to) {
                continue;
            }

            for (int d = from; d < to; d++) {
                if (c == d || b == d) {
                    // these cause divide by zero errors later, so skip them
                    continue;
                }

                // if (c - d) * e == 4
                int e = 4 / (c - d);
                if (from > e || e > to) {
                    continue;
                }

                // if (b - d) * g == 4
                int g = 4 / (b - d);
                if (from > g || g > to) {
                    continue;
                }

                // if 9 - e - h == 4
                int h = 5 - e;
                if (from > h || h > to) {
                    continue;
                }

                if (isSolution(a, b, c, d, e, f, g, h)) {
                    printSolution(new int[] { a, b, c, d, e, f, g, h });
                }
            }
        }
    }
}

Context

StackExchange Code Review Q#126071, answer score: 7

Revisions (0)

No revisions yet.