Search for arithmetic operations that result in 24

I am writing a program that evaluates the integer values โ€‹โ€‹of 4 playing cards (numbers 1-13) and displays a solution of 24. I have a big if statement that I wrote for this, and realized that there are too many solutions to add all of them . I am looking for advice on how to condensate this into a more optimized version. The code works fine, no errors, here is my whole code:

import javafx.application.Application; import javafx.event.ActionEvent; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.image.Image; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.layout.Pane; import javafx.stage.Stage; import javafx.scene.image.ImageView; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.concurrent.atomic.AtomicReference; import java.util.*; public class Main extends Application { private Card card1; private Card card2; private Card card3; private Card card4; private int a; private int b; private int c; private int d; private int e=0; private int f=0; boolean par=false; @Override public void start(Stage primaryStage) { ArrayList<Integer> deck; deck = new ArrayList<>(); int i = 1; while(i < 52){ deck.add(i); i++; } final AtomicReference<String> result = new AtomicReference<>(""); Collections.shuffle(deck); BorderPane pane = new BorderPane(); HBox top = new HBox(10); Label display = new Label(result.toString()); Button btShuffle = new Button("Shuffle"); Button fiSolution = new Button("Find Solution"); TextField solfield = new TextField(); VBox bottomBox = new VBox(); top.getChildren().add(fiSolution); top.getChildren().add(solfield); top.getChildren().add(btShuffle); HBox center = new HBox(10); card1 = new Card(deck.get(0)); center.getChildren().add(card1); card2 = new Card(deck.get(1)); center.getChildren().add(card2); card3 = new Card(deck.get(3)); center.getChildren().add(card3); card4 = new Card(deck.get(4)); center.getChildren().add(card4); //String str1 = solfield.setText(); fiSolution.setOnAction( (ActionEvent e) -> { a = card1.CardValue(); b = card2.CardValue(); c = card3.CardValue(); d = card4.CardValue(); if (a+b+c+d == 24) solfield.setText(a+"+"+b+"+"+c+"+"+d); else if (a+b+cd == 24) solfield.setText(a+"+"+b+"+"+c+"-"+d); else if (a-b+c+d == 24) solfield.setText(a+"+-"+b+"+"+c+"+"+d); else if (a+b-c+d == 24) solfield.setText(a+"+"+b+"-"+c+"+"+d); else if ((((a+b)-c)*d)==24) solfield.setText(a+"+"+b+"-"+c+"*"+d); else if ((((a+b)-c)/d)==24) solfield.setText(a+"+"+b+"-"+c+"/"+d); else if ((((a+b)/c)-d)==24) solfield.setText(a+"+"+b+"/"+c+"-"+d); else if ((((a+b)/c)*d)==24) solfield.setText(a+"+"+b+"/"+c+"*"+d); else if ((((a+b)*c)/d)==24) solfield.setText(a+"+"+b+"*"+c+"/"+d); else if ((((a+b)*c)-d)==24) solfield.setText(a+"+"+b+"*"+c+"-"+d); else if ((((ab)+c)*d)==24) solfield.setText(a+"-"+b+"+"+c+"*"+d); else if ((((ab)+c)/d)==24) solfield.setText(a+"-"+b+"+"+c+"/"+d); else if ((((ab)/c)+d)==24) solfield.setText(a+"-"+b+"/"+c+"+"+d); else if ((((ab)/c)*d)==24) solfield.setText(a+"-"+b+"/"+c+"*"+d); else if ((((ab)*c)/d)==24) solfield.setText(a+"-"+b+"*"+c+"/"+d); else if ((((ab)*c)+d)==24) solfield.setText(a+"-"+b+"*"+c+"+"+d); else if ((((a*b)+c)/d)==24) solfield.setText(a+"*"+b+"+"+c+"/"+d); else if ((((a*b)+c)-d)==24) solfield.setText(a+"*"+b+"+"+c+"-"+d); else if ((((a*b)-c)/d)==24) solfield.setText(a+"*"+b+"-"+c+"/"+d); else if ((((a*b)-c)+d)==24) solfield.setText(a+"*"+b+"-"+c+"+"+d); else if ((((a*b)/c)+d)==24) solfield.setText(a+"*"+b+"/"+c+"+"+d); else if ((((a*b)/c)-d)==24) solfield.setText(a+"*"+b+"/"+c+"-"+d); else if ((((a/b)+c)*d)==24) solfield.setText(a+"/"+b+"+"+c+"*"+d); else if ((((a/b)+c)-d)==24) solfield.setText(a+"/"+b+"+"+c+"-"+d); else if ((((a/b)-c)+d)==24) solfield.setText(a+"/"+b+"-"+c+"+"+d); else if ((((a/b)-c)*d)==24) solfield.setText(a+"/"+b+"-"+c+"*"+d); else if ((((a/b)*c)-d)==24) solfield.setText(a+"/"+b+"*"+c+"-"+d); else if ((((a/b)*c)+d)==24) solfield.setText(a+"/"+b+"*"+c+"+"+d); f=c+d; if (((a/b)*f)==24) solfield.setText(a+"/"+b+"*("+c+"+"+d+")"); else if (((a/b)-f)==24) solfield.setText(a+"/"+b+"-("+c+"+"+d+")"); else if (((a*b)-f)==24) solfield.setText(a+"*"+b+"-("+c+"+"+d+")"); else if (((a*b)/f)==24) solfield.setText(a+"*"+b+"/("+c+"+"+d+")"); else if (((ab)*f)==24) solfield.setText(a+"-"+b+"*("+c+"+"+d+")"); else if (((ab)/f)==24) solfield.setText(a+"-"+b+"/("+c+"+"+d+")"); f=cd; if (((a/b)*f)==24) solfield.setText(a+"/"+b+"*("+c+"-"+d+")"); else if (((a/b)+f)==24) solfield.setText(a+"/"+b+"+("+c+"-"+d+")"); else if (((a*b)+f)==24) solfield.setText(a+"*"+b+"+("+c+"-"+d+")"); else if (((a*b)/f)==24) solfield.setText(a+"*"+b+"/("+c+"-"+d+")"); else if (((a+b)*f)==24) solfield.setText(a+"+"+b+"*("+c+"-"+d+")"); else if (((a+b)/f)==24) solfield.setText(a+"+"+b+"/("+c+"-"+d+")"); f=c*d; if (((a/b)-f)==24) solfield.setText(a+"/"+b+"*("+c+"*"+d+")"); else if (((a/b)+f)==24) solfield.setText(a+"/"+b+"+("+c+"*"+d+")"); else if (((ab)+f)==24) solfield.setText(a+"-"+b+"+("+c+"*"+d+")"); else if (((ab)/f)==24) solfield.setText(a+"-"+b+"/("+c+"*"+d+")"); else if (((a+b)-f)==24) solfield.setText(a+"+"+b+"-("+c+"*"+d+")"); else if (((a+b)/f)==24) solfield.setText(a+"+"+b+"/("+c+"*"+d+")"); f=c/d; if (((ab)*f)==24) solfield.setText(a+"-"+b+"*("+c+"/"+d+")"); else if (((ab)+f)==24) solfield.setText(a+"-"+b+"+("+c+"/"+d+")"); else if (((a*b)+f)==24) solfield.setText(a+"*"+b+"+("+c+"/"+d+")"); else if (((a*b)-f)==24) solfield.setText(a+"*"+b+"-("+c+"/"+d+")"); else if (((a+b)*f)==24) solfield.setText(a+"+"+b+"*("+c+"/"+d+")"); else if (((a+b)-f)==24) solfield.setText(a+"+"+b+"-("+c+"/"+d+")"); f=b*c; if (((af)/d)==24) solfield.setText(a+"-("+b+"*"+c+")/"+d); else if (((af)+d)==24) solfield.setText(a+"-("+b+"*"+c+")+"+d); else if (((a/f)+d)==24) solfield.setText(a+"/("+b+"*"+c+")+"+d); else if (((a/f)-d)==24) solfield.setText(a+"/("+b+"*"+c+")-"+d); else if (((a+f)/d)==24) solfield.setText(a+"+("+b+"*"+c+")/"+d); else if (((a+f)-d)==24) solfield.setText(a+"+("+b+"*"+c+")-"+d); f=bc; if (((a*f)/d)==24) solfield.setText(a+"*("+b+"-"+c+")/"+d); else if (((a*f)+d)==24) solfield.setText(a+"*("+b+"-"+c+")+"+d); else if (((a/f)+d)==24) solfield.setText(a+"/("+b+"-"+c+")+"+d); else if (((a/f)*d)==24) solfield.setText(a+"/("+b+"-"+c+")*"+d); f=b/c; if (((af)*d)==24) solfield.setText(a+"-("+b+"/"+c+")*"+d); else if (((af)+d)==24) solfield.setText(a+"-("+b+"/"+c+")+"+d); else if (((a*f)+d)==24) solfield.setText(a+"*("+b+"/"+c+")+"+d); else if (((a*f)-d)==24) solfield.setText(a+"*("+b+"/"+c+")-"+d); else if (((a+f)*d)==24) solfield.setText(a+"+("+b+"/"+c+")*"+d); else if (((a+f)-d)==24) solfield.setText(a+"+("+b+"/"+c+")-"+d); f=b+c; if (((a*f)/d)==24) solfield.setText(a+"*("+b+"+"+c+")/"+d); else if (((a*f)-d)==24) solfield.setText(a+"*("+b+"+"+c+")-"+d); else if (((a/f)-d)==24) solfield.setText(a+"/("+b+"+"+c+")-"+d); else if (((a/f)*d)==24) solfield.setText(a+"/("+b+"+"+c+")*"+d); }); btShuffle.setOnAction( e -> { center.getChildren().clear(); Collections.shuffle(deck); card1 = new Card(deck.get(0)); card2 = new Card(deck.get(1)); card3 = new Card(deck.get(2)); card4 = new Card(deck.get(3)); center.getChildren().add(card1); center.getChildren().add(card2); center.getChildren().add(card3); center.getChildren().add(card4); }); HBox bottom = new HBox(10); Label expression = new Label("Please Enter the expression: "); TextField tfExpress = new TextField(); String str = tfExpress.getText(); Button btVerify = new Button("Verify"); bottom.getChildren().add(expression); bottom.getChildren().add(tfExpress); bottom.getChildren().add(btVerify); bottomBox.getChildren().add(bottom); bottomBox.getChildren().add(display); btVerify.setOnAction( (ActionEvent e) -> { String regex = ("[^0-9]+"); String[] inputIntegers = tfExpress.getText().split(regex); // expInput.removeIf(p-> p.equals(signs)); ArrayList<Integer> temp = new ArrayList<>(); temp.add(new Integer(card1.CardValue())); temp.add(new Integer(card2.CardValue())); temp.add(new Integer(card3.CardValue())); temp.add(new Integer(card4.CardValue())); if(inputIntegers.length != 0) { if (inputIntegers.length != 0) { for (String s : inputIntegers) { if (!s.equals("")) temp.remove(new Integer(Integer.valueOf(s))); } } } if(temp.isEmpty()) { if(evaluateExpression(tfExpress.getText()) == 24){ display.setText("Correct"); } else display.setText("Incorrect"); } else display.setText("The numbers in the expression don't " + "match the numbers in the set."); }); pane.setTop(top); pane.setCenter(center); pane.setBottom(bottomBox); Scene scene = new Scene(pane); primaryStage.setTitle("24 card game"); primaryStage.setScene(scene); primaryStage.show(); } public boolean Twentyfour(boolean par){ //some people play the game with or without parentheses. this.par=par; return par; } /** Evaluate an expression */ public static int evaluateExpression(String expression) { // Create operandStack to store operands Stack<Integer> operandStack = new Stack<Integer>(); // Create operatorStack to store operators Stack<Character> operatorStack = new Stack<Character>(); // Insert blanks around (, ), +, -, /, and * expression = insertBlanks(expression); // Extract operands and operators String[] tokens = expression.split(" "); // Phase 1: Scan tokens for (String token: tokens) { if (token.length() == 0) // Blank space continue; // Back to the while loop to extract the next token else if (token.charAt(0) == '+' || token.charAt(0) == '-') { // Process all +, -, *, / in the top of the operator stack while (!operatorStack.isEmpty() && (operatorStack.peek() == '+' || operatorStack.peek() == '-' || operatorStack.peek() == '*' || operatorStack.peek() == '/')) { processAnOperator(operandStack, operatorStack); } // Push the + or - operator into the operator stack operatorStack.push(token.charAt(0)); } else if (token.charAt(0) == '*' || token.charAt(0) == '/') { // Process all *, / in the top of the operator stack while (!operatorStack.isEmpty() && (operatorStack.peek() == '*' || operatorStack.peek() == '/')) { processAnOperator(operandStack, operatorStack); } // Push the * or / operator into the operator stack operatorStack.push(token.charAt(0)); } else if (token.trim().charAt(0) == '(') { operatorStack.push('('); // Push '(' to stack } else if (token.trim().charAt(0) == ')') { // Process all the operators in the stack until seeing '(' while (operatorStack.peek() != '(') { processAnOperator(operandStack, operatorStack); } operatorStack.pop(); // Pop the '(' symbol from the stack } else { // An operand scanned // Push an operand to the stack operandStack.push(new Integer(token)); } } // Phase 2: process all the remaining operators in the stack while (!operatorStack.isEmpty()) { processAnOperator(operandStack, operatorStack); } // Return the result return operandStack.pop(); } /** Process one operator: Take an operator from operatorStack and * apply it on the operands in the operandStack */ public static void processAnOperator( Stack<Integer> operandStack, Stack<Character> operatorStack) { char op = operatorStack.pop(); int op1 = operandStack.pop(); int op2 = operandStack.pop(); if (op == '+') operandStack.push(op2 + op1); else if (op == '-') operandStack.push(op2 - op1); else if (op == '*') operandStack.push(op2 * op1); else if (op == '/') operandStack.push(op2 / op1); } public static String insertBlanks(String s) { String result = ""; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '(' || s.charAt(i) == ')' || s.charAt(i) == '+' || s.charAt(i) == '-' || s.charAt(i) == '*' || s.charAt(i) == '/') result += " " + s.charAt(i) + " "; else result += s.charAt(i); } return result; } public class Card extends Pane { public int cardVal; Card(int card){ Image cardImage; cardImage = new Image("card/"+ card +".png"); getChildren().add(new ImageView(cardImage)); cardVal = card; } public int CardValue(){ int card = 0; if(cardVal <= 13){ card = cardVal; } else if(cardVal > 13 && cardVal <= 26){ card = cardVal - 13; } else if(cardVal > 26 && cardVal <= 39){ card = cardVal - 26; } else if(cardVal > 39 && cardVal <= 52){ card = cardVal - 39; } return card; } } public static void main(String[] args) { launch(args); } } 
+6
source share
3 answers

Enum can help here.

Iโ€™m not sure that everything worked out for me, because Iโ€™m not sure that I realized all the possible bracketing, but now it looks complete.

 enum Op { Add("+") { @Override int op(int a, int b) { return a + b; } }, Sub("-") { @Override int op(int a, int b) { return a - b; } }, Mul("*") { @Override int op(int a, int b) { return a * b; } }, Div("/") { @Override int op(int a, int b) { // Insane value for / 0 to ensure unlikely to match. return b != 0 ? a / b : Integer.MAX_VALUE; } }; final String asString; Op(String asString) { this.asString = asString; } public String toString() { return asString; } abstract int op(int a, int b); } private void tryAllOrders(int a, int b, int c, int d, Op op1, Op op2, Op op3, int target) { if (op3.op(op2.op(op1.op(a, b), c), d) == target) { System.out.println(" ((" + a + op1 + b + ")" + op2 + c + ")" + op3 + d + "=" + target); } if (op3.op(op1.op(a, op2.op(b, c)), d) == target) { System.out.println(" (" + a + op1 + "(" + b + op2 + c + "))" + op3 + d + "=" + target); } if (op2.op(op1.op(a, b), op3.op(c, d)) == target) { System.out.println(" (" + a + op1 + b + ")" + op2 + "(" + c + op3 + d + ")=" + target); } if (op1.op(a, op3.op(op2.op(b, c), d)) == target) { System.out.println(" " + a + op1 + "((" + b + op2 + c + ")" + op3 + d + ")=" + target); } if (op1.op(a, op2.op(b, op3.op(c, d))) == target) { System.out.println(" " + a + op1 + "(" + b + op2 + "(" + c + op3 + d + "))=" + target); } } private void tryAllOps(int a, int b, int c, int d, int target) { for (Op op1 : Op.values()) { for (Op op2 : Op.values()) { for (Op op3 : Op.values()) { tryAllOrders(a, b, c, d, op1, op2, op3, target); } } } } public void test() { int target = 24; for (int a = 1; a <= 13; a++) { for (int b = 1; b <= 13; b++) { for (int c = 1; c <= 13; c++) { for (int d = 1; d <= 13; d++) { tryAllOps(a, b, c, d, target); } } } } } 

He prints:

 ((1+1)+1)*8=24 (1+(1+1))*8=24 (1+1)*(1+11)=24 ((1+1)*1)*12=24 (1+(1*1))*12=24 (1+1)*(1*12)=24 ... 7+((11*8)/5)=24 ((7+11)*8)/6=24 ((7-11)+8)*6=24 (7-(11-8))*6=24 ((7+11)/8)*12=24 (7/(11-8))*12=24 ... ((13/13)*13)+11=24 (13/13)*(13+11)=24 (13/(13/13))+11=24 ((13+13)/13)*12=24 (13-(13/13))+12=24 13-((13/13)-12)=24 

Overall result of 67,752 .

+4
source

Ah, combinatorics!

First of all, do one calculation manually: How many combinations are there?

  • Each variable can be used only once.
  • The order of the variables matters (this can be considered as brackets)
  • Between each variable there is a mathematical operation, one of + - * / , each operation can be used more than once.

Four variables, ordered, create \ $ 4! = 4 * 3 * 2 * 1 = 24 \ $.

Various mathematical operations create combinations \ $ 4 ^ 3 = 64 \ $.

The result is a combination of \ $ 64 * 24 = 1536 \ $. This is not too much, so gross coercion is acceptable.

One approach:

This is a recursive way to select a variable and an operator and add it to the result.

Please note that this is just an approximate approach and has not been tested, it will require some adjustments to make it work correctly.

 void result(List<Variable> remaining, List<Variable> used, List<Operator> operatorsUsed, int current) { for (Variable variable : remaining) { for (Operator operation : operators) { int newValue = operation.perform(current, variable.getValue()); List<Variable> copy = new ArrayList<>(variables); copy.remove(variable); List<Operator> usedOps = new ArrayList<>(operatorsUsed); usedOps.add(operation); int result = result(copy, newValue); if (result == 24) { solfield.setText(createString(used, operatorsUsed)); } } } } 
+2
source

9216 different equations - 6 points for parentheses (taking into account 1 b 2 c 3 d, operations are performed in 6 different orders), 64 (4x4x4) different cases of operators and 24 different orders of numbers.

Obviously, you cannot write them manually.

However, you can manually define each of these classes and have three for-loops loops, each of which iterates through the list of operations.

For actual implementation, I believe that the strategy of the strategy would be better, since it allows you to divide the problem into small pieces.

... This is a brute force decision, although I think there should be something better ...

0
source

Source: https://habr.com/ru/post/986674/


All Articles