24-point game is a common intellectual game, which can be played with cards without jokers. The rule is to draw four random cards and manipulate the four numbers to get the result 24 using four arithmetic operations: addition, subtraction, multiplication and division. In card playing, J, Q, K correspond numbers 11, 12 and 13 respectively.

With esProc, we can conveniently program the game, and calculate the result with the four random numbers:

Next, let’s analyze this block of code in detail.

The four numbers for computations are given in A1. First, to calculate the 24 points we should try all possible permutations of the four cards. To do this, we list the permutations, including those with the repeated numbers, in A2 using a four-digit quaternary number. In B2, we only select those without repeated numbers. They are as follows:

Three arithmetic operators need to be inserted into four numbers during the computation. Each one is selected arbitrarily from addition, subtraction, multiplication and division. Execute loop in A3 on a three-digit quaternary number to list all possible combinations:

As different computational orders lead to different computed results, we can adjust the order by adding parentheses in different ways. Three operators mean the computation can be performed in three steps, and different ways of adding parentheses decide the order of the execution of the three steps. B3 selects from the results of A3 the combinations that contain all three elements 1, 2, 3. They represent all possible orders for execution, as shown below:

Since there could be repeated numbers among the four randomly selected cards, we’ll list all permutations of cards in A4 and remove those repeated ones in B4 in order to avoid redundant loops. For the numbers [8,3,8,3] specified in A1, B4 lists permutations as follows:

For each permutation, the code in line 5 and line 6 tries every combination of arithmetic operators in every computational order by loop. To do this, the code calls A8’s subroutine, which uses copied parameters to avoid affecting the subsequent computations.

When calling the subroutine in A8, the sequence of numbers, the sequence of operators, and the sequence of computational orders should be entered respectively into A8, B8 and C8; besides, expression for computation should be entered in D8. B9 loops through the sequence of computational orders to compute the results step by step. C9 gets the result of one step by calling the subroutine in A13. The subroutine, which is quite simple, computes the result of a four arithmetic operation based on two given numbers and the operator in between. D9 aims at the expression for computing one step, after which the original two numbers become one. Then modify the sequence expressions, the sequence of operators and the sequence of numbers in E9, C10 and D10. After solving one step, the original number of computational steps decreases by one, and then we need to modify the sequence of computational order in E10 again. In line 11, unless it is the last step, parentheses need to be added to the newly-generated expression to ensure an appropriate computational order.

When the loop in B9 is over, the subroutine in A8 completes its computation of expression for one type of permutation with one combination of operators. B18 evaluates whether the result is 24. Considering the computational error of double-precision number, the result will be rounded to three decimal places. If the result equals 24, the current combination can meet the requirement and the expression will be put in B1 through C12.

After looping through all combinations, if no expression is found in B1 by looking at A7, then the problem has no solution.

After all the computations, result can be found in B1, as shown below:

Instead of entering a fixed permutation of numbers into A1, we can also use a cellset parameter by modifying A1’s code into **=arg1**:

Set the cellset parameter before doing computation:

The result displayed in B1 after computation is as follows: