I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

# Thursday Code Puzzler: Count To 24

05.30.2013
| 4555 views |

It's Thursday, so it's time for another code puzzler. The idea is simple: solve the coding problem as efficiently as you can, in any language or framework that you find suitable.

Note: Even though there really is nothing stopping you from finding a solution to this on the internet, try to keep honest, and come up with your own answer.  It's all about the participation!

Create 24

Create the number 24 using only these numbers once each: 3, 3, 7, 7. You may use only the following functions: +, -, *, /. This should be possible using whole numbers (no decimals)

Catch up on all our previous puzzlers here

Tags:

### Christian Rubiales replied on Thu, 2013/05/30 - 5:09am

```public class Test24 {

public static void main(String[] args) {
String[] o = {"+", "-", "/", "*"};
float[][] combinations = {{3,3,7,7},{3,7,3,7},{7,3,3,7},{7,3,7,3} ,{7,7,3,3},{3,7,7,3}};

float[] a;
float solution = 0;
for (int i = 0; i < combinations.length; i++) {
for (int j = 0; j < o.length; j++) {
for (int k = 0; k < o.length; k++) {
for (int x = 0; x < o.length; x++) {
a = combinations[i];

if (o[j].equals("+")) {
solution = a[0] + a[1];
} else if (o[j].equals("-")) {
solution = a[0] - a[1];
} else if (o[j].equals("/")) {
solution = a[0] / a[1];
} else if (o[j].equals("*")) {
solution = a[0] * a[1];
}

if (o[k].equals("+")) {
solution = solution + a[2];
} else if (o[k].equals("-")) {
solution = solution - a[2];
} else if (o[k].equals("/")) {
solution = solution / a[2];
} else if (o[k].equals("*")) {
solution = solution * a[2];
}

if (o[x].equals("+")) {
solution = solution + a[3];
} else if (o[x].equals("-")) {
solution = solution - a[3];
} else if (o[x].equals("/")) {
solution = solution / a[3];
} else if (o[x].equals("*")) {
solution = solution * a[3];
}
System.out.println(String.format("%f%s%f%s%f%s%f = %f", a[0], o[j], a[1], o[k], a[2], o[x], a[3], solution));

if (solution == 24) {
System.exit(0);
}
}
}
}
}
}
}
```

### Marko Kurm replied on Thu, 2013/05/30 - 8:52am

This is a bit longer, but it can do it for a variable length of numbers and operations.

```package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

public static void main(String[] args) {
List<List<Integer>> numberCombinations = new Combinations<Integer>(Arrays.asList(3, 3, 7, 7)).get();

for(List<Integer> combination : numberCombinations) {
generateOperations(combination);
}
}

private static List<String> generateOperations(List<Integer> numbers) {
List<String> result = new ArrayList<String>();
List<List<Operation>> operationCombinations = new Combinations<Operation>(Arrays.asList(Operation.PLUS, Operation.MINUS, Operation.MULTIPLY, Operation.DIVIDE)).get(3);

for(List<Operation> operations : operationCombinations) {
new Calculation(numbers, operations).calculate(24);
}

return result;
}

static class Combinations<T> {

private List<T> elements;

public Combinations(List<T> elements) {
this.elements = elements;
}

public List<List<T>> get() {
return getCombinations(elements);
}

public List<List<T>> get(int count) {
return getCombinations(count, elements);
}

private List<List<T>> getCombinations(int count, List<T> elements) {
List<List<T>> result = new ArrayList<List<T>>();

if (elements.size() == 1) {
} else {
for (final T object : elements) {
List<List<T>> integers = new ArrayList<List<T>>();

if (count == 1) {
} else {
for (List<T> nrList : getCombinations(count - 1, getSubList(elements, object))) {
List<T> newList = new ArrayList<T>();
}
}
}
}

return result;
}

private List<List<T>> getCombinations(List<T> elements) {
List<List<T>> result = new ArrayList<List<T>>();

if (elements.size() == 1) {
} else {
for (final T object : elements) {
List<List<T>> integers = new ArrayList<List<T>>();

for (List<T> nrList : getCombinations(getSubList(elements, object))) {
List<T> newList = new ArrayList<T>();
}

}
}

return result;
}

private List<T> getSubList(List<T> numbers, T object) {
List<T> copy = copy(numbers);
copy.remove(object);
return copy;
}

private List<T> copy(List<T> original) {
List<T> copy = new ArrayList<T>();
for (T i : original) {
}
return copy;
}

}

static class Calculation {
private List<Integer> arguments;
private List<Operation> operations;

public Calculation(List<Integer> arguments, List<Operation> operations) {
this.arguments = arguments;
this.operations = operations;

if(arguments.size() - operations.size() != 1) {
throw new IllegalArgumentException("Arguments list must be operations list + 1 in size");
}
}

public void calculate(int expected) {
Double value = calculateValue();
if(value == expected) {
throw new RuntimeException("Solution found: " + this);
}
}

@Override
public String toString() {
String calculation = arguments.get(0).toString();
for(int i = 0; i < operations.size(); i++) {
Operation operation = operations.get(i);
Integer argument = arguments.get(i + 1);
calculation = calculation + " " + operation + " " + argument;
}
return calculation + " = " + calculateValue() + "\n";
}

private Double calculateValue() {
Double sum = 0.0;
for(int i = 0; i < operations.size(); i++) {
if(i == 0) {
sum = new Double(arguments.get(0));
}

Operation operation = operations.get(i);
Double argument = new Double(arguments.get(i + 1));

if(operation == Operation.PLUS) {
sum = sum + argument;
} else if (operation == Operation.MINUS) {
sum = sum - argument;
} else if (operation == Operation.MULTIPLY) {
sum = sum * argument;
} else {
sum = sum / argument;
}
}
return sum;
}
}

static enum Operation {
PLUS,
MINUS,
MULTIPLY,
DIVIDE;

@Override
public String toString() {
if(this.equals(PLUS)) {
return "+";
} else if(this.equals(MINUS)) {
return "-";
} else if(this.equals(MULTIPLY)) {
return "*";
} else {
return "/";
}
}
}

}
```

### Tomasz Nurkiewicz replied on Thu, 2013/05/30 - 2:19pm

Can you reveal the answer? Not the solution but only answer? My program can't find it and two solutions in comments so far are incorrect (?) - using floating point arithmetic.

### sun east replied on Thu, 2013/05/30 - 10:02pm

```scala> new Poker24().solve(3, 3, 7, 7).foreach(println)
(3/7+3)*7
7*(3/7+3)
(3+3/7)*7
7*(3+3/7)```

### Marko Kurm replied on Fri, 2013/05/31 - 1:38am in response to: Tomasz Nurkiewicz

At some point in the calculation, the numbers will be floating point. But the end result will be exactly 24.

### Harald Wellmann replied on Sat, 2013/06/01 - 8:20am

(77-3)/3 = 24 with usual integer arithmetics (e.g. in Java). I didn't use a computer to find this solution.

### Oleksandr Alesinskyy replied on Wed, 2013/06/05 - 6:11am in response to: Harald Wellmann

77-3 is 74, not divisible  by 3, so your solution is wrong.

### W. Veldhuis replied on Wed, 2013/06/05 - 8:07am in response to: Harald Wellmann

"I didn't use a computer to find this solution."

We can see that :)

### Michael Glassman replied on Wed, 2013/06/05 - 8:25am

Derivation of the solution without a computer:

1. Since 3 + 3 + 7 + 7 only comes to 20, the solution involves either multiplication or the apposition of two digits (i.e., 33) or both.
2. Including 33, 37, 73, or 77 in the solution doesn't reveal an obvious path to 24, though.
3. If addition or subtraction were the final step, then we'd need to use the other digits to get to 17, 21, 27, or 31; no obvious solution is evident for any of these.
4. So the last step is multiplication or division, and it only takes a few moments to realize that the last step is not division by 3 or 7.
5. If the last step were muliplication by 3, we'd need to make 8 from 3, 7, and 7, which is also not possible.
6. Therefore, the only remaining possibility is to multiply by 7 in the last step, which seems counter-intuitive since 24 isn't evenly divisible by 7.
7. Nevertheless, when on realizes that 24 / 7 = 3 3/7, then the solution is obvious:
3 / 7 + 3 * 7 = 24
Note: this answer depends on doing operations from left to right, not algebraically. Alternatively, this could be written as (3 / 7 + 3) * 7.

### Robert Sharouty replied on Wed, 2013/06/05 - 9:15am

```class Create24{
int[] a = {3, 3, 7 ,7};
int sum;

private void calculate() {
for (int i : a) {
sum += i;
}
sum += a.length;
System.out.println(sum);
}

public static void main(String[] args) {
new Create24().calculate();
}
}Summing 3, 3 , 7 , 7 in a for loop and using the array.length as a replacement for number 4.
```

### Kevin Berg replied on Wed, 2013/06/05 - 12:27pm in response to: Oleksandr Alesinskyy

It depends on how you interpret requirements, especially the last statement "This should be possible using whole numbers (no decimals)". I believe integer math meets those requirements, or the requirements need to be re-stated. Otherwise you are reading things into the requirements that are not there.
```scala> (77-3)/3
res4: Int = 24```

### Bean Duke replied on Wed, 2013/06/05 - 12:50pm

Harald Wellmann's solution is corret - just try it in Java Compiler

### Andrew Carlson replied on Wed, 2013/06/05 - 5:21pm

ANSI SQL

`SELECT CAST ((77-3)/3 AS INT)`

Returns

---------------

24

(1 row (s) affected)

### Andrew Carlson replied on Wed, 2013/06/05 - 5:10pm in response to: Oleksandr Alesinskyy

You can divide 74 by 3.

The only number you cannot divide is 0.

### Oleksandr Alesinskyy replied on Thu, 2013/06/06 - 4:06am

Yes, his solution is correct  - I somehow missed that he mentioned "e.g. in Java".

Note, that the Java definition of an "integer arithmetic" is not the only possible one. In other definitions a division result may be 25 (as a reminder is 2 in this case, which is nearer to 3 than to 0).

### Andreas Lundberg replied on Thu, 2013/06/06 - 3:28am

Here is my implementation:

It contains a main in the bottom of the file and the constructor calls the solve method. Enjoy!

```/**
*
*/
package no.andreas.katas.twentyfourpoker;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

/**
* @author Andreas Lundberg
*
*/
public class TwentyFourPoker {

enum OPERATOR {

public String operatorString;

OPERATOR(final String operatorString) {

this.operatorString = operatorString;
}

public static OPERATOR getRandomOperator() {

OPERATOR operator = null;
switch (new Random().nextInt(4) + 1) {
case 1:
break;
case 2:
operator = OPERATOR.SUBTRACT;
break;
case 3:
operator = OPERATOR.MULTIPLY;
break;
case 4:
operator = OPERATOR.DIVIDE;
break;

default:
throw new RuntimeException("No operator available");
}
return operator;
}
}

int loopCounter = 0;

long maxNumberOfItterations = 1000;

double expectedSolution = 24.0d;

double bestDelta = Double.MAX_VALUE;

List<Integer> involvedNumbers = new ArrayList<Integer>();

public TwentyFourPoker() {

solve();
}

public void solve() {

while (true) {
if (loopCounter >= maxNumberOfItterations) {
System.out.println(String.format(
"I ran for %d itterations, but could not find the answer!", loopCounter));
break;
}
loopCounter++;
String[] mathStrings = generateCalculationString();
double sum = eval(mathStrings);
double delta = Math.abs(expectedSolution - sum);
if (delta < bestDelta) {
bestDelta = delta;
System.out.println(join(mathStrings) + " = " + sum + " with delta = " + bestDelta);
if (bestDelta == 0.0d) {
System.out.println(String.format("Solution accomplished after %d itterations!",
loopCounter));
break;
}
}
}

}

private double eval(final String[] mathStrings) {

double sum = 0.0d;
for (int i = 0; i < mathStrings.length; i++) {

String mathString = mathStrings[i];
if (i > 0) {
mathString = sum + mathString;
}
sum = eval(mathString);
}
return sum;
}

private double eval(final String mathString) {

double sum = 0.0d;
try {
String eval = String.valueOf(new ScriptEngineManager().getEngineByName("JavaScript")
.eval(mathString));

sum = Double.valueOf(eval).doubleValue();
} catch (ScriptException e) {
e.printStackTrace();
}
return sum;
}

private String[] generateCalculationString() {

Collections.shuffle(involvedNumbers);
String[] mathString = new String[] { "", "", "", "" };
for (int i = 0; i < involvedNumbers.size(); i++) {
if (i > 0) {
String op = OPERATOR.getRandomOperator().operatorString;
int val = involvedNumbers.get(i);
int selectedIndex = new Random().nextInt(i + 1);
mathString[selectedIndex] = mathString[selectedIndex] + op + val;
} else {

mathString[i] = involvedNumbers.get(i) + "";
}
}
return mathString;
}

public String join(final String[] strings) {

String joined = "";
for (String string : strings) {
if (string.trim().length() > 0) {

joined += "(" + string + ")";
}
}

return joined;
}

public static void main(final String[] args) {

new TwentyFourPoker();
}
}
```

### Andreas Lundberg replied on Thu, 2013/06/06 - 4:19am in response to: Andreas Lundberg

Challenge: Rewrite this in Groovy and refator down to a minimum number of lines.

Is it possible to get it down to 10 %? 16 lines, where it is still humanly readable and contains all logic?

### K Hyland replied on Thu, 2013/06/06 - 7:39am

Answer in python. Note I'm new to python so probably could write this a lot more efficiently. I'd be interested in any improvements people can suggest. Using python itertools to do the heavy lifting and generate all permutations of numbers, and product to get all permutations of operators (which can repeat). Then loop through them til we get the answer (256 * 6 permutations).

```import itertools
''' Find out how to calculate target from given numbers '''
Nums = [3,3,7,7]
Ops = ["+", "-", "*","/"] # Add, subtract, multiply, divide
Target = 24

def calc(nums, ops, target):
for opList in itertools.product(ops, repeat=len(nums)):
for numList in set(itertools.permutations(nums)):	# Set reduces number by factor of 4 here.
eqn = ""
for num in range(len(numList)):
eqn += str(numList[num])+opList[num]
numIter = iter(numList)
sol = float(numIter.next())
num = numIter.next()
i=0
# Note inital version just have eval(eqn) below.. but because of precedence rules this doesn't work (3/7+3*7) = (3/7)+(3*7)
# Now it calculates left to right regardless of precedence rules
# Also crazy behaviour before round was introduced (sol = 23.99999999 was not equal 24... Needed to round)
while(num):
sol = eval(str(sol)+opList[i]+str(float(num)))
i+=1
try:
num = numIter.next()
except StopIteration:
num=None
if(round(sol)==round(target)):
return (eqn[0:-1])

print calc(Nums, Ops, Target),"=",Target```

### Philippe Lhoste replied on Fri, 2013/06/07 - 8:03am

Let see. The aggregation trick doesn't seem to be fitting the requirements. They say : "using these numbers", not "using these digits"! Otherwise, it would be a mathematical puzzle, not a code puzzle!

Likewise, "no decimals" seems to exclude the floating point tricks.

I appreciate Michael Glassman's reasoning, except I fail to see how 3 / 7 + 3 * 7 = 24
Using integer arithmetic (like in Java, for example), 3/7 should be zero. Perhaps it was intended to be 3 % 7? Or the programming language giving this result should be explicitly specified... :-)

Robert Sharouty's solution is the best to my eyes (short, understandable, fitting the rules, nice trick). :-D

### Michael Glassman replied on Fri, 2013/06/07 - 9:03am in response to: Philippe Lhoste

Thank you, Philippe, for the kind mention about the process I used to find an arithmetical solution. I know that this Code Puzzler was posted in the Java forum, but James wrote two things that made me think that floating point arithmetic could be used:

1. "...solve the coding problem as efficiently as you can, in any language or framework that you find suitable." I took this to mean that the solution wasn't restricted to Java.
2. "This should be possible using whole numbers (no decimals)." To me, "no decimals" meant "no numbers with decimal points," such as 3.7. I don't think it precludes an intermediate step from being a rational number.

Under these assumptions, 3/7 is not zero. Adding 3 gives 24/7, and multiplying by 7 equals 24.

Mike

### Oleksandr Alesinskyy replied on Fri, 2013/06/07 - 9:42am in response to: Michael Glassman

As for me "no decimals" means no decimals elsewhere - neither in results nor in the intermediate steps.

### Philippe Lhoste replied on Fri, 2013/06/07 - 2:28pm in response to: Michael Glassman

Yes, I don't think these code puzzlers are limited to Java, that's why I wrote you should indicate which language would work. For example, JavaScript (which doesn't has real integers).

I was confused by the lack of parentheses (and unusual way of evaluating the expression), despite your sentence following the formula. I failed to understand it, even if it makes sense afterward. I blame my lack of attention / understanding.

And about the interpretation of the rules, I blame the imprecise specifications, I wouldn't like to do a real program based on them! :-)

### David Brouse replied on Wed, 2013/06/26 - 2:06pm

I apologize because this response is a bit long, but I spent a lot of time on the solution.

This problem derives from a math competition for elementary school students.  Two teams are shown the same four integers and compete to be the first team to supply the operators between the numbers that will produce the answer 24.

This is a challenging coding problem, because different answers result from how the terms are combined (eg. (2 * 3) + (6 * 5) is not equal to 2 * (3 + 6) * 5 even though the numbers are in the same order, and have the same operations between them).

I decided to solve this problem generically for any set of four integers.  The big issue was how to handle the problem with parentheses.  The answer is Postfix Notation (or Reverse Polish Notation - RPN) .  The expressions in the above example are written in infix notation (which is the most familiar way we view and write arithmetic expressions).  However, a parenthesized infix expression can be written in postfix notation without the need for parentheses.  For example, the expression "2 * (3 + 6) * 5" in infix notation would be written in postfix notation as "3 6 + 2 * 5 *".  A postfix notation solver can be easily written in any programming language using a stack structure.

In this code puzzler there are four numbers supplied, so only three operations can be placed between them.  In postfix notation, it turns out that there are only five possible combinations of four numbers and three operations (NNONONO, NNNOONO, NNNNOOO, NNONNOO, and NNNONOO).

Knowing the combinations in postfix notation, it was easy to write nested loops to brute force every combination of the four numbers and the four operations to fill all of the templates.

There are 24 ways to order the four numbers.  There are 64 ways to put  four operations between the 24 numbers, and five postfix patterns to fill for a total of 7,680 combinations for each set of four numbers.

As an FYI, there are four unique solutions to the set of numbers (3, 3, 7, 7).  Here are the solutions output by my code:

• (3 + (3 / 7)) * 7
• ((3 / 7) + 3) * 7
• 7 * ((3 / 7) + 3)
• 7 * (3 + (3 / 7))

As a side note, it's unlikely that that combination of numbers would show up at a competition.  The solutions typically have intermediate steps that result in whole numbers.  It would be difficult for elementary school students to divide 3 by 7 in their heads. :)

Here are my two classes -- the PostfixExpression class and the CountTo24 class:

```import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
* This is a simple class that represents an expression in postfix
* notation (or RPN - Reverse Polish Notation). Given a String
* of terms in postfix notation separated by spaces, this class
* can solution the expression or return the expression in infix
* notation (the format that most people find easiest to read).
*
* The class uses a stack to solution the expression (implemented
* with a Java LinkedList) whereby numbers and operations are
* pushed and popped to perform the calculations.
*/
public class PostfixExpression {
private final String postfixExpression;

public PostfixExpression(String postfixExpression) {
this.postfixExpression = postfixExpression;
}
public String toInfixExpression() {
String[] terms = postfixExpression.split("\\s");
Set operators = new HashSet(Arrays.asList(new String[] {"+", "-", "*", "/"}));
for (String term : terms) {
if (operators.contains(term)) {
String operand1 = stack.pop();
String operand2 = stack.pop();
String newOperand = "(" + operand2 + " " + term + " " + operand1 +")";
stack.push(newOperand);
} else {
stack.push(term);
}
}
String infixExpression = stack.pop();
// Remove the extraneous beginning and ending parentheses
return infixExpression.substring(1, infixExpression.length() - 1);
}

/**
* Solve the postfix notation expression
* NOTE: Only add, subtract, multiply, and divide
* operations are supported.
*
* @return a double representing the solution to the
*         postfix notation expression
*/
public double solution() {
String[] terms = postfixExpression.split("\\s");

for (String term : terms) {
if (term.equals("+")) {
double operand1 = stack.pop();
double operand2 = stack.pop();
stack.push(operand2 + operand1);
} else if (term.equals("-")) {
double operand1 = stack.pop();
double operand2 = stack.pop();
stack.push(operand2 - operand1);
} else if (term.equals("*")) {
double operand1 = stack.pop();
double operand2 = stack.pop();
stack.push(operand2 * operand1);
} else if (term.equals("/")) {
double operand1 = stack.pop();
double operand2 = stack.pop();
stack.push(operand2 / operand1);
} else {
stack.push(Double.parseDouble(term));
}
}
return stack.pop();
}
}
```
```import java.util.HashSet;
import java.util.Set;

/**
* Count To 24: Four integers are supplied, and any one or
* more of the four operations add, subtract, multiply, and
* divide must be used on all four of the integers to
*
* For example:
*    The integers 5, 2, 6, 3 could be combined with
*    the multiply and subtract operators to produce the
*    answer 24 in the following way: (2 * 6) * (5 - 3) = 24
*/
public class CountTo24 {
String[] operators = new String[] {"+", "-", "*", "/"};

public static void main(String[] args) {
CountTo24 countTo24 = new CountTo24();
int[] operands = new int[] {3, 3, 7, 7};
Set results = countTo24.solveFor24(operands);
for (String result : results) {
System.out.println(result);
}
}

public Set solveFor24(int[] operands) {
Set resultSet = new HashSet();
PostfixExpression postfixExpression;
String[] postfixPatterns = new String[] {"NNONONO", "NNNOONO", "NNNNOOO", "NNONNOO", "NNNONOO"};
for (int num1 = 0; num1 < operands.length; num1 ++) {
for (int num2 = 0; num2 < operands.length; num2++) {
if (num2 != num1) {
for (int num3 = 0; num3 < operands.length; num3++) {
if (num3 != num1 && num3 != num2) {
for (int num4 = 0; num4 < operands.length; num4 ++) {
if (num4 != num1 && num4 != num2 && num4 != num3) {
for (String op1 : operators) {
for (String op2 : operators) {
for (String op3 : operators) {
int[] nums = new int[] {operands[num1], operands[num2], operands[num3], operands[num4]};
String[] ops = new String[] {op1, op2, op3};
for (String postfixPattern : postfixPatterns) {
postfixExpression = buildPostfixExpressionFromPattern(postfixPattern, nums, ops);
determineResult(resultSet, postfixExpression);
}
}
}
}
}
}
}
}
}
}
}
return resultSet;
}

private void determineResult(Set resultSet, PostfixExpression postfixExpression) {
try {
if (postfixExpression.solution() == 24.0d) {
}
} catch (Exception e) {
// Ignore any math errors such as divide by zero.
}
}

private PostfixExpression buildPostfixExpressionFromPattern(String pattern, int[] nums, String[] ops) {
StringBuilder rpnEquation = new StringBuilder();
int numCounter = 0;
int opCounter = 0;
for (int i = 1; i <= pattern.length(); i++) {
if (pattern.substring(i - 1, i).equals("N")) {
rpnEquation.append(nums[numCounter++]);
} else {
rpnEquation.append(ops[opCounter++]);
}
if (i != pattern.length()) {
rpnEquation.append(" ");
}
}
return new PostfixExpression(rpnEquation.toString());
}
}
```

### Andreas Lundberg replied on Thu, 2013/06/27 - 2:45am in response to: David Brouse

The scary thing with this piece of code is the nested for loops.

There are up to 9 of them  at worst.

Creates a very high complexity.