/*** HACKED TO RUN IN JAVA, Original code by Carl Johansen as listed below ***/ //////////////////////////////////////////////////////////////////// /// fourfours.cs /// © 2005 Carl Johansen /// /// Simple program for solving the Four Fours puzzle //////////////////////////////////////////////////////////////////// class FourFoursSolver { private static float Operate(float lhs, float rhs, int operation, boolean blnAbort) { blnAbort = false; switch (operation) { case 0: return lhs + rhs; case 1: return lhs - rhs; case 2: float res = 0; try { return lhs * rhs; } catch (Exception err) { blnAbort = true; return 0; } case 3: if (rhs < 0.001) { blnAbort = true; return 0; } else return lhs / rhs; case 4: try { return (float)Math.pow(lhs, rhs); } catch (Exception err) { blnAbort = true; return 0; } default: return -9999; } } static private String OperatorSymbol(int operation) { switch (operation) { case 0: return "+"; case 1: return "-"; case 2: return "*"; case 3: return "/"; case 4: return "^"; default: return "unknown operator!"; } } static private String ExpressionForDisplay(String[] arrTermsDisp, byte[] termIndex, int[] operations, String[] separators) { //combines the expression's operators and operands using the specified separator characters // (white spaces and round brackets) to create a string for display return separators[0] + arrTermsDisp[termIndex[0]].toString() + separators[1] + OperatorSymbol(operations[0]) + separators[2] + arrTermsDisp[termIndex[1]].toString() + separators[3] + OperatorSymbol(operations[1]) + separators[4] + arrTermsDisp[termIndex[2]].toString() + separators[5] + OperatorSymbol(operations[2]) + separators[6] + arrTermsDisp[termIndex[3]].toString() + separators[7]; } public static void main(String[] args) { final int NUM_OPERATORS = 5, NUM_TERMS = 6; int intCurrResult, intCurrResultScore, intIterations = 0; long datStartTime = System.currentTimeMillis(); float decCurrResult = 0, decTempResult = 0; byte step; boolean blnAbort; int[] operations = new int[3]; float[] arrTerms = { 4, 2, 24, 4.0F / 10.0F, 4.0F / 9.0F, 2.0F / 3.0F, 0, 0 }; String[] arrTermsDisp = { "4", "sqrt(4)", "4!", ".4", ".4bar", "sqrt(.4bar)" }; int[] arrTermScore = { 50, 40, 30, 20, 10, 1 }; // used to give preference to "simpler" answers // There are four possible groupings. // { 0, 0, 1 } means apply operator #0 to operand #0 and operand #1 and call the result "operand #4" // { 2, 2, 3 } means apply operator #2 to operand #2 and operand #3 and call the result "operand #5" // { 4, 1, 5 } means apply operator #1 to operand #4 and operand #5. This is the overall result byte[][][] expression = { { { 0, 0, 1 }, { 2, 2, 3 }, { 4, 1, 5 } }, // ( A x B ) x ( C x D ) { { 0, 0, 1 }, { 4, 1, 2 }, { 5, 2, 3 } }, // ( ( A x B ) x C ) x D { { 1, 1, 2 }, { 0, 0, 4 }, { 5, 2, 3 } }, // ( A x ( B x C ) ) x D { { 2, 2, 3 }, { 1, 1, 4 }, { 0, 0, 5 } } }; // A x ( B x ( C x D ) ) byte[] termIndex = { 0, 0, 0, 0, NUM_TERMS, NUM_TERMS + 1 }; String[] arrAnswer = new String[101]; int[] arrBestAnswerScore = new int[101]; boolean[] seenResult = new boolean[101]; // go through all possible operator/operand combinations for (int association = 0; association < 4; association++) //There are four ways of applying precedence to the operators for (termIndex[0] = 0; termIndex[0] < NUM_TERMS; termIndex[0]++) for (termIndex[1] = 0; termIndex[1] < NUM_TERMS; termIndex[1]++) for (termIndex[2] = 0; termIndex[2] < NUM_TERMS; termIndex[2]++) for (termIndex[3] = 0; termIndex[3] < NUM_TERMS; termIndex[3]++) for (operations[0] = 0; operations[0] < NUM_OPERATORS; operations[0]++) for (operations[1] = 0; operations[1] < NUM_OPERATORS; operations[1]++) for (operations[2] = 0; operations[2] < NUM_OPERATORS; operations[2]++) { intIterations++; for (step = 0, blnAbort = false; step <= 2 && !blnAbort; step++) { decTempResult = Operate(arrTerms[termIndex[expression[association][step][0]]], arrTerms[termIndex[expression[association][step][2]]], operations[expression[association][step][1]], blnAbort); if (!blnAbort) switch (step) { case 0: arrTerms[NUM_TERMS] = decTempResult; break; case 1: arrTerms[NUM_TERMS + 1] = decTempResult; break; case 2: decCurrResult = decTempResult; break; } } if (!blnAbort && decCurrResult >= 1 && decCurrResult <= 100 && Math.abs((intCurrResult = (int)(decCurrResult)) - (float)decCurrResult) < 0.0000001) { intCurrResultScore = arrTermScore[termIndex[0]] + arrTermScore[termIndex[1]] + arrTermScore[termIndex[2]] + arrTermScore[termIndex[3]]; if (intCurrResultScore > arrBestAnswerScore[intCurrResult]) { //This looks like the most attractive answer we have seen so far for intCurrResult arrBestAnswerScore[intCurrResult] = intCurrResultScore; switch (association) { case 0: arrAnswer[intCurrResult] = ExpressionForDisplay(arrTermsDisp, termIndex, operations, new String[] { "(", " ", " ", ") ", " (", " ", " ", ")" }); break; case 1: arrAnswer[intCurrResult] = ExpressionForDisplay(arrTermsDisp, termIndex, operations, new String[] { "( (", " ", " ", ") ", " ", ") ", " ", "" }); break; case 2: arrAnswer[intCurrResult] = ExpressionForDisplay(arrTermsDisp, termIndex, operations, new String[] { "", " ", " (", " ", " ", ") ", " ", "" }); break; case 3: arrAnswer[intCurrResult] = ExpressionForDisplay(arrTermsDisp, termIndex, operations, new String[] { "", "", " (", "", " (", "", "", ") )" }); break; default: break; } } if (!seenResult[intCurrResult]) seenResult[intCurrResult] = true; } } for (int i = 1; i <= 100; i++) System.out.println(i + " = " + arrAnswer[i]); System.out.println("Done. (" + intIterations + " loop iterations)"); System.out.println("Elapsed time: " + (System.currentTimeMillis() - datStartTime) + " milliseconds"); //Console.ReadLine(); } }