⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.

{{task}}

;task: Write a program that takes four digits, either from user input or by random generation, and computes arithmetic expressions following the rules of the [[24 game]].

Show examples of solutions generated by the program.

;Related task:

  • [[Arithmetic Evaluator]]

ABAP

Will generate all possible solutions of any given four numbers according to the rules of the 24 game.

Note: the permute function was locally from [[Permutations#ABAP|here]]

data: lv_flag type c,
      lv_number type i,
      lt_numbers type table of i.

constants: c_no_val type i value 9999.

append 1 to lt_numbers.
append 1 to lt_numbers.
append 2 to lt_numbers.
append 7 to lt_numbers.

write 'Evaluating 24 with the following input: '.
loop at lt_numbers into lv_number.
  write lv_number.
endloop.
perform solve_24 using lt_numbers.

form eval_formula using iv_eval type string changing ev_out type i.
  call function 'EVAL_FORMULA' "analysis of a syntactically correct formula
    exporting
      formula = iv_eval
    importing
      value   = ev_out
    exceptions
   others     = 1.

  if sy-subrc <> 0.
    ev_out = -1.
  endif.
endform.

" Solve a 24 puzzle.
form solve_24 using it_numbers like lt_numbers.
  data: lv_flag   type c,
        lv_op1    type c,
        lv_op2    type c,
        lv_op3    type c,
        lv_var1   type c,
        lv_var2   type c,
        lv_var3   type c,
        lv_var4   type c,
        lv_eval   type string,
        lv_result type i,
        lv_var     type i.

  define retrieve_var.
    read table it_numbers index &1 into lv_var.
    &2 = lv_var.
  end-of-definition.

  define retrieve_val.
    perform eval_formula using lv_eval changing lv_result.
    if lv_result = 24.
        write / lv_eval.
    endif.
  end-of-definition.
  " Loop through all the possible number permutations.
  do.
    " Init. the operations table.

    retrieve_var: 1 lv_var1, 2 lv_var2, 3 lv_var3, 4 lv_var4.
    do 4 times.
      case sy-index.
        when 1.
          lv_op1 = '+'.
        when 2.
          lv_op1 = '*'.
        when 3.
          lv_op1 = '-'.
        when 4.
          lv_op1 = '/'.
      endcase.
      do 4 times.
        case sy-index.
        when 1.
          lv_op2 = '+'.
        when 2.
          lv_op2 = '*'.
        when 3.
          lv_op2 = '-'.
        when 4.
          lv_op2 = '/'.
        endcase.
        do 4 times.
          case sy-index.
          when 1.
            lv_op3 = '+'.
          when 2.
            lv_op3 = '*'.
          when 3.
            lv_op3 = '-'.
          when 4.
            lv_op3 = '/'.
          endcase.
          concatenate '(' '(' lv_var1 lv_op1 lv_var2 ')' lv_op2 lv_var3 ')' lv_op3 lv_var4  into lv_eval separated by space.
          retrieve_val.
          concatenate '(' lv_var1 lv_op1 lv_var2 ')' lv_op2 '(' lv_var3 lv_op3 lv_var4 ')'  into lv_eval separated by space.
          retrieve_val.
          concatenate '(' lv_var1 lv_op1 '(' lv_var2 lv_op2 lv_var3 ')' ')' lv_op3 lv_var4  into lv_eval separated by space.
          retrieve_val.
          concatenate lv_var1 lv_op1 '(' '(' lv_var2 lv_op2 lv_var3 ')' lv_op3 lv_var4 ')'  into lv_eval separated by space.
          retrieve_val.
          concatenate lv_var1 lv_op1 '(' lv_var2 lv_op2 '(' lv_var3 lv_op3 lv_var4 ')' ')'  into lv_eval separated by space.
          retrieve_val.
        enddo.
      enddo.
    enddo.

    " Once we've reached the last permutation -> Exit.
    perform permute using it_numbers changing lv_flag.
    if lv_flag = 'X'.
      exit.
    endif.
  enddo.
endform.


" Permutation function - this is used to permute:
" A = {A1...AN} -> Set of supplied variables.
" B = {B1...BN - 1} -> Set of operators.
" Can be used for an unbounded size set. Relies
" on lexicographic ordering of the set.
form permute using iv_set like lt_numbers
             changing ev_last type c.
  data: lv_len     type i,
        lv_first   type i,
        lv_third   type i,
        lv_count   type i,
        lv_temp    type i,
        lv_temp_2  type i,
        lv_second  type i,
        lv_changed type c,
        lv_perm    type i.
  describe table iv_set lines lv_len.

  lv_perm = lv_len - 1.
  lv_changed = ' '.
  " Loop backwards through the table, attempting to find elements which
  " can be permuted. If we find one, break out of the table and set the
  " flag indicating a switch.
  do.
    if lv_perm <= 0.
      exit.
    endif.
    " Read the elements.
    read table iv_set index lv_perm into lv_first.
    add 1 to lv_perm.
    read table iv_set index lv_perm into lv_second.
    subtract 1 from lv_perm.
    if lv_first < lv_second.
      lv_changed = 'X'.
      exit.
    endif.
    subtract 1 from lv_perm.
  enddo.

  " Last permutation.
  if lv_changed <> 'X'.
    ev_last = 'X'.
    exit.
  endif.

  " Swap tail decresing to get a tail increasing.
  lv_count = lv_perm + 1.
  do.
    lv_first = lv_len + lv_perm - lv_count + 1.
    if lv_count >= lv_first.
      exit.
    endif.

    read table iv_set index lv_count into lv_temp.
    read table iv_set index lv_first into lv_temp_2.
    modify iv_set index lv_count from lv_temp_2.
    modify iv_set index lv_first from lv_temp.
    add 1 to lv_count.
  enddo.

  lv_count = lv_len - 1.
  do.
    if lv_count <= lv_perm.
      exit.
    endif.

    read table iv_set index lv_count into lv_first.
    read table iv_set index lv_perm into lv_second.
    read table iv_set index lv_len into lv_third.
    if ( lv_first < lv_third ) and ( lv_first > lv_second ).
      lv_len = lv_count.
    endif.

    subtract 1 from lv_count.
  enddo.

  read table iv_set index lv_perm into lv_temp.
  read table iv_set index lv_len into lv_temp_2.
  modify iv_set index lv_perm from lv_temp_2.
  modify iv_set index lv_len from lv_temp.
endform.

Sample Runs:

Evaluating 24 with the following input:  1 1 2 7
( 1 + 2 ) * ( 1 + 7 )
( 1 + 2 ) * ( 7 + 1 )
( 1 + 7 ) * ( 1 + 2 )
( 1 + 7 ) * ( 2 + 1 )
( 2 + 1 ) * ( 1 + 7 )
( 2 + 1 ) * ( 7 + 1 )
( 7 + 1 ) * ( 1 + 2 )
( 7 + 1 ) * ( 2 + 1 )

Evaluating 24 with the following input:  1
( ( 1 + 2 ) + 3 ) * 4
( 1 + ( 2 + 3 ) ) * 4
( ( 1 * 2 ) * 3 ) * 4
( 1 * 2 ) * ( 3 * 4 )
( 1 * ( 2 * 3 ) ) * 4
1 * ( ( 2 * 3 ) * 4 )
1 * ( 2 * ( 3 * 4 ) )
( ( 1 * 2 ) * 4 ) * 3
( 1 * 2 ) * ( 4 * 3 )
( 1 * ( 2 * 4 ) ) * 3
1 * ( ( 2 * 4 ) * 3 )
1 * ( 2 * ( 4 * 3 ) )
( ( 1 + 3 ) + 2 ) * 4
( 1 + ( 3 + 2 ) ) * 4
( 1 + 3 ) * ( 2 + 4 )
( ( 1 * 3 ) * 2 ) * 4
( 1 * 3 ) * ( 2 * 4 )
( 1 * ( 3 * 2 ) ) * 4
1 * ( ( 3 * 2 ) * 4 )
1 * ( 3 * ( 2 * 4 ) )
( 1 + 3 ) * ( 4 + 2 )
( ( 1 * 3 ) * 4 ) * 2
( 1 * 3 ) * ( 4 * 2 )
( 1 * ( 3 * 4 ) ) * 2
1 * ( ( 3 * 4 ) * 2 )
1 * ( 3 * ( 4 * 2 ) )
( ( 1 * 4 ) * 2 ) * 3
( 1 * 4 ) * ( 2 * 3 )
( 1 * ( 4 * 2 ) ) * 3
1 * ( ( 4 * 2 ) * 3 )
1 * ( 4 * ( 2 * 3 ) )
( ( 1 * 4 ) * 3 ) * 2
( 1 * 4 ) * ( 3 * 2 )
( 1 * ( 4 * 3 ) ) * 2
1 * ( ( 4 * 3 ) * 2 )
1 * ( 4 * ( 3 * 2 ) )
( ( 2 + 1 ) + 3 ) * 4
( 2 + ( 1 + 3 ) ) * 4
( ( 2 * 1 ) * 3 ) * 4
( 2 * 1 ) * ( 3 * 4 )
( 2 * ( 1 * 3 ) ) * 4
2 * ( ( 1 * 3 ) * 4 )
2 * ( 1 * ( 3 * 4 ) )
( ( 2 / 1 ) * 3 ) * 4
( 2 / 1 ) * ( 3 * 4 )
( 2 / ( 1 / 3 ) ) * 4
2 / ( 1 / ( 3 * 4 ) )
2 / ( ( 1 / 3 ) / 4 )
( ( 2 * 1 ) * 4 ) * 3
( 2 * 1 ) * ( 4 * 3 )
( 2 * ( 1 * 4 ) ) * 3
2 * ( ( 1 * 4 ) * 3 )
2 * ( 1 * ( 4 * 3 ) )
( ( 2 / 1 ) * 4 ) * 3
( 2 / 1 ) * ( 4 * 3 )
( 2 / ( 1 / 4 ) ) * 3
2 / ( 1 / ( 4 * 3 ) )
2 / ( ( 1 / 4 ) / 3 )
( ( 2 + 3 ) + 1 ) * 4
( 2 + ( 3 + 1 ) ) * 4
( ( 2 * 3 ) * 1 ) * 4
( 2 * 3 ) * ( 1 * 4 )
( 2 * ( 3 * 1 ) ) * 4
2 * ( ( 3 * 1 ) * 4 )
2 * ( 3 * ( 1 * 4 ) )
( ( 2 * 3 ) / 1 ) * 4
( 2 * ( 3 / 1 ) ) * 4
2 * ( ( 3 / 1 ) * 4 )
( 2 * 3 ) / ( 1 / 4 )
2 * ( 3 / ( 1 / 4 ) )
( ( 2 * 3 ) * 4 ) * 1
( 2 * 3 ) * ( 4 * 1 )
( 2 * ( 3 * 4 ) ) * 1
2 * ( ( 3 * 4 ) * 1 )
2 * ( 3 * ( 4 * 1 ) )
( ( 2 * 3 ) * 4 ) / 1
( 2 * 3 ) * ( 4 / 1 )
( 2 * ( 3 * 4 ) ) / 1
2 * ( ( 3 * 4 ) / 1 )
2 * ( 3 * ( 4 / 1 ) )
( 2 + 4 ) * ( 1 + 3 )
( ( 2 * 4 ) * 1 ) * 3
( 2 * 4 ) * ( 1 * 3 )
( 2 * ( 4 * 1 ) ) * 3
2 * ( ( 4 * 1 ) * 3 )
2 * ( 4 * ( 1 * 3 ) )
( ( 2 * 4 ) / 1 ) * 3
( 2 * ( 4 / 1 ) ) * 3
2 * ( ( 4 / 1 ) * 3 )
( 2 * 4 ) / ( 1 / 3 )
2 * ( 4 / ( 1 / 3 ) )
( 2 + 4 ) * ( 3 + 1 )
( ( 2 * 4 ) * 3 ) * 1
( 2 * 4 ) * ( 3 * 1 )
( 2 * ( 4 * 3 ) ) * 1
2 * ( ( 4 * 3 ) * 1 )
2 * ( 4 * ( 3 * 1 ) )
( ( 2 * 4 ) * 3 ) / 1
( 2 * 4 ) * ( 3 / 1 )
( 2 * ( 4 * 3 ) ) / 1
2 * ( ( 4 * 3 ) / 1 )
2 * ( 4 * ( 3 / 1 ) )
( ( 3 + 1 ) + 2 ) * 4
( 3 + ( 1 + 2 ) ) * 4
( 3 + 1 ) * ( 2 + 4 )
( ( 3 * 1 ) * 2 ) * 4
( 3 * 1 ) * ( 2 * 4 )
( 3 * ( 1 * 2 ) ) * 4
3 * ( ( 1 * 2 ) * 4 )
3 * ( 1 * ( 2 * 4 ) )
( ( 3 / 1 ) * 2 ) * 4
( 3 / 1 ) * ( 2 * 4 )
( 3 / ( 1 / 2 ) ) * 4
3 / ( 1 / ( 2 * 4 ) )
3 / ( ( 1 / 2 ) / 4 )
( 3 + 1 ) * ( 4 + 2 )
( ( 3 * 1 ) * 4 ) * 2
( 3 * 1 ) * ( 4 * 2 )
( 3 * ( 1 * 4 ) ) * 2
3 * ( ( 1 * 4 ) * 2 )
3 * ( 1 * ( 4 * 2 ) )
( ( 3 / 1 ) * 4 ) * 2
( 3 / 1 ) * ( 4 * 2 )
( 3 / ( 1 / 4 ) ) * 2
3 / ( 1 / ( 4 * 2 ) )
3 / ( ( 1 / 4 ) / 2 )
( ( 3 + 2 ) + 1 ) * 4
( 3 + ( 2 + 1 ) ) * 4
( ( 3 * 2 ) * 1 ) * 4
( 3 * 2 ) * ( 1 * 4 )
( 3 * ( 2 * 1 ) ) * 4
3 * ( ( 2 * 1 ) * 4 )
3 * ( 2 * ( 1 * 4 ) )
( ( 3 * 2 ) / 1 ) * 4
( 3 * ( 2 / 1 ) ) * 4
3 * ( ( 2 / 1 ) * 4 )
( 3 * 2 ) / ( 1 / 4 )
3 * ( 2 / ( 1 / 4 ) )
( ( 3 * 2 ) * 4 ) * 1
( 3 * 2 ) * ( 4 * 1 )
( 3 * ( 2 * 4 ) ) * 1
3 * ( ( 2 * 4 ) * 1 )
3 * ( 2 * ( 4 * 1 ) )
( ( 3 * 2 ) * 4 ) / 1
( 3 * 2 ) * ( 4 / 1 )
( 3 * ( 2 * 4 ) ) / 1
3 * ( ( 2 * 4 ) / 1 )
3 * ( 2 * ( 4 / 1 ) )
( ( 3 * 4 ) * 1 ) * 2
( 3 * 4 ) * ( 1 * 2 )
( 3 * ( 4 * 1 ) ) * 2
3 * ( ( 4 * 1 ) * 2 )
3 * ( 4 * ( 1 * 2 ) )
( ( 3 * 4 ) / 1 ) * 2
( 3 * ( 4 / 1 ) ) * 2
3 * ( ( 4 / 1 ) * 2 )
( 3 * 4 ) / ( 1 / 2 )
3 * ( 4 / ( 1 / 2 ) )
( ( 3 * 4 ) * 2 ) * 1
( 3 * 4 ) * ( 2 * 1 )
( 3 * ( 4 * 2 ) ) * 1
3 * ( ( 4 * 2 ) * 1 )
3 * ( 4 * ( 2 * 1 ) )
( ( 3 * 4 ) * 2 ) / 1
( 3 * 4 ) * ( 2 / 1 )
( 3 * ( 4 * 2 ) ) / 1
3 * ( ( 4 * 2 ) / 1 )
3 * ( 4 * ( 2 / 1 ) )
4 * ( ( 1 + 2 ) + 3 )
4 * ( 1 + ( 2 + 3 ) )
( ( 4 * 1 ) * 2 ) * 3
( 4 * 1 ) * ( 2 * 3 )
( 4 * ( 1 * 2 ) ) * 3
4 * ( ( 1 * 2 ) * 3 )
4 * ( 1 * ( 2 * 3 ) )
( ( 4 / 1 ) * 2 ) * 3
( 4 / 1 ) * ( 2 * 3 )
( 4 / ( 1 / 2 ) ) * 3
4 / ( 1 / ( 2 * 3 ) )
4 / ( ( 1 / 2 ) / 3 )
4 * ( ( 1 + 3 ) + 2 )
4 * ( 1 + ( 3 + 2 ) )
( ( 4 * 1 ) * 3 ) * 2
( 4 * 1 ) * ( 3 * 2 )
( 4 * ( 1 * 3 ) ) * 2
4 * ( ( 1 * 3 ) * 2 )
4 * ( 1 * ( 3 * 2 ) )
( ( 4 / 1 ) * 3 ) * 2
( 4 / 1 ) * ( 3 * 2 )
( 4 / ( 1 / 3 ) ) * 2
4 / ( 1 / ( 3 * 2 ) )
4 / ( ( 1 / 3 ) / 2 )
( 4 + 2 ) * ( 1 + 3 )
4 * ( ( 2 + 1 ) + 3 )
4 * ( 2 + ( 1 + 3 ) )
( ( 4 * 2 ) * 1 ) * 3
( 4 * 2 ) * ( 1 * 3 )
( 4 * ( 2 * 1 ) ) * 3
4 * ( ( 2 * 1 ) * 3 )
4 * ( 2 * ( 1 * 3 ) )
( ( 4 * 2 ) / 1 ) * 3
( 4 * ( 2 / 1 ) ) * 3
4 * ( ( 2 / 1 ) * 3 )
( 4 * 2 ) / ( 1 / 3 )
4 * ( 2 / ( 1 / 3 ) )
( 4 + 2 ) * ( 3 + 1 )
4 * ( ( 2 + 3 ) + 1 )
4 * ( 2 + ( 3 + 1 ) )
( ( 4 * 2 ) * 3 ) * 1
( 4 * 2 ) * ( 3 * 1 )
( 4 * ( 2 * 3 ) ) * 1
4 * ( ( 2 * 3 ) * 1 )
4 * ( 2 * ( 3 * 1 ) )
( ( 4 * 2 ) * 3 ) / 1
( 4 * 2 ) * ( 3 / 1 )
( 4 * ( 2 * 3 ) ) / 1
4 * ( ( 2 * 3 ) / 1 )
4 * ( 2 * ( 3 / 1 ) )
4 * ( ( 3 + 1 ) + 2 )
4 * ( 3 + ( 1 + 2 ) )
( ( 4 * 3 ) * 1 ) * 2
( 4 * 3 ) * ( 1 * 2 )
( 4 * ( 3 * 1 ) ) * 2
4 * ( ( 3 * 1 ) * 2 )
4 * ( 3 * ( 1 * 2 ) )
( ( 4 * 3 ) / 1 ) * 2
( 4 * ( 3 / 1 ) ) * 2
4 * ( ( 3 / 1 ) * 2 )
( 4 * 3 ) / ( 1 / 2 )
4 * ( 3 / ( 1 / 2 ) )
4 * ( ( 3 + 2 ) + 1 )
4 * ( 3 + ( 2 + 1 ) )
( ( 4 * 3 ) * 2 ) * 1
( 4 * 3 ) * ( 2 * 1 )
( 4 * ( 3 * 2 ) ) * 1
4 * ( ( 3 * 2 ) * 1 )
4 * ( 3 * ( 2 * 1 ) )
( ( 4 * 3 ) * 2 ) / 1
( 4 * 3 ) * ( 2 / 1 )
( 4 * ( 3 * 2 ) ) / 1
4 * ( ( 3 * 2 ) / 1 )
4 * ( 3 * ( 2 / 1 ) )

Evaluating 24 with the following input:  5 6 7 8
5 * ( 6 - ( 8 / 7 ) )
( 5 + 7 ) * ( 8 - 6 )
( ( 5 + 7 ) - 8 ) * 6
( 5 + ( 7 - 8 ) ) * 6
( ( 5 - 8 ) + 7 ) * 6
( 5 - ( 8 - 7 ) ) * 6
6 * ( ( 5 + 7 ) - 8 )
6 * ( 5 + ( 7 - 8 ) )
6 * ( ( 5 - 8 ) + 7 )
6 * ( 5 - ( 8 - 7 ) )
6 * ( ( 7 + 5 ) - 8 )
6 * ( 7 + ( 5 - 8 ) )
( 6 / ( 7 - 5 ) ) * 8
6 / ( ( 7 - 5 ) / 8 )
6 * ( ( 7 - 8 ) + 5 )
6 * ( 7 - ( 8 - 5 ) )
( 6 * 8 ) / ( 7 - 5 )
6 * ( 8 / ( 7 - 5 ) )
( 6 - ( 8 / 7 ) ) * 5
( 7 + 5 ) * ( 8 - 6 )
( ( 7 + 5 ) - 8 ) * 6
( 7 + ( 5 - 8 ) ) * 6
( ( 7 - 8 ) + 5 ) * 6
( 7 - ( 8 - 5 ) ) * 6
( 8 - 6 ) * ( 5 + 7 )
( 8 * 6 ) / ( 7 - 5 )
8 * ( 6 / ( 7 - 5 ) )
( 8 - 6 ) * ( 7 + 5 )
( 8 / ( 7 - 5 ) ) * 6
8 / ( ( 7 - 5 ) / 6 )

```



## Argile

{{works with|Argile|1.0.0}}

```Argile
die "Please give 4 digits as argument 1\n" if argc < 2

print a function that given four digits argv[1] subject to the rules of	\
the _24_ game, computes an expression to solve the game if possible.

use std, array

let digits    be an array of 4 byte
let operators be an array of 4 byte
(: reordered arrays :)
let (type of digits)    rdigits
let (type of operators) roperators

.: a function that given four digits  subject to
   the rules of the _24_ game, computes an expression to solve
   the game if possible.                                       :. -> text
  if #digits != 4 {return "[error: need exactly 4 digits]"}
  operators[0] = '+' ; operators[1] = '-'
  operators[2] = '*' ; operators[3] = '/'
  for each (val int d) from 0 to 3
    if (digits[d] < '1') || (digits[d] > '9')
      return "[error: non-digit character given]"
    (super digits)[d] = digits[d]
  let expr = for each operand order stuff
  return "" if expr is nil
  expr

.:for each operand order stuff:. -> text
  for each (val int a) from 0 to 3
    for each (val int b) from 0 to 3
      next if (b == a)
      for each (val int c) from 0 to 3
        next if (c == b) or (c == a)
	for each (val int d) from 0 to 3
	  next if (d == c) or (d == b) or (d == a)
	  rdigits[0] = digits[a] ; rdigits[1] = digits[b]
	  rdigits[2] = digits[c] ; rdigits[3] = digits[d]
	  let found = for each operator order stuff
	  return found unless found is nil
  nil

.:for each operator order stuff:. -> text
  for each (val int i) from 0 to 3
    for each (val int j) from 0 to 3
      for each (val int k) from 0 to 3
        roperators[0] = operators[i]
	roperators[1] = operators[j]
	roperators[2] = operators[k]
	let found = for each RPN pattern stuff
	return found if found isn't nil
  nil

our (raw array of text) RPN_patterns = Cdata
  "xx.x.x."
  "xx.xx.."
  "xxx..x."
  "xxx.x.."
  "xxxx..."
our (raw array of text) formats = Cdata
  "((%c%c%c)%c%c)%c%c"
  "(%c%c%c)%c(%c%c%c)"
  "(%c%c(%c%c%c))%c%c"
  "%c%c((%c%c%c)%c%c)"
  "%c%c(%c%c(%c%c%c))"
our (raw array of array of 3 int) rrop = Cdata
  {0;1;2}; {0;2;1}; {1;0;2}; {2;0;1}; {2;1;0}

.:for each RPN pattern stuff:. -> text
  let RPN_stack be an array of 4 real
  for each (val int rpn) from 0 to 4
    let (nat) sp=0, op=0, dg=0.
    let text p
    for (p = RPN_patterns[rpn]) (*p != 0) (p++)
      if *p == 'x'
        if sp >= 4 {die "RPN stack overflow\n"}
	if dg >  3 {die "RPN digits overflow\n"}
	RPN_stack[sp++] = (rdigits[dg++] - '0') as real
      if *p == '.'
        if sp < 2 {die "RPN stack underflow\n"}
	if op > 2 {die "RPN operators overflow\n"}
	sp -= 2
	let x = RPN_stack[sp]
	let y = RPN_stack[sp + 1]
	switch roperators[op++]
	  case '+' {x += y}
	  case '-' {x -= y}
	  case '*' {x *= y}
	  case '/' {x /= y}
	  default  {die "RPN operator unknown\n"}
	RPN_stack[sp++] = x
    if RPN_stack[0] == 24.0
      our array of 12 byte buffer (: 4 paren + 3 ops + 4 digits + null :)
      snprintf (buffer as text) (size of buffer) (formats[rpn])		\
         (rdigits[0]) (roperators[(rrop[rpn][0])]) (rdigits[1])		\
                      (roperators[(rrop[rpn][1])]) (rdigits[2])		\
                      (roperators[(rrop[rpn][2])]) (rdigits[3]);
      return buffer as text
  nil
```

Examples:

```txt
$ arc 24_game_solve.arg -o 24_game_solve.c
$ gcc -Wall 24_game_solve.c -o 24_game_solve
$ ./24_game_solve 1234
((1+2)+3)*4
$ ./24_game_solve 9999

$ ./24_game_solve 5678
((5+7)-8)*6
$ ./24_game_solve 1127
(1+2)*(1+7)
```



## AutoHotkey

{{works with|AutoHotkey_L}}
Output is in RPN.

```AHK
#NoEnv
InputBox, NNNN       ; user input 4 digits
NNNN := RegExReplace(NNNN, "(\d)(?=\d)", "$1,") ; separate with commas for the sort command
sort NNNN, d`, ; sort in ascending order for the permutations to work
StringReplace NNNN, NNNN, `,, , All ; remove comma separators after sorting

ops := "+-*/"
patterns := [	 "x x.x.x."
		,"x x.x x.."
		,"x x x..x."
		,"x x x.x.."
		,"x x x x..."	]

; build bruteforce operator list ("+++, ++-, ++* ... ///")
a := b := c := 0
While (++a<5){
 While (++b<5){
  While (++c<5){
   l := SubStr(ops, a, 1) . SubStr(ops, b, 1) . SubStr(ops, c, 1)

   ; build bruteforce template ("x x+x+x+, x x+x x++ ... x x x x///")
   For each, pattern in patterns
   {
      Loop 3
         StringReplace, pattern, pattern, ., % SubStr(l, A_Index, 1)
      pat .= pattern "`n"
   }
  }c := 0
 }b := 0
}
StringTrimRight, pat, pat, 1 ; remove trailing newline


; permutate input. As the lexicographic algorithm is used, each permutation generated is unique
While NNNN
{
	StringSplit, N, NNNN
	; substitute numbers in for x's and evaluate
	Loop Parse, pat, `n
	{
		eval := A_LoopField ; current line
		Loop 4
			StringReplace, eval, eval, x, % N%A_Index% ; substitute number for "x"
		If Round(evalRPN(eval), 4) = 24
			final .= eval "`n"
	}
	NNNN := perm_next(NNNN) ; next lexicographic permutation of user's digits
}
MsgBox % final ? clipboard := final : "No solution"

; simple stack-based evaluation. Integers only. Whitespace is used to push a value.
evalRPN(s){
	stack := []
	Loop Parse, s
		If A_LoopField is number
			t .= A_LoopField
		else
		{
			If t
				stack.Insert(t), t := ""
			If InStr("+-/*", l := A_LoopField)
			{
				a := stack.Remove(), b := stack.Remove()
				stack.Insert(	 l = "+" ? b + a
						:l = "-" ? b - a
						:l = "*" ? b * a
						:l = "/" ? b / a
						:0	)
			}
		}
	return stack.Remove()
}



perm_Next(str){
	p := 0, sLen := StrLen(str)
	Loop % sLen
	{
		If A_Index=1
			continue
		t := SubStr(str, sLen+1-A_Index, 1)
		n := SubStr(str, sLen+2-A_Index, 1)
		If ( t < n )
		{
			p := sLen+1-A_Index, pC := SubStr(str, p, 1)
			break
		}
	}
	If !p
		return false
	Loop
	{
		t := SubStr(str, sLen+1-A_Index, 1)
		If ( t > pC )
		{
			n := sLen+1-A_Index, nC := SubStr(str, n, 1)
			break
		}
	}
	return SubStr(str, 1, p-1) . nC . Reverse(SubStr(str, p+1, n-p-1) . pC .  SubStr(str, n+1))
}

Reverse(s){
	Loop Parse, s
		o := A_LoopField o
	return o
}
```

{{out}}for 1127:

```txt

1 2+1 7+*
1 2+7 1+*
1 7+1 2+*
1 7+2 1+*
2 1+1 7+*
2 1+7 1+*
7 1+1 2+*
7 1+2 1+*
```

And for 8338:

```txt
8 3 8 3/-/
```



## BBC BASIC


```bbcbasic

      PROCsolve24("1234")
      PROCsolve24("6789")
      PROCsolve24("1127")
      PROCsolve24("5566")
      END

      DEF PROCsolve24(s$)
      LOCAL F%, I%, J%, K%, L%, P%, T%, X$, o$(), p$(), t$()
      DIM o$(4), p$(24,4), t$(11)
      o$() = "", "+", "-", "*", "/"
      RESTORE
      FOR T% = 1 TO 11
        READ t$(T%)
      NEXT
      DATA "abcdefg", "(abc)defg", "ab(cde)fg", "abcd(efg)", "(abc)d(efg)", "(abcde)fg"
      DATA "ab(cdefg)", "((abc)de)fg", "(ab(cde))fg", "ab((cde)fg)", "ab(cd(efg))"

      FOR I% = 1 TO 4
        FOR J% = 1 TO 4
          FOR K% = 1 TO 4
            FOR L% = 1 TO 4
              IF I%<>J% IF J%<>K% IF K%<>L% IF I%<>K% IF J%<>L% IF I%<>L% THEN
                P% += 1
                p$(P%,1) = MID$(s$,I%,1)
                p$(P%,2) = MID$(s$,J%,1)
                p$(P%,3) = MID$(s$,K%,1)
                p$(P%,4) = MID$(s$,L%,1)
              ENDIF
            NEXT
          NEXT
        NEXT
      NEXT

      FOR I% = 1 TO 4
        FOR J% = 1 TO 4
          FOR K% = 1 TO 4
            FOR T% = 1 TO 11
              FOR P% = 1 TO 24
                X$ = t$(T%)
                MID$(X$, INSTR(X$,"a"), 1) = p$(P%,1)
                MID$(X$, INSTR(X$,"b"), 1) = o$(I%)
                MID$(X$, INSTR(X$,"c"), 1) = p$(P%,2)
                MID$(X$, INSTR(X$,"d"), 1) = o$(J%)
                MID$(X$, INSTR(X$,"e"), 1) = p$(P%,3)
                MID$(X$, INSTR(X$,"f"), 1) = o$(K%)
                MID$(X$, INSTR(X$,"g"), 1) = p$(P%,4)
                F% = TRUE : ON ERROR LOCAL F% = FALSE
                IF F% IF EVAL(X$) = 24 THEN PRINT X$ : EXIT FOR I%
                RESTORE ERROR
              NEXT
            NEXT
          NEXT
        NEXT
      NEXT
      IF I% > 4 PRINT "No solution found"
      ENDPROC

```

{{out}}

```txt

(1+2+3)*4
6*8/(9-7)
(1+2)*(1+7)
(5+5-6)*6

```



## C

This is a solver that's generic enough to deal with more than 4 numbers,
goals other than 24, or different digit ranges.
It guarantees a solution if there is one.
Its output format is reasonably good looking, though not necessarily optimal.

```c
#include 
#include 
#include 

#define n_cards 4
#define solve_goal 24
#define max_digit 9

typedef struct { int num, denom; } frac_t, *frac;
typedef enum { C_NUM = 0, C_ADD, C_SUB, C_MUL, C_DIV } op_type;

typedef struct expr_t *expr;
typedef struct expr_t {
        op_type op;
        expr left, right;
        int value;
} expr_t;

void show_expr(expr e, op_type prec, int is_right)
{
        const char * op;
        switch(e->op) {
        case C_NUM:     printf("%d", e->value);
                        return;
        case C_ADD:     op = " + "; break;
        case C_SUB:     op = " - "; break;
        case C_MUL:     op = " x "; break;
        case C_DIV:     op = " / "; break;
        }

        if ((e->op == prec && is_right) || e->op < prec) printf("(");
        show_expr(e->left, e->op, 0);
        printf("%s", op);
        show_expr(e->right, e->op, 1);
        if ((e->op == prec && is_right) || e->op < prec) printf(")");
}

void eval_expr(expr e, frac f)
{
        frac_t left, right;
        if (e->op == C_NUM) {
                f->num = e->value;
                f->denom = 1;
                return;
        }
        eval_expr(e->left, &left);
        eval_expr(e->right, &right);
        switch (e->op) {
        case C_ADD:
                f->num = left.num * right.denom + left.denom * right.num;
                f->denom = left.denom * right.denom;
                return;
        case C_SUB:
                f->num = left.num * right.denom - left.denom * right.num;
                f->denom = left.denom * right.denom;
                return;
        case C_MUL:
                f->num = left.num * right.num;
                f->denom = left.denom * right.denom;
                return;
        case C_DIV:
                f->num = left.num * right.denom;
                f->denom = left.denom * right.num;
                return;
        default:
                fprintf(stderr, "Unknown op: %d\n", e->op);
                return;
        }
}
int solve(expr ex_in[], int len)
{
        int i, j;
        expr_t node;
        expr ex[n_cards];
        frac_t final;

        if (len == 1) {
                eval_expr(ex_in[0], &final);
                if (final.num == final.denom * solve_goal && final.denom) {
                        show_expr(ex_in[0], 0, 0);
                        return 1;
                }
                return 0;
        }

        for (i = 0; i < len - 1; i++) {
                for (j = i + 1; j < len; j++)
                        ex[j - 1] = ex_in[j];
                ex[i] = &node;
                for (j = i + 1; j < len; j++) {
                        node.left = ex_in[i];
                        node.right = ex_in[j];
                        for (node.op = C_ADD; node.op <= C_DIV; node.op++)
                                if (solve(ex, len - 1))
                                        return 1;

                        node.left = ex_in[j];
                        node.right = ex_in[i];
                        node.op = C_SUB;
                        if (solve(ex, len - 1)) return 1;
                        node.op = C_DIV;
                        if (solve(ex, len - 1)) return 1;

                        ex[j] = ex_in[j];
                }
                ex[i] = ex_in[i];
        }

        return 0;
}

int solve24(int n[])
{
        int i;
        expr_t ex[n_cards];
        expr   e[n_cards];
        for (i = 0; i < n_cards; i++) {
                e[i] = ex + i;
                ex[i].op = C_NUM;
                ex[i].left = ex[i].right = 0;
                ex[i].value = n[i];
        }
        return solve(e, n_cards);
}

int main()
{
        int i, j, n[] = { 3, 3, 8, 8, 9 };
        srand(time(0));

        for (j = 0; j < 10; j++) {
                for (i = 0; i < n_cards; i++) {
                        n[i] = 1 + (double) rand() * max_digit / RAND_MAX;
                        printf(" %d", n[i]);
                }
                printf(":  ");
                printf(solve24(n) ? "\n" : "No solution\n");
        }

        return 0;
}
```

{{out}}

```txt
 1 8 2 1:  1 x 8 x (2 + 1)
 6 8 2 8:  6 + 8 + 2 + 8
 4 2 8 1:  (4 - 2 + 1) x 8
 3 1 9 9:  (9 - 1) / (3 / 9)
 5 7 5 1:  No solution
 5 8 4 1:  (5 + 1) x (8 - 4)
 8 3 4 9:  8 + 3 + 4 + 9
 3 7 4 4:  ((3 + 7) - 4) x 4
 5 6 4 1:  4 / (1 - 5 / 6)
 5 5 9 8:  5 x 5 - 9 + 8
```

For the heck of it, using seven numbers ranging from 0 to 99, trying to calculate 1:

```txt
 54 64 44 67 60 54 97:  (54 + 64 + 44) / 54 + 60 / (67 - 97)
 83 3 52 50 14 48 55:  55 - (((83 + 3 + 52) - 50 + 14) - 48)
 70 14 26 6 4 50 19:  ((70 + 14 + 26) / 4 - 19) x 6 - 50
 75 29 61 95 1 6 73:  6 / (73 - ((75 + 29 + 61) - 95)) - 1
 99 65 59 54 29 3 21:  3 - (99 + 65 + 54) / (59 + 29 + 21)
 88 57 18 72 60 70 22:  (72 - 70) x (60 + 22) - (88 + 57 + 18)
 73 18 76 44 32 3 49:  32 / (49 - (44 + 3)) - ((73 + 18) - 76)
 36 53 68 12 82 30 8:  ((36 + 53 + 68) - 82) / 30 - 12 / 8
 83 35 81 82 99 40 36:  ((83 + 35) x 81 - 82 x 99) / 40 / 36
 29 43 57 18 1 74 89:  (1 + 74) / (((29 + 43) - 57) / 18) - 89
```



## C++

{{works with|C++11}}
{{works with|GCC|4.8}}

This code may be extended to work with more than 4 numbers, goals other than 24, or different digit ranges. Operations have been manually determined for these parameters, with the belief they are complete.


```cpp

#include 
#include 
#include 
#include 
#include 

typedef short int Digit;  // Typedef for the digits data type.

constexpr Digit nDigits{4};      // Amount of digits that are taken into the game.
constexpr Digit maximumDigit{9}; // Maximum digit that may be taken into the game.
constexpr short int gameGoal{24};    // Desired result.

typedef std::array digitSet; // Typedef for the set of digits in the game.
digitSet d;

void printTrivialOperation(std::string operation) { // Prints a commutative operation taking all the digits.
	bool printOperation(false);
	for(const Digit& number : d) {
		if(printOperation)
			std::cout << operation;
		else
			printOperation = true;
		std::cout << number;
	}
	std::cout << std::endl;
}

void printOperation(std::string prefix, std::string operation1, std::string operation2, std::string operation3, std::string suffix = "") {
	std::cout << prefix << d[0] << operation1 << d[1] << operation2 << d[2] << operation3 << d[3] << suffix << std::endl;
}

int main() {
	std::mt19937_64 randomGenerator;
	std::uniform_int_distribution digitDistro{1, maximumDigit};
	// Let us set up a number of trials:
	for(int trial{10}; trial; --trial) {
		for(Digit& digit : d) {
			digit = digitDistro(randomGenerator);
			std::cout << digit << " ";
		}
		std::cout << std::endl;
		std::sort(d.begin(), d.end());
		// We start with the most trivial, commutative operations:
		if(std::accumulate(d.cbegin(), d.cend(), 0) == gameGoal)
			printTrivialOperation(" + ");
		if(std::accumulate(d.cbegin(), d.cend(), 1, std::multiplies{}) == gameGoal)
			printTrivialOperation(" * ");
		// Now let's start working on every permutation of the digits.
		do {
			// Operations with 2 symbols + and one symbol -:
			if(d[0] + d[1] + d[2] - d[3] == gameGoal) printOperation("", " + ", " + ", " - "); // If gameGoal is ever changed to a smaller value, consider adding more operations in this category.
			// Operations with 2 symbols + and one symbol *:
			if(d[0] * d[1] + d[2] + d[3] == gameGoal) printOperation("", " * ", " + ", " + ");
			if(d[0] * (d[1] + d[2]) + d[3] == gameGoal) printOperation("", " * ( ", " + ", " ) + ");
			if(d[0] * (d[1] + d[2] + d[3]) == gameGoal) printOperation("", " * ( ", " + ", " + ", " )");
			// Operations with one symbol + and 2 symbols *:
			if((d[0] * d[1] * d[2]) + d[3] == gameGoal) printOperation("( ", " * ", " * ", " ) + ");
			if(d[0] * d[1] * (d[2] + d[3]) == gameGoal) printOperation("( ", " * ", " * ( ", " + ", " )");
			if((d[0] * d[1]) + (d[2] * d[3]) == gameGoal) printOperation("( ", " * ", " ) + ( ", " * ", " )");
			// Operations with one symbol - and 2 symbols *:
			if((d[0] * d[1] * d[2]) - d[3] == gameGoal) printOperation("( ", " * ", " * ", " ) - ");
			if(d[0] * d[1] * (d[2] - d[3]) == gameGoal) printOperation("( ", " * ", " * ( ", " - ", " )");
			if((d[0] * d[1]) - (d[2] * d[3]) == gameGoal) printOperation("( ", " * ", " ) - ( ", " * ", " )");
			// Operations with one symbol +, one symbol *, and one symbol -:
			if(d[0] * d[1] + d[2] - d[3] == gameGoal) printOperation("", " * ", " + ", " - ");
			if(d[0] * (d[1] + d[2]) - d[3] == gameGoal) printOperation("", " * ( ", " + ", " ) - ");
			if(d[0] * (d[1] - d[2]) + d[3] == gameGoal) printOperation("", " * ( ", " - ", " ) + ");
			if(d[0] * (d[1] + d[2] - d[3]) == gameGoal) printOperation("", " * ( ", " + ", " - ", " )");
			if(d[0] * d[1] - (d[2] + d[3]) == gameGoal) printOperation("", " * ", " - ( ", " + ", " )");
			// Operations with one symbol *, one symbol /, one symbol +:
			if(d[0] * d[1] == (gameGoal - d[3]) * d[2]) printOperation("( ", " * ", " / ", " ) + ");
			if(((d[0] * d[1]) + d[2]) == gameGoal * d[3]) printOperation("(( ", " * ", " ) + ", " ) / ");
			if((d[0] + d[1]) * d[2] == gameGoal * d[3]) printOperation("(( ", " + ", " ) * ", " ) / ");
			if(d[0] * d[1] == gameGoal * (d[2] + d[3])) printOperation("( ", " * ", " ) / ( ", " + ", " )");
			// Operations with one symbol *, one symbol /, one symbol -:
			if(d[0] * d[1] == (gameGoal + d[3]) * d[2]) printOperation("( ", " * ", " / ", " ) - ");
			if(((d[0] * d[1]) - d[2]) == gameGoal * d[3]) printOperation("(( ", " * ", " ) - ", " ) / ");
			if((d[0] - d[1]) * d[2] == gameGoal * d[3]) printOperation("(( ", " - ", " ) * ", " ) / ");
			if(d[0] * d[1] == gameGoal * (d[2] - d[3])) printOperation("( ", " * ", " ) / ( ", " - ", " )");
			// Operations with 2 symbols *, one symbol /:
			if(d[0] * d[1] * d[2] == gameGoal * d[3]) printOperation("", " * ", " * ", " / ");
			if(d[0] * d[1] == gameGoal * d[2] * d[3]) printOperation("", " * ", " / ( ", " * ", " )");
			// Operations with 2 symbols /, one symbol -:
			if(d[0] * d[3] == gameGoal * (d[1] * d[3] - d[2])) printOperation("", " / ( ", " - ", " / ", " )");
			// Operations with 2 symbols /, one symbol *:
			if(d[0] * d[1] == gameGoal * d[2] * d[3]) printOperation("( ", " * ", " / ", " ) / ", "");
		} while(std::next_permutation(d.begin(), d.end())); // All operations are repeated for all possible permutations of the numbers.
	}
	return 0;
}

```


{{out}}

```txt

8 3 7 9
3 * ( 7 + 9 - 8 )
3 * ( 9 + 7 - 8 )
1 4 3 1
( 3 * 4 * ( 1 + 1 )
( 4 * 3 * ( 1 + 1 )
5 4 3 6
6 * ( 3 + 5 - 4 )
6 * ( 5 + 3 - 4 )
2 5 5 8
5 4 7 3
3 * 4 + 5 + 7
3 * 4 + 7 + 5
( 3 * 4 * ( 7 - 5 )
3 * ( 5 + 7 - 4 )
3 * ( 7 + 5 - 4 )
4 * 3 + 5 + 7
4 * 3 + 7 + 5
( 4 * 3 * ( 7 - 5 )
4 * 5 + 7 - 3
5 * 4 + 7 - 3
5 * ( 7 - 3 ) + 4
3 3 9 2
2 * 9 + 3 + 3
3 * ( 2 + 3 ) + 9
3 * ( 2 + 9 - 3 )
3 * ( 3 + 2 ) + 9
3 * ( 9 - 2 ) + 3
3 * ( 9 + 2 - 3 )
9 * 2 + 3 + 3
3 2 7 9
3 * ( 7 - 2 ) + 9
(( 7 + 9 ) * 3 ) / 2
(( 9 + 7 ) * 3 ) / 2
7 1 5 3
7 6 9 4
(( 7 + 9 ) * 6 ) / 4
(( 9 + 7 ) * 6 ) / 4
3 5 3 1
( 1 * 3 * ( 3 + 5 )
( 1 * 3 * ( 5 + 3 )
( 3 * 1 * ( 3 + 5 )
( 3 * 1 * ( 5 + 3 )
(( 3 + 5 ) * 3 ) / 1
(( 5 + 3 ) * 3 ) / 1

```



## Ceylon

Don't forget to import ceylon.random in your module.ceylon file.

```ceylon
import ceylon.random {
	DefaultRandom
}

shared sealed class Rational(numerator, denominator = 1) satisfies Numeric {

	shared Integer numerator;
	shared Integer denominator;

	Integer gcd(Integer a, Integer b) => if (b == 0) then a else gcd(b, a % b);

	shared Rational inverted => Rational(denominator, numerator);

	shared Rational simplified =>
		let (largestFactor = gcd(numerator, denominator))
			Rational(numerator / largestFactor, denominator / largestFactor);

	divided(Rational other) => (this * other.inverted).simplified;

	negated => Rational(-numerator, denominator).simplified;

	plus(Rational other) =>
		let (top = numerator*other.denominator + other.numerator*denominator,
			bottom = denominator * other.denominator)
			Rational(top, bottom).simplified;

	times(Rational other) =>
		Rational(numerator * other.numerator, denominator * other.denominator).simplified;

	shared Integer integer => numerator / denominator;
	shared Float float => numerator.float / denominator.float;

	string => denominator == 1 then numerator.string else "``numerator``/``denominator``";

	shared actual Boolean equals(Object that) {
		if (is Rational that) {
			value simplifiedThis = this.simplified;
			value simplifiedThat = that.simplified;
			return simplifiedThis.numerator==simplifiedThat.numerator &&
					simplifiedThis.denominator==simplifiedThat.denominator;
		} else {
			return false;
		}
	}
}

shared Rational? rational(Integer numerator, Integer denominator = 1) =>
	if (denominator == 0)
	then null
	else Rational(numerator, denominator).simplified;

shared Rational numeratorOverOne(Integer numerator) => Rational(numerator);

shared abstract class Operation(String lexeme) of addition | subtraction | multiplication | division {
	shared formal Rational perform(Rational left, Rational right);
	string => lexeme;
}

shared object addition extends Operation("+") {
	perform(Rational left, Rational right) => left + right;
}
shared object subtraction extends Operation("-") {
	perform(Rational left, Rational right) => left - right;
}
shared object multiplication extends Operation("*") {
	perform(Rational left, Rational right) => left * right;
}
shared object division extends Operation("/") {
	perform(Rational left, Rational right) => left / right;
}

shared Operation[] operations = `Operation`.caseValues;

shared interface Expression of NumberExpression | OperationExpression {
	shared formal Rational evaluate();
}

shared class NumberExpression(Rational number) satisfies Expression {
	evaluate() => number;
	string => number.string;
}
shared class OperationExpression(Expression left, Operation op, Expression right) satisfies Expression {
	evaluate() => op.perform(left.evaluate(), right.evaluate());
	string => "(``left`` ``op`` ``right``)";
}

shared void run() {

	value twentyfour = numeratorOverOne(24);

	value random = DefaultRandom();

	function buildExpressions({Rational*} numbers, Operation* ops) {
		assert (is NumberExpression[4] numTuple = numbers.collect(NumberExpression).tuple());
		assert (is Operation[3] opTuple = ops.sequence().tuple());
		value [a, b, c, d] = numTuple;
		value [op1, op2, op3] = opTuple;
		value opExp = OperationExpression; // this is just to give it a shorter name
		return [
			opExp(opExp(opExp(a, op1, b), op2, c), op3, d),
			opExp(opExp(a, op1, opExp(b, op2, c)), op3, d),
			opExp(a, op1, opExp(opExp(b, op2, c), op3, d)),
			opExp(a, op1, opExp(b, op2, opExp(c, op3, d)))
		];
	}

	print("Please enter your 4 numbers to see how they form 24 or enter the letter r for random numbers.");

	if (exists line = process.readLine()) {

		Rational[] chosenNumbers;

		if (line.trimmed.uppercased == "R") {
			chosenNumbers = random.elements(1..9).take(4).collect((Integer element) => numeratorOverOne(element));
			print("The random numbers are ``chosenNumbers``");
		} else {
			chosenNumbers = line.split().map(Integer.parse).narrow().collect(numeratorOverOne);
		}

		value expressions = {
			for (numbers in chosenNumbers.permutations)
			for (op1 in operations)
			for (op2 in operations)
			for (op3 in operations)
			for (exp in buildExpressions(numbers, op1, op2, op3))
			if (exp.evaluate() == twentyfour)
			exp
		};

		print("The solutions are:");
		expressions.each(print);
	}
}
```



## Clojure


```Clojure
(ns rosettacode.24game.solve
  (:require [clojure.math.combinatorics :as c]
            [clojure.walk :as w]))

(def ^:private op-maps
  (map #(zipmap [:o1 :o2 :o3] %) (c/selections '(* + - /) 3)))

(def ^:private patterns '(
  (:o1 (:o2 :n1 :n2) (:o3 :n3 :n4))
  (:o1 :n1 (:o2 :n2 (:o3 :n3 :n4)))
  (:o1 (:o2 (:o3 :n1 :n2) :n3) :n4)))

(defn play24 [& digits]
  {:pre (and (every? #(not= 0 %) digits)
             (= (count digits) 4))}
  (->> (for [:let [digit-maps
                     (->> digits sort c/permutations
                          (map #(zipmap [:n1 :n2 :n3 :n4] %)))]
             om op-maps, dm digit-maps]
         (w/prewalk-replace dm
           (w/prewalk-replace om patterns)))
       (filter #(= (eval %) 24))
       (map println)
       doall
       count))
```


The function play24 works by substituting the given digits and the four operations into the binary tree patterns (o (o n n) (o n n)), (o (o (o n n) n) n), and (o n (o n (o n n))).
The substitution is the complex part of the program: two pairs of nested maps (the function) are used to substitute in operations and digits, which are replaced into the tree patterns.


## COBOL


```cobol>        >
SOURCE FORMAT FREE
*> This code is dedicated to the public domain
*> This is GNUCobol 2.0
identification division.
program-id. twentyfoursolve.
environment division.
configuration section.
repository. function all intrinsic.
input-output section.
file-control.
    select count-file
        assign to count-file-name
        file status count-file-status
        organization line sequential.
data division.
file section.
fd  count-file.
01  count-record pic x(7).

working-storage section.
01  count-file-name pic x(64) value 'solutioncounts'.
01  count-file-status pic xx.

01  command-area.
    03  nd pic 9.
    03  number-definition.
        05  n occurs 4 pic 9.
    03  number-definition-9 redefines number-definition
        pic 9(4).
    03  command-input pic x(16).
    03  command pic x(5).
    03  number-count pic 9999.
    03  l1 pic 99.
    03  l2 pic 99.
    03  expressions pic zzz,zzz,zz9.

01  number-validation.
    03  px pic 99.
    03  permutations value
          '1234'
        & '1243'
        & '1324'
        & '1342'
        & '1423'
        & '1432'

        & '2134'
        & '2143'
        & '2314'
        & '2341'
        & '2413'
        & '2431'

        & '3124'
        & '3142'
        & '3214'
        & '3241'
        & '3423'
        & '3432'

        & '4123'
        & '4132'
        & '4213'
        & '4231'
        & '4312'
        & '4321'.
        05  permutation occurs 24 pic x(4).
    03  cpx pic 9.
    03  current-permutation pic x(4).
    03  od1 pic 9.
    03  od2 pic 9.
    03  od3 pic 9.
    03  operator-definitions pic x(4) value '+-*/'.
    03  cox pic 9.
    03  current-operators pic x(3).
    03  rpn-forms value
          'nnonono'
        & 'nnonnoo'
        & 'nnnonoo'
        & 'nnnoono'
        & 'nnnnooo'.
        05  rpn-form occurs 5 pic x(7).
    03  rpx pic 9.
    03  current-rpn-form pic x(7).

01  calculation-area.
    03  oqx pic 99.
    03  output-queue pic x(7).
    03  work-number pic s9999.
    03  top-numerator pic s9999 sign leading separate.
    03  top-denominator pic s9999 sign leading separate.
    03  rsx pic 9.
    03  result-stack occurs 8.
        05  numerator pic s9999.
        05  denominator pic s9999.
    03  divide-by-zero-error pic x.

01  totals.
    03  s pic 999.
    03  s-lim pic 999 value 600.
    03  s-max pic 999 value 0.
    03  solution occurs 600 pic x(7).
    03  sc pic 999.
    03  sc1 pic 999.
    03  sc2 pic 9.
    03  sc-max pic 999 value 0.
    03  sc-lim pic 999 value 600.
    03  solution-counts value zeros.
        05  solution-count occurs 600 pic 999.
    03  ns pic 9999.
    03  ns-max pic 9999 value 0.
    03  ns-lim pic 9999 value 6561.
    03  number-solutions occurs 6561.
        05 ns-number pic x(4).
        05 ns-count pic 999.
    03  record-counts pic 9999.
    03  total-solutions pic 9999.

01  infix-area.
    03  i pic 9.
    03  i-s pic 9.
    03  i-s1 pic 9.
    03  i-work pic x(16).
    03  i-stack occurs 7 pic x(13).

procedure division.
start-twentyfoursolve.
    display 'start twentyfoursolve'
    perform display-instructions
    perform get-command
    perform until command-input = spaces
        display space
        initialize command number-count
        unstring command-input delimited by all space
            into command number-count
        move command-input to number-definition
        move spaces to command-input
        evaluate command
        when 'h'
        when 'help'
            perform display-instructions
        when 'list'
            if ns-max = 0
                perform load-solution-counts
            end-if
            perform list-counts
        when 'show'
            if ns-max = 0
                perform load-solution-counts
            end-if
            perform show-numbers
        when other
            if number-definition-9 not numeric
                display 'invalid number'
            else
                perform get-solutions
                perform display-solutions
            end-if
        end-evaluate
        if command-input = spaces
            perform get-command
        end-if
    end-perform
    display 'exit twentyfoursolve'
    stop run
    .
display-instructions.
    display space
    display 'enter a number  as four integers from 1-9 to see its solutions'
    display 'enter list to see counts of solutions for all numbers'
    display 'enter show  to see numbers having  solutions'
    display ' ends the program'
    .
get-command.
    display space
    move spaces to command-input
    display '(h for help)?' with no advancing
    accept command-input
    .
ask-for-more.
    display space
    move 0 to l1
    add 1 to l2
    if l2 = 10
        display 'more ()?' with no advancing
        accept command-input
        move 0 to l2
    end-if
    .
list-counts.
    add 1 to sc-max giving sc
    display 'there are ' sc ' solution counts'
    display space
    display 'solutions/numbers'
    move 0 to l1
    move 0 to l2
    perform varying sc from 1 by 1 until sc > sc-max
    or command-input <> spaces
        if solution-count(sc) > 0
            subtract 1 from sc giving sc1 *> offset to capture zero counts
            display sc1 '/' solution-count(sc) space with no advancing
            add 1 to l1
            if l1 = 8
                perform ask-for-more
            end-if
        end-if
    end-perform
    if l1 > 0
        display space
    end-if
    .
show-numbers. *> with number-count solutions
    add 1 to number-count giving sc1 *> offset for zero count
    evaluate true
    when number-count >= sc-max
        display 'no number has ' number-count ' solutions'
        exit paragraph
    when solution-count(sc1) = 1 and number-count = 1
        display '1 number has 1 solution'
    when solution-count(sc1) = 1
        display '1 number has ' number-count ' solutions'
    when number-count = 1
        display solution-count(sc1) ' numbers have 1 solution'
    when other
        display solution-count(sc1) ' numbers have ' number-count ' solutions'
    end-evaluate
    display space
    move 0 to l1
    move 0 to l2
    perform varying ns from 1 by 1 until ns > ns-max
    or command-input <> spaces
        if ns-count(ns) = number-count
            display ns-number(ns) space with no advancing
            add 1 to l1
            if l1 = 14
                perform ask-for-more
            end-if
        end-if
    end-perform
    if l1 > 0
        display space
    end-if
    .
display-solutions.
    evaluate s-max
    when 0 display number-definition ' has no solutions'
    when 1 display number-definition ' has 1 solution'
    when other display number-definition ' has ' s-max ' solutions'
    end-evaluate
    display space
    move 0 to l1
    move 0 to l2
    perform varying s from 1 by 1 until s > s-max
    or command-input <> spaces
        *> convert rpn solution(s) to infix
        move 0 to i-s
        perform varying i from 1 by 1 until i > 7
            if solution(s)(i:1) >= '1' and <= '9'
                add 1 to i-s
                move solution(s)(i:1) to i-stack(i-s)
            else
                subtract 1 from i-s giving i-s1
                move spaces to i-work
                string '(' i-stack(i-s1) solution(s)(i:1) i-stack(i-s) ')'
                    delimited by space into i-work
                move i-work to i-stack(i-s1)
                subtract 1 from i-s
            end-if
        end-perform
        display solution(s) space i-stack(1) space space with no advancing
        add 1 to l1
        if l1 = 3
            perform ask-for-more
        end-if
    end-perform
    if l1 > 0
        display space
    end-if
    .
load-solution-counts.
    move 0 to ns-max *> numbers and their solution count
    move 0 to sc-max *> solution counts
    move spaces to count-file-status
    open input count-file
    if count-file-status <> '00'
        perform create-count-file
        move 0 to ns-max *> numbers and their solution count
        move 0 to sc-max *> solution counts
        open input count-file
    end-if
    read count-file
    move 0 to record-counts
    move zeros to solution-counts
    perform until count-file-status <> '00'
        add 1 to record-counts
        perform increment-ns-max
        move count-record to number-solutions(ns-max)
        add 1 to ns-count(ns-max) giving sc *> offset 1 for zero counts
        if sc > sc-lim
            display 'sc ' sc ' exceeds sc-lim ' sc-lim
            stop run
        end-if
        if sc > sc-max
            move sc to sc-max
        end-if
        add 1 to solution-count(sc)
        read count-file
    end-perform
    close count-file
    .
create-count-file.
    open output count-file
    display 'Counting solutions for all numbers'
    display 'We will examine 9*9*9*9 numbers'
    display 'For each number we will examine 4! permutations of the digits'
    display 'For each permutation we will examine 4*4*4 combinations of operators'
    display 'For each permutation and combination we will examine 5 rpn forms'
    display 'We will count the number of unique solutions for the given number'
    display 'Each number and its counts will be written to file ' trim(count-file-name)
    compute expressions = 9*9*9*9*factorial(4)*4*4*4*5
    display 'So we will evaluate ' trim(expressions) ' statements'
    display 'This will take a few minutes'
    display 'In the future if ' trim(count-file-name) ' exists, this step will be bypassed'
    move 0 to record-counts
    move 0 to total-solutions
    perform varying n(1) from 1 by 1 until n(1) = 0
        perform varying n(2) from 1 by 1 until n(2) = 0
            display n(1) n(2) '..' *> show progress
            perform varying n(3) from 1 by 1 until n(3) = 0
                perform varying n(4) from 1 by 1 until n(4) = 0
                    perform get-solutions
                    perform increment-ns-max
                    move number-definition to ns-number(ns-max)
                    move s-max to ns-count(ns-max)
                    move number-solutions(ns-max) to count-record
                    write count-record
                    add s-max to total-solutions
                    add 1 to record-counts
                    add 1 to ns-count(ns-max) giving sc *> offset by 1 for zero counts
                    if sc > sc-lim
                        display 'error: ' sc ' solution count exceeds ' sc-lim
                        stop run
                    end-if
                    add 1 to solution-count(sc)
                end-perform
            end-perform
        end-perform
    end-perform
    close count-file
    display record-counts ' numbers and counts written to ' trim(count-file-name)
    display total-solutions ' total solutions'
    display space
    .
increment-ns-max.
    if ns-max >= ns-lim
        display 'error: numbers exceeds ' ns-lim
        stop run
    end-if
    add 1 to ns-max
    .
get-solutions.
    move 0 to s-max
    perform varying px from 1 by 1 until px > 24
        move permutation(px) to current-permutation
        perform varying od1 from 1 by 1 until od1 > 4
            move operator-definitions(od1:1) to current-operators(1:1)
            perform varying od2 from 1 by 1 until od2 > 4
                move operator-definitions(od2:1) to current-operators(2:1)
                perform varying od3 from 1 by 1 until od3 > 4
                    move operator-definitions(od3:1) to current-operators(3:1)
                    perform varying rpx from 1 by 1 until rpx > 5
                        move rpn-form(rpx) to current-rpn-form
                        move 0 to cpx cox
                        move spaces to output-queue
                        perform varying oqx from 1 by 1 until oqx > 7
                            if current-rpn-form(oqx:1) = 'n'
                                add 1 to cpx
                                move current-permutation(cpx:1) to nd
                                move n(nd) to output-queue(oqx:1)
                            else
                                add 1 to cox
                                move current-operators(cox:1) to output-queue(oqx:1)
                            end-if
                        end-perform
                        perform evaluate-rpn
                        if divide-by-zero-error = space
                        and 24 * top-denominator = top-numerator
                            perform varying s from 1 by 1 until s > s-max
                            or solution(s) = output-queue
                                continue
                            end-perform
                            if s > s-max
                                if s >= s-lim
                                    display 'error: solutions ' s ' for ' number-definition ' exceeds ' s-lim
                                    stop run
                                end-if
                                move s to s-max
                                move output-queue to solution(s-max)
                            end-if
                        end-if
                    end-perform
                end-perform
            end-perform
        end-perform
    end-perform
    .
evaluate-rpn.
    move space to divide-by-zero-error
    move 0 to rsx *> stack depth
    perform varying oqx from 1 by 1 until oqx > 7
        if output-queue(oqx:1) >= '1' and <= '9'
            *> push the digit onto the stack
            add 1 to rsx
            move top-numerator to numerator(rsx)
            move top-denominator to denominator(rsx)
            move output-queue(oqx:1) to top-numerator
            move 1 to top-denominator
        else
            *> apply the operation
            evaluate output-queue(oqx:1)
            when '+'
                compute top-numerator = top-numerator * denominator(rsx)
                    + top-denominator * numerator(rsx)
                compute top-denominator = top-denominator * denominator(rsx)
            when '-'
                compute top-numerator = top-denominator * numerator(rsx)
                    - top-numerator * denominator(rsx)
                compute top-denominator = top-denominator * denominator(rsx)
            when '*'
                compute top-numerator = top-numerator * numerator(rsx)
                compute top-denominator = top-denominator * denominator(rsx)
            when '/'
                compute work-number = numerator(rsx) * top-denominator
                compute top-denominator = denominator(rsx) * top-numerator
                if top-denominator = 0
                    move 'y' to divide-by-zero-error
                    exit paragraph
                end-if
                move work-number to top-numerator
            end-evaluate
            *> pop the stack
            subtract 1 from rsx
        end-if
    end-perform
    .
end program twentyfoursolve.
```


{{out}}

```txt

prompt$ cobc -xj twentyfoursolve.cob
start twentyfoursolve

enter a number  as four integers from 1-9 to see its solutions
enter list to see counts of solutions for all numbers
enter show  to see numbers having  solutions
 ends the program

(h for help)?5678

5678 has 026 solutions

57+8-6* (((5+7)-8)*6)  57+86-* ((5+7)*(8-6))  578-+6* ((5+(7-8))*6)
58-7+6* (((5-8)+7)*6)  587--6* ((5-(8-7))*6)  657+8-* (6*((5+7)-8))
6578-+* (6*(5+(7-8)))  658-7+* (6*((5-8)+7))  6587--* (6*(5-(8-7)))
675+8-* (6*((7+5)-8))  6758-+* (6*(7+(5-8)))  675-/8* ((6/(7-5))*8)
675-8// (6/((7-5)/8))  678-5+* (6*((7-8)+5))  6785--* (6*(7-(8-5)))
6875-/* (6*(8/(7-5)))  68*75-/ ((6*8)/(7-5))  75+8-6* (((7+5)-8)*6)
75+86-* ((7+5)*(8-6))  758-+6* ((7+(5-8))*6)  86-57+* ((8-6)*(5+7))
86-75+* ((8-6)*(7+5))  8675-/* (8*(6/(7-5)))  86*75-/ ((8*6)/(7-5))
875-/6* ((8/(7-5))*6)  875-6// (8/((7-5)/6))

(h for help)?

```



## CoffeeScript


```coffeescript

# This program tries to find some way to turn four digits into an arithmetic
# expression that adds up to 24.
#
# Example solution for 5, 7, 8, 8:
#    (((8 + 7) * 8) / 5)


solve_24_game = (digits...) ->
  # Create an array of objects for our helper functions
  arr = for digit in digits
    {
      val: digit
      expr: digit
    }
  combo4 arr...

combo4 = (a, b, c, d) ->
  arr = [a, b, c, d]
  # Reduce this to a three-node problem by combining two
  # nodes from the array.
  permutations = [
    [0, 1, 2, 3]
    [0, 2, 1, 3]
    [0, 3, 1, 2]
    [1, 2, 0, 3]
    [1, 3, 0, 2]
    [2, 3, 0, 1]
  ]
  for permutation in permutations
    [i, j, k, m] = permutation
    for combo in combos arr[i], arr[j]
      answer = combo3 combo, arr[k], arr[m]
      return answer if answer
  null

combo3 = (a, b, c) ->
  arr = [a, b, c]
  permutations = [
    [0, 1, 2]
    [0, 2, 1]
    [1, 2, 0]
  ]
  for permutation in permutations
    [i, j, k] = permutation
    for combo in combos arr[i], arr[j]
      answer = combo2 combo, arr[k]
      return answer if answer
  null

combo2 = (a, b) ->
  for combo in combos a, b
    return combo.expr if combo.val == 24
  null

combos = (a, b) ->
  [
    val: a.val + b.val
    expr: "(#{a.expr} + #{b.expr})"
  ,
    val: a.val * b.val
    expr: "(#{a.expr} * #{b.expr})"
  ,
    val: a.val - b.val
    expr: "(#{a.expr} - #{b.expr})"
  ,
    val: b.val - a.val
    expr: "(#{b.expr} - #{a.expr})"
  ,
    val: a.val / b.val
    expr: "(#{a.expr} / #{b.expr})"
  ,
    val: b.val / a.val
    expr: "(#{b.expr} / #{a.expr})"
  ,
  ]

# test
do ->
  rand_digit = -> 1 + Math.floor (9 * Math.random())

  for i in [1..15]
    a = rand_digit()
    b = rand_digit()
    c = rand_digit()
    d = rand_digit()
    solution = solve_24_game a, b, c, d
    console.log "Solution for #{[a,b,c,d]}: #{solution ? 'no solution'}"

```

{{out}}

```txt

> coffee 24_game.coffee
Solution for 8,3,1,8: ((1 + 8) * (8 / 3))
Solution for 6,9,5,7: (6 - ((5 - 7) * 9))
Solution for 4,2,1,1: no solution
Solution for 3,5,1,3: (((3 + 5) * 1) * 3)
Solution for 6,4,1,7: ((7 - (4 - 1)) * 6)
Solution for 8,1,3,1: (((8 + 1) - 1) * 3)
Solution for 6,1,3,3: (((6 + 1) * 3) + 3)
Solution for 7,1,5,6: (((7 - 1) * 5) - 6)
Solution for 4,2,3,1: ((3 + 1) * (4 + 2))
Solution for 8,8,5,8: ((5 * 8) - (8 + 8))
Solution for 3,8,4,1: ((1 - (3 - 8)) * 4)
Solution for 6,4,3,8: ((8 - (6 / 3)) * 4)
Solution for 2,1,8,7: (((2 * 8) + 1) + 7)
Solution for 5,2,7,5: ((2 * 7) + (5 + 5))
Solution for 2,4,8,9: ((9 - (2 + 4)) * 8)

```



## Common Lisp



```lisp
(defconstant +ops+ '(* / + -))

(defun digits ()
  (sort (loop repeat 4 collect (1+ (random 9))) #'<))

(defun expr-value (expr)
  (eval expr))

(defun divides-by-zero-p (expr)
  (when (consp expr)
    (destructuring-bind (op &rest args) expr
      (or (divides-by-zero-p (car args))
          (and (eq op '/)
               (or (and (= 1 (length args))
                        (zerop (expr-value (car args))))
                   (some (lambda (arg)
                           (or (divides-by-zero-p arg)
                               (zerop (expr-value arg))))
                         (cdr args))))))))

(defun solvable-p (digits &optional expr)
  (unless (divides-by-zero-p expr)
    (if digits
        (destructuring-bind (next &rest rest) digits
          (if expr
              (some (lambda (op)
                      (solvable-p rest (cons op (list next expr))))
                    +ops+)
            (solvable-p rest (list (car +ops+) next))))
      (when (and expr
                 (eql 24 (expr-value expr)))
        (merge-exprs expr)))))

(defun merge-exprs (expr)
  (if (atom expr)
      expr
    (destructuring-bind (op &rest args) expr
      (if (and (member op '(* +))
               (= 1 (length args)))
          (car args)
        (cons op
              (case op
                ((* +)
                 (loop for arg in args
                       for merged = (merge-exprs arg)
                       when (and (consp merged)
                                 (eq op (car merged)))
                       append (cdr merged)
                       else collect merged))
                (t (mapcar #'merge-exprs args))))))))

(defun solve-24-game (digits)
  "Generate a lisp form using the operators in +ops+ and the given
digits which evaluates to 24.  The first form found is returned, or
NIL if there is no solution."
  (solvable-p digits))
```


{{out}}

```txt

CL-USER 138 > (loop repeat 24 for soln = (solve-24-game (digits)) when soln do (pprint soln))

(+ 7 5 (* 4 3))
(* 6 4 (- 3 2))
(+ 9 8 4 3)
(* 8 (- 6 (* 3 1)))
(* 6 4 (/ 2 2))
(* 9 (/ 8 (- 8 5)))
NIL

```



## D

This uses the Rational struct and permutations functions of two other Rosetta Code Tasks.
{{trans|Scala}}

```d
import std.stdio, std.algorithm, std.range, std.conv, std.string,
       std.concurrency, permutations2, arithmetic_rational;

string solve(in int target, in int[] problem) {
    static struct T { Rational r; string e; }

    Generator!T computeAllOperations(in Rational[] L) {
        return new typeof(return)({
            if (!L.empty) {
                immutable x = L[0];
                if (L.length == 1) {
                    yield(T(x, x.text));
                } else {
                    foreach (const o; computeAllOperations(L.dropOne)) {
                        immutable y = o.r;
                        auto sub = [T(x * y, "*"), T(x + y, "+"), T(x - y, "-")];
                        if (y) sub ~= [T(x / y, "/")];
                        foreach (const e; sub)
                            yield(T(e.r, format("(%s%s%s)", x, e.e, o.e)));
                    }
                }
            }
        });
    }

    foreach (const p; problem.map!Rational.array.permutations!false)
        foreach (const sol; computeAllOperations(p))
            if (sol.r == target)
                return sol.e;
    return "No solution";
}

void main() {
    foreach (const prob; [[6, 7, 9, 5], [3, 3, 8, 8], [1, 1, 1, 1]])
        writeln(prob, ": ", solve(24, prob));
}
```

{{out}}

```txt
[6, 7, 9, 5]: (6+(9*(7-5)))
[3, 3, 8, 8]: (8/(3-(8/3)))
[1, 1, 1, 1]: No solution
```



## EchoLisp

The program takes n numbers - not limited to 4 - builds the all possible legal rpn expressions according to the game rules,  and evaluates them. Time saving : 4 5 + is the same as 5 4 + . Do not generate twice. Do not generate expressions like 5 6 * + which are not legal.


```scheme

;; use task [[RPN_to_infix_conversion#EchoLisp]] to print results
(define (rpn->string rpn)
    (if (vector? rpn)
        (infix->string (rpn->infix rpn))
        "😥 Not found"))


(string-delimiter "")
(define OPS #(*  + - // )) ;; use float division
(define-syntax-rule (commutative? op) (or (= op *) (= op +)))

;; ---------------------------------
;; calc rpn -> num value or #f if bad rpn
;; rpn is a vector of ops or numbers
;; ----------------------------------
(define (calc rpn)
(define S (stack 'S))
    (for ((token rpn))
        (if (procedure? token)
            (let [(op2 (pop S)) (op1 (pop S))]
                (if (and op1 op2)
                (push S (apply token (list op1 op2)))
                (push S #f))) ;; not-well formed
        (push S token ))
        #:break (not (stack-top S)))
    (if (= 1 (stack-length S)) (pop S) #f))

;; check for legal rpn -> #f if not legal
(define (rpn? rpn)
(define S (stack 'S))
    (for ((token rpn))
        (if (procedure? token)
            (push S (and (pop S) (pop S)))
            (push S token ))
        #:break (not (stack-top S)))
    (stack-top S))

;; --------------------------------------
;; build-rpn : push next rpn op or number
;; dleft is number of not used digits
;; ---------------------------------------
(define count 0)

(define (build-rpn into: rpn  depth  maxdepth  digits  ops dleft target &hit )
(define cmpop #f)
    (cond
;; tooo long
    [(> (++ count) 200_000) (set-box! &hit 'not-found)]
;; stop on first hit
    [(unbox &hit) &hit]
;; partial rpn must be legal
    [(not (rpn? rpn)) #f]
;; eval rpn if complete
    [(> depth maxdepth)
        (when (= target (calc rpn))  (set-box! &hit rpn))]
;;  else, add a digit to rpn
    [else
    [when (< depth maxdepth)  ;; digits anywhere except last
        (for [(d digits) (i 10)]
                #:continue (zero? d)
                (vector-set! digits i 0) ;; mark used
                (vector-set! rpn depth d)
                (build-rpn rpn (1+ depth) maxdepth  digits  ops (1- dleft)  target &hit)
                (vector-set! digits i d)) ;; mark unused
                ] ;; add digit
;; or,  add an op
;; ops anywhere except  positions 0,1
    [when  (and (> depth 1) (<= (+ depth dleft) maxdepth));; cutter : must use all digits
    (set! cmpop
        (and (number? [rpn (1- depth)])
             (number? [rpn (- depth 2)])
              (> [rpn (1- depth)]  [rpn (- depth 2)])))

        (for [(op ops)]
            #:continue (and cmpop (commutative? op)) ;; cutter : 3 4 + ===  4 3 +
            (vector-set! rpn depth op)
            (build-rpn rpn (1+ depth) maxdepth  digits  ops dleft target &hit)
            (vector-set! rpn depth 0))] ;; add op
        ] ; add something to rpn vector
        )) ; build-rpn

;;------------------------
;;gen24 : num random numbers
;;------------------------
(define (gen24 num maxrange)
     (->> (append (range 1 maxrange)(range 1 maxrange)) shuffle (take num)))

;;-------------------------------------------
;; try-rpn : sets starter values for build-rpn
;;-------------------------------------------
(define (try-rpn digits target)
    (set! digits (list-sort > digits)) ;; seems to accelerate things
    (define rpn (make-vector (1- (* 2 (length digits)))))
    (define &hit (box #f))
    (set! count 0)

    (build-rpn rpn starter-depth: 0
        max-depth: (1- (vector-length rpn))
         (list->vector digits)
         OPS
        remaining-digits: (length digits)
        target &hit )
    (writeln  target '=   (rpn->string (unbox &hit)) 'tries= count))

;; -------------------------------
;; (task numdigits target maxrange)
;; --------------------------------
(define (task (numdigits 4) (target 24) (maxrange 10))
        (define digits (gen24 numdigits maxrange))
        (writeln digits '→ target)
        (try-rpn digits target))

```


{{out}}

```txt

(task 4) ;; standard 24-game
(7 9 2 4)     →     24
24     =     9 + 7 + 4 * 2     tries=     35

(task 4)
(1 9 3 4)     →     24
24     =     9 + (4 + 1) * 3     tries=     468

(task 5 ) ;; 5 digits
(4 8 6 9 8)     →     24
24     =     9 * 8 * (8 / (6 * 4))     tries=     104

(task 5 100) ;; target = 100
(5 6 5 1 3)     →     100
100     =     (6 + (5 * 3 - 1)) * 5     tries=     10688

(task 5 (random 100))
(1 1 8 6 8)     →     31
31     =     8 * (6 - 1) - (8 + 1)     tries=     45673

(task 6 (random 100)) ;; 6 digits
(7 2 7 8 3 1)     →     40
40     =     8 / (7 / (7 * (3 + 2 * 1)))     tries=     154

(task 6 (random 1000) 100) ;; 6 numbers < 100 , target < 1000
(19 15 83 74 61 48)     →     739
739     =     (83 + (74 - (61 + 48))) * 15 + 19     tries=     29336

(task 6 (random 1000) 100) ;; 6 numbers < 100
(73 29 65 78 22 43)     →     1
1     =     😥 Not found     tries=     200033

(task 7 (random 1000) 100) ;; 7 numbers < 100
(7 55 94 4 71 58 93)     →     705
705     =     94 + 93 + 71 + 58 + 55 * 7 + 4     tries=     5982

(task 6 (random -100) 10) ;; negative target
(5 9 7 3 6 3)     →     -54
-54     =     9 * (7 + (6 - 5 * 3)) * 3     tries=     2576

```



## Elixir

{{trans|Ruby}}

```elixir
defmodule Game24 do
  @expressions [ ["((", "", ")", "", ")", ""],
                 ["(", "(", "", "", "))", ""],
                 ["(", "", ")", "(", "", ")"],
                 ["", "((", "", "", ")", ")"],
                 ["", "(", "", "(", "", "))"] ]

  def solve(digits) do
    dig_perm = permute(digits) |> Enum.uniq
    operators = perm_rep(~w[+ - * /], 3)
    for dig <- dig_perm, ope <- operators, expr <- @expressions,
        check?(str = make_expr(dig, ope, expr)),
        do: str
  end

  defp check?(str) do
    try do
      {val, _} = Code.eval_string(str)
      val == 24
    rescue
      ArithmeticError -> false      # division by zero
    end
  end

  defp permute([]), do: [[]]
  defp permute(list) do
    for x <- list, y <- permute(list -- [x]), do: [x|y]
  end

  defp perm_rep([], _), do: [[]]
  defp perm_rep(_,  0), do: [[]]
  defp perm_rep(list, i) do
    for x <- list, y <- perm_rep(list, i-1), do: [x|y]
  end

  defp make_expr([a,b,c,d], [x,y,z], [e0,e1,e2,e3,e4,e5]) do
    e0 <> a <> x <> e1 <> b <> e2 <> y <> e3 <> c <> e4 <> z <> d <> e5
  end
end

case Game24.solve(System.argv) do
  [] -> IO.puts "no solutions"
  solutions ->
    IO.puts "found #{length(solutions)} solutions, including #{hd(solutions)}"
    IO.inspect Enum.sort(solutions)
end
```


{{out}}

```txt

C:\Elixir>elixir game24.exs 1 1 3 4
found 12 solutions, including ((1+1)*3)*4
["((1+1)*3)*4", "((1+1)*4)*3", "(1+1)*(3*4)", "(1+1)*(4*3)", "(3*(1+1))*4",
 "(3*4)*(1+1)", "(4*(1+1))*3", "(4*3)*(1+1)", "3*((1+1)*4)", "3*(4*(1+1))",
 "4*((1+1)*3)", "4*(3*(1+1))"]

C:\Elixir>elixir game24.exs 6 7 8 9
found 8 solutions, including (6*8)/(9-7)
["(6*8)/(9-7)", "(6/(9-7))*8", "(8*6)/(9-7)", "(8/(9-7))*6", "6*(8/(9-7))",
 "6/((9-7)/8)", "8*(6/(9-7))", "8/((9-7)/6)"]

C:\Elixir>elixir game24.exs 1 2 2 3
no solutions

```



## ERRE

ERRE hasn't an "EVAL" function so we must write an evaluation routine; this task is solved via "brute-force".

```ERR

PROGRAM 24SOLVE

LABEL 98,99,2540,2550,2560

! possible brackets
CONST NBRACKETS=11,ST_CONST$="+-*/^("

DIM D[4],PERM[24,4]
DIM BRAKETS$[NBRACKETS]
DIM OP$[3]
DIM STACK$[50]

PROCEDURE COMPATTA_STACK
   IF NS>1 THEN
      R=1
      WHILE R=NS2 THEN GOTO 99 END IF
            N1#=VAL(STACK$[L-1]) N2#=VAL(STACK$[L+1]) NOP=NOP-1
            IF STACK$[L]="^" THEN
                RI#=N1#^N2#
            END IF
            STACK$[L-1]=STR$(RI#)
            N=L
            WHILE N<=NS2-2 DO
               STACK$[N]=STACK$[N+2]
               N=N+1
            END WHILE
            NS2=NS2-2
            L=NS1-1
        END IF
        L=L+1
     END WHILE

     L=NS1
     WHILE L<=NS2 DO
        IF STACK$[L]="*" OR STACK$[L]="/" THEN
            IF L>=NS2 THEN GOTO 99 END IF
            N1#=VAL(STACK$[L-1]) N2#=VAL(STACK$[L+1]) NOP=NOP-1
            IF STACK$[L]="*" THEN
                 RI#=N1#*N2#
              ELSE
                 IF N2#<>0 THEN RI#=N1#/N2# ELSE NERR=6 RI#=0 END IF
            END IF
            STACK$[L-1]=STR$(RI#)
            N=L
            WHILE N<=NS2-2 DO
               STACK$[N]=STACK$[N+2]
               N=N+1
            END WHILE
            NS2=NS2-2
            L=NS1-1
        END IF
        L=L+1
     END WHILE

     L=NS1
     WHILE L<=NS2 DO
        IF STACK$[L]="+" OR STACK$[L]="-" THEN
            EXIT IF L>=NS2
            N1#=VAL(STACK$[L-1]) N2#=VAL(STACK$[L+1])  NOP=NOP-1
            IF STACK$[L]="+" THEN RI#=N1#+N2# ELSE RI#=N1#-N2# END IF
            STACK$[L-1]=STR$(RI#)
            N=L
            WHILE N<=NS2-2 DO
               STACK$[N]=STACK$[N+2]
               N=N+1
            END WHILE
            NS2=NS2-2
            L=NS1-1
        END IF
        L=L+1
     END WHILE
99:
     IF NOP<2 THEN   ! precedenza tra gli operatori
          DB#=VAL(STACK$[NS1])
       ELSE
          IF NOP<3 THEN
               DB#=VAL(STACK$[NS1+2])
             ELSE
               DB#=VAL(STACK$[NS1+4])
          END IF
     END IF
END PROCEDURE

PROCEDURE SVOLGI_PAR
   NPA=NPA-1
   FOR J=NS TO 1 STEP -1 DO
      EXIT IF STACK$[J]="("
   END FOR
   IF J=0 THEN
       NS1=1  NS2=NS  CALC_ARITM NERR=7
     ELSE
       FOR R=J TO NS-1 DO
         STACK$[R]=STACK$[R+1]
       END FOR
       NS1=J  NS2=NS-1  CALC_ARITM
       IF NS1=2 THEN
           NS1=1 STACK$[1]=STACK$[2]
       END IF
       NS=NS1
       COMPATTA_STACK
   END IF
END PROCEDURE

PROCEDURE MYEVAL(EXPRESSION$,DB#,NERR->DB#,NERR)

     NOP=0 NPA=0 NS=1 K$="" NERR=0
     STACK$[1]="@"          ! init stack

     FOR W=1 TO LEN(EXPRESSION$) DO
        LOOP
           CODE=ASC(MID$(EXPRESSION$,W,1))
           IF (CODE>=48 AND CODE<=57) OR CODE=46 THEN
                K$=K$+CHR$(CODE)
                W=W+1 IF W>LEN(EXPRESSION$) THEN GOTO 98 END IF
              ELSE
                EXIT IF K$=""
                IF NS>1 OR (NS=1 AND STACK$[1]<>"@") THEN NS=NS+1 END IF
                IF FLAG=0 THEN
                      STACK$[NS]=K$
                   ELSE
                      STACK$[NS]=STR$(VAL(K$)*FLAG)
                END IF
                K$=""  FLAG=0
                EXIT
           END IF
        END LOOP
        IF CODE=43 THEN K$="+" END IF
        IF CODE=45 THEN K$="-" END IF
        IF CODE=42 THEN K$="*" END IF
        IF CODE=47 THEN K$="/" END IF
        IF CODE=94 THEN K$="^" END IF

        CASE CODE OF
          43,45,42,47,94->  ! +-*/^
             IF MID$(EXPRESSION$,W+1,1)="-" THEN FLAG=-1  W=W+1 END IF
             IF INSTR(ST_CONST$,STACK$[NS])<>0 THEN
                 NERR=5
               ELSE
                 NS=NS+1 STACK$[NS]=K$ NOP=NOP+1
                 IF NOP>=2 THEN
                    FOR J=NS TO 1 STEP -1 DO
                       IF STACK$[J]<>"(" THEN GOTO 2540 END IF
                       IF J

          40->  ! (
             IF NS>1 OR (NS=1 AND STACK$[1]<>"@") THEN NS=NS+1 END IF
             STACK$[NS]="(" NPA=NPA+1
             IF MID$(EXPRESSION$,W+1,1)="-" THEN FLAG=-1 W=W+1 END IF
          END ->

          41-> ! )
             SVOLGI_PAR
             IF NERR=7 THEN
                  NERR=0 NOP=0 NPA=0 NS=1
               ELSE
                  IF NERR=0 OR NERR=1 THEN
                      DB#=VAL(STACK$[NS])
                      REGISTRO_X#=DB#
                    ELSE
                      NOP=0 NPA=0 NS=1
                  END IF
             END IF
          END ->

          OTHERWISE
             NERR=8
        END CASE
        K$=""
   END FOR
98:
   IF K$<>"" THEN
        IF NS>1 OR (NS=1 AND STACK$[1]<>"@") THEN NS=NS+1 END IF
        IF FLAG=0 THEN STACK$[NS]=K$ ELSE STACK$[NS]=STR$(VAL(K$)*FLAG) END IF
   END IF

   IF INSTR(ST_CONST$,STACK$[NS])<>0 THEN
         NERR=6
       ELSE
         WHILE NPA<>0 DO
             SVOLGI_PAR
         END WHILE
         IF NERR<>7 THEN NS1=1  NS2=NS CALCARITM END IF
    END IF

    NS=1  NOP=0  NPA=0

END PROCEDURE

BEGIN
   PRINT(CHR$(12);) ! CLS

   ! possible brackets
   DATA("4#4#4#4")
   DATA("(4#4)#4#4")
   DATA("4#(4#4)#4")
   DATA("4#4#(4#4)")
   DATA("(4#4)#(4#4)")
   DATA("(4#4#4)#4")
   DATA("4#(4#4#4)")
   DATA("((4#4)#4)#4")
   DATA("(4#(4#4))#4")
   DATA("4#((4#4)#4)")
   DATA("4#(4#(4#4))")
   FOR I=1 TO NBRACKETS DO
     READ(BRAKETS$[I])
   END FOR

   INPUT("ENTER 4 DIGITS: ",A$)
   ND=0
   FOR I=1 TO LEN(A$) DO
      C$=MID$(A$,I,1)
      IF INSTR("123456789",C$)>0 THEN
        ND=ND+1
        D[ND]=VAL(C$)
      END IF
   END FOR
   ! precompute permutations. dumb way.
   NPERM=1*2*3*4
   N=0
   FOR I=1 TO 4 DO
      FOR J=1 TO 4 DO
        FOR K=1 TO 4 DO
            FOR L=1 TO 4 DO
            ! valid permutation (no dupes)
                IF I<>J AND I<>K AND I<>L  AND J<>K AND J<>L AND K<>L THEN
                    N=N+1
! actually,we can as well permute given digits
                    PERM[N,1]=D[I]
                    PERM[N,2]=D[J]
                    PERM[N,3]=D[K]
                    PERM[N,4]=D[L]
                END IF
            END FOR
        END FOR
      END FOR
   END FOR

   ! operations: full search
   COUNT=0
   OPS$="+-*/"
   FOR OP1=1 TO 4 DO
      OP$[1]=MID$(OPS$,OP1,1)
      FOR OP2=1 TO 4 DO
        OP$[2]=MID$(OPS$,OP2,1)
        FOR OP3=1 TO 4 DO
            OP$[3]=MID$(OPS$,OP3,1)
            ! substitute all brackets
            FOR T=1 TO NBRACKETS DO
                TMPL$=BRAKETS$[T]
                ! now,substitute all digits: permutations.
                FOR P=1 TO NPERM DO
                    RES$=""
                    NOP=0
                    ND=0
                    FOR I=1 TO LEN(TMPL$) DO
                        C$=MID$(TMPL$,I,1)
                        CASE C$ OF
                        "#"->                ! operations
                            NOP=NOP+1
                            RES$=RES$+OP$[NOP]
                        END ->
                        "4"->                ! digits
                            ND=NOP+1
                            RES$=RES$+MID$(STR$(PERM[P,ND]),2)
                        END ->
                        OTHERWISE            ! brackets goes here
                            RES$=RES$+C$
                        END CASE
                    END FOR
                    ! eval here
                    MY_EVAL(RES$,DB#,NERR->DB#,NERR)
                    IF DB#=24 AND NERR=0 THEN
                        PRINT("24=";RES$)
                        COUNT=COUNT+1
                    END IF
                END FOR
            END FOR
        END FOR
      END FOR
    END FOR

    IF COUNT=0 THEN
       PRINT("If you see this, probably task cannot be solved with these digits")
     ELSE
       PRINT("Total=";COUNT)
    END IF

END PROGRAM

```

{{out}}

```txt

ENTER 4 DIGITS: ? 6759
24=6+(7-5)*9
24=6+((7-5)*9)
24=6+9*(7-5)
24=6+(9*(7-5))
24=6-(5-7)*9
24=6-((5-7)*9)
24=(7-5)*9+6
24=((7-5)*9)+6
24=6-9*(5-7)
24=6-(9*(5-7))
24=9*(7-5)+6
24=(9*(7-5))+6
Total= 12

```



## Euler Math Toolbox


Via brute force.


```Euler Math Toolbox

>function try24 (v) ...
$n=cols(v);
$if n==1 and v[1]~=24 then
$  "Solved the problem",
$  return 1;
$endif
$loop 1 to n
$  w=tail(v,2);
$  loop 1 to n-1
$    h=w; a=v[1]; b=w[1];
$    w[1]=a+b; if try24(w); ""+a+"+"+b+"="+(a+b), return 1; endif;
$    w[1]=a-b; if try24(w); ""+a+"-"+b+"="+(a-b), return 1; endif;
$    w[1]=a*b; if try24(w); ""+a+"*"+b+"="+(a*b), return 1; endif;
$    if not b~=0 then
$       w[1]=a/b; if try24(w); ""+a+"/"+b+"="+(a/b), return 1; endif;
$    endif;
$    w=rotright(w);
$  end;
$  v=rotright(v);
$end;
$return 0;
$endfunction

```



```Euler Math Toolbox

>try24([1,2,3,4]);
 Solved the problem
 6*4=24
 3+3=6
 1+2=3
>try24([8,7,7,1]);
 Solved the problem
 22+2=24
 14+8=22
 7+7=14
>try24([8,4,7,1]);
 Solved the problem
 6*4=24
 7-1=6
 8-4=4
>try24([3,4,5,6]);
 Solved the problem
 4*6=24
 -1+5=4
 3-4=-1

```


=={{header|F_Sharp|F#}}==
The program wants to give all solutions for a given set of 4 digits.
It eliminates all duplicate solutions which result from transposing equal digits.
The basic solution is an adaption of the OCaml program.

```fsharp
open System

let rec gcd x y = if x = y || x = 0 then y else if x < y then gcd y x else gcd y (x-y)
let abs (x : int) = Math.Abs x
let sign (x: int) = Math.Sign x
let cint s = Int32.Parse(s)

type Rat(x : int, y : int) =
    let g = if y = 0 then 0 else gcd (abs x) (abs y)
    member this.n = if g = 0 then sign y * sign x else sign y * x / g   // store a minus sign in the numerator
    member this.d =
        if y = 0 then 0 else sign y * y / g
    static member (~-) (x : Rat) = Rat(-x.n, x.d)
    static member (+) (x : Rat, y : Rat) = Rat(x.n * y.d + y.n * x.d, x.d * y.d)
    static member (-) (x : Rat, y : Rat) = x + Rat(-y.n, y.d)
    static member (*) (x : Rat, y : Rat) = Rat(x.n * y.n, x.d * y.d)
    static member (/) (x : Rat, y : Rat) = x * Rat(y.d, y.n)
    interface System.IComparable with
      member this.CompareTo o =
        match o with
        | :? Rat as that -> compare (this.n * that.d) (that.n * this.d)
        | _ -> invalidArg "o" "cannot compare values of differnet types."
    override this.Equals(o) =
        match o with
        | :? Rat as that -> this.n = that.n && this.d = that.d
        | _ -> false
    override this.ToString() =
        if this.d = 1 then this.n.ToString()
        else sprintf @"<%d,%d>" this.n this.d
    new(x : string, y : string) = if y = "" then Rat(cint x, 1) else Rat(cint x, cint y)

type expression =
    | Const of Rat
    | Sum  of expression * expression
    | Diff of expression * expression
    | Prod of expression * expression
    | Quot of expression * expression

let rec eval = function
    | Const c -> c
    | Sum (f, g) -> eval f + eval g
    | Diff(f, g) -> eval f - eval g
    | Prod(f, g) -> eval f * eval g
    | Quot(f, g) -> eval f / eval g

let print_expr expr =
    let concat (s : seq) = System.String.Concat s
    let paren p prec op_prec = if prec > op_prec then p else ""
    let rec print prec = function
    | Const c -> c.ToString()
    | Sum(f, g) ->
        concat [ (paren "(" prec 0); (print 0 f); " + "; (print 0 g); (paren ")" prec 0) ]
    | Diff(f, g) ->
        concat [ (paren "(" prec 0); (print 0 f); " - "; (print 1 g); (paren ")" prec 0) ]
    | Prod(f, g) ->
        concat [ (paren "(" prec 2); (print 2 f); " * "; (print 2 g); (paren ")" prec 2) ]
    | Quot(f, g) ->
        concat [ (paren "(" prec 2); (print 2 f); " / "; (print 3 g); (paren ")" prec 2) ]
    print 0 expr

let rec normal expr =
    let norm epxr =
        match expr with
        | Sum(x, y) -> if eval x <= eval y then expr else Sum(normal y, normal x)
        | Prod(x, y) -> if eval x <= eval y then expr else Prod(normal y, normal x)
        | _ -> expr
    match expr with
    | Const c -> expr
    | Sum(x, y) -> norm (Sum(normal x, normal y))
    | Prod(x, y) -> norm (Prod(normal x, normal y))
    | Diff(x, y) -> Diff(normal x, normal y)
    | Quot(x, y) -> Quot(normal x, normal y)

let rec insert v = function
    | [] -> [[v]]
    | x::xs as li -> (v::li) :: (List.map (fun y -> x::y) (insert v xs))

let permutations li =
    List.foldBack (fun x z -> List.concat (List.map (insert x) z)) li [[]]

let rec comp expr rest = seq {
    match rest with
    | x::xs ->
        yield! comp (Sum (expr, x)) xs;
        yield! comp (Diff(x, expr)) xs;
        yield! comp (Diff(expr, x)) xs;
        yield! comp (Prod(expr, x)) xs;
        yield! comp (Quot(x, expr)) xs;
        yield! comp (Quot(expr, x)) xs;
    | [] -> if eval expr = Rat(24,1) then yield print_expr (normal expr)
}

[]
let main argv =
    let digits = List.init 4 (fun i -> Const (Rat(argv.[i],"")))
    let solutions =
        permutations digits
        |> Seq.groupBy (sprintf "%A")
        |> Seq.map snd |> Seq.map Seq.head
        |> Seq.map (fun x -> comp (List.head x) (List.tail x))
        |> Seq.choose (fun x -> if Seq.isEmpty x then None else Some x)
        |> Seq.concat
    if Seq.isEmpty solutions then
        printfn "No solutions."
    else
        solutions
        |> Seq.groupBy id
        |> Seq.iter (fun x -> printfn "%s" (fst x))
    0
```

{{out}}

```txt
>solve24 3 3 3 4
4 * (3 * 3 - 3)
3 + 3 * (3 + 4)

>solve24 3 3 3 5
No solutions.

solve24 3 3 3 6
6 + 3 * (3 + 3)
(3 / 3 + 3) * 6
3 * (3 + 6) - 3
3 + 3 + 3 * 6

>solve24 3 3 8 8
8 / (3 - 8 / 3)

>solve24 3 8 8 9
3 * (9 - 8 / 8)
(9 - 8) * 3 * 8
3 / (9 - 8) * 8
8 / ((9 - 8) / 3)
3 * (9 - 8) * 8
3 * 8 / (9 - 8)
3 / ((9 - 8) / 8)
```



## Factor

Factor is well-suited for this task due to its homoiconicity and because it is a reverse-Polish notation evaluator. All we're doing is grouping each permutation of digits with three selections of the possible operators into quotations (blocks of code that can be stored like sequences). Then we call each quotation and print out the ones that equal 24. The recover word is an exception handler that is used to intercept divide-by-zero errors and continue gracefully by removing those quotations from consideration.

```factor
USING: continuations grouping io kernel math math.combinatorics
prettyprint quotations random sequences sequences.deep ;
IN: rosetta-code.24-game

: 4digits ( -- seq ) 4 9 random-integers [ 1 + ] map ;

: expressions ( digits -- exprs )
    all-permutations [ [ + - * / ] 3 selections
    [ append ] with map ] map flatten 7 group ;

: 24= ( exprs -- )
    >quotation dup call( -- x ) 24 = [ . ] [ drop ] if ;

: 24-game ( -- )
    4digits dup "The numbers: " write . "The solutions: "
    print expressions [ [ 24= ] [ 2drop ] recover ] each ;

24-game
```

{{out}}

```txt

The numbers: { 4 9 3 1 }
The solutions:
[ 4 9 3 1 * - * ]
[ 4 9 3 1 / - * ]
[ 4 9 1 3 * - * ]
[ 4 1 9 3 - * * ]
[ 4 1 9 3 - / / ]
[ 9 3 4 1 + * + ]
[ 9 3 1 4 + * + ]
[ 1 4 9 3 - * * ]
[ 1 4 9 3 * - - ]
[ 1 4 3 9 * - - ]

The numbers: { 1 7 4 9 }
The solutions:

The numbers: { 1 5 6 8 }
The solutions:
[ 6 1 5 8 - - * ]
[ 6 1 8 5 - + * ]
[ 6 8 1 5 - + * ]
[ 6 8 5 1 - - * ]

```



## Fortran


```Fortran
program solve_24
  use helpers
  implicit none
  real                 :: vector(4), reals(4), p, q, r, s
  integer              :: numbers(4), n, i, j, k, a, b, c, d
  character, parameter :: ops(4) = (/ '+', '-', '*', '/' /)
  logical              :: last
  real,parameter       :: eps = epsilon(1.0)

  do n=1,12
    call random_number(vector)
    reals   = 9 * vector + 1
    numbers = int(reals)
    call Insertion_Sort(numbers)

    permutations: do
      a = numbers(1); b = numbers(2); c = numbers(3); d = numbers(4)
      reals = real(numbers)
      p = reals(1);   q = reals(2);   r = reals(3);   s = reals(4)
      ! combinations of operators:
      do i=1,4
        do j=1,4
          do k=1,4
            if      ( abs(op(op(op(p,i,q),j,r),k,s)-24.0) < eps ) then
              write (*,*) numbers, ' : ', '((',a,ops(i),b,')',ops(j),c,')',ops(k),d
              exit permutations
            else if ( abs(op(op(p,i,op(q,j,r)),k,s)-24.0) < eps ) then
              write (*,*) numbers, ' : ', '(',a,ops(i),'(',b,ops(j),c,'))',ops(k),d
              exit permutations
            else if ( abs(op(p,i,op(op(q,j,r),k,s))-24.0) < eps ) then
              write (*,*) numbers, ' : ', a,ops(i),'((',b,ops(j),c,')',ops(k),d,')'
              exit permutations
            else if ( abs(op(p,i,op(q,j,op(r,k,s)))-24.0) < eps ) then
              write (*,*) numbers, ' : ', a,ops(i),'(',b,ops(j),'(',c,ops(k),d,'))'
              exit permutations
            else if ( abs(op(op(p,i,q),j,op(r,k,s))-24.0) < eps ) then
              write (*,*) numbers, ' : ', '(',a,ops(i),b,')',ops(j),'(',c,ops(k),d,')'
              exit permutations
            end if
          end do
        end do
      end do
      call nextpermutation(numbers,last)
      if ( last ) then
        write (*,*) numbers, ' : no solution.'
        exit permutations
      end if
    end do permutations

  end do

contains

  pure real function op(x,c,y)
    integer, intent(in) :: c
    real, intent(in)    :: x,y
    select case ( ops(c) )
      case ('+')
        op = x+y
      case ('-')
        op = x-y
      case ('*')
        op = x*y
      case ('/')
        op = x/y
    end select
  end function op

end program solve_24
```



```Fortran
module helpers

contains

  pure subroutine Insertion_Sort(a)
    integer, intent(inout) :: a(:)
    integer                :: temp, i, j
    do i=2,size(a)
      j = i-1
      temp = a(i)
      do while ( j>=1 .and. a(j)>temp )
        a(j+1) = a(j)
        j = j - 1
      end do
      a(j+1) = temp
    end do
  end subroutine Insertion_Sort

  subroutine nextpermutation(perm,last)
    integer, intent(inout) :: perm(:)
    logical, intent(out)   :: last
    integer :: k,l
    k = largest1()
    last = k == 0
    if ( .not. last ) then
      l = largest2(k)
      call swap(l,k)
      call reverse(k)
    end if
  contains
    pure integer function largest1()
      integer :: k, max
      max = 0
      do k=1,size(perm)-1
        if ( perm(k) < perm(k+1) ) then
          max = k
        end if
      end do
      largest1 = max
    end function largest1

    pure integer function largest2(k)
      integer, intent(in) :: k
      integer             :: l, max
      max = k+1
      do l=k+2,size(perm)
        if ( perm(k) < perm(l) ) then
          max = l
        end if
      end do
      largest2 = max
    end function largest2

    subroutine swap(l,k)
      integer, intent(in) :: k,l
      integer             :: temp
      temp    = perm(k)
      perm(k) = perm(l)
      perm(l) = temp
    end subroutine swap

    subroutine reverse(k)
      integer, intent(in) :: k
      integer             :: i
      do i=1,(size(perm)-k)/2
        call swap(k+i,size(perm)+1-i)
      end do
    end subroutine reverse

  end subroutine nextpermutation

end module helpers
```

{{out}} (using g95):

```txt
 3 6 7 9  :  3 *(( 6 - 7 )+ 9 )
 3 9 5 8  : (( 3 * 9 )+ 5 )- 8
 4 5 6 9  : (( 4 + 5 )+ 6 )+ 9
 2 9 9 8  : ( 2 +( 9 / 9 ))* 8
 1 4 7 5  : ( 1 +( 4 * 7 ))- 5
 8 7 7 6  : no solution.
 3 3 8 9  : ( 3 *( 3 + 8 ))- 9
 1 5 6 7  : ( 1 +( 5 * 6 ))- 7
 2 3 5 3  :  2 *(( 3 * 5 )- 3 )
 4 5 6 9  : (( 4 + 5 )+ 6 )+ 9
 1 1 3 6  : ( 1 +( 1 * 3 ))* 6
 2 4 6 8  : (( 2 / 4 )* 6 )* 8

```



## GAP


```gap
# Solution in '''RPN'''
check := function(x, y, z)
	local r, c, s, i, j, k, a, b, p;
	i := 0;
	j := 0;
	k := 0;
	s := [ ];
	r := "";
	for c in z do
		if c = 'x' then
			i := i + 1;
			k := k + 1;
			s[k] := x[i];
			Append(r, String(x[i]));
		else
			j := j + 1;
			b := s[k];
			k := k - 1;
			a := s[k];
			p := y[j];
			r[Size(r) + 1] := p;
			if p = '+' then
				a := a + b;
			elif p = '-' then
				a := a - b;
			elif p = '*' then
				a := a * b;
			elif p = '/' then
				if b = 0 then
					continue;
				else
					a := a / b;
				fi;
			else
				return fail;
			fi;
			s[k] := a;
		fi;
	od;
	if s[1] = 24 then
		return r;
	else
		return fail;
	fi;
end;

Player24 := function(digits)
	local u, v, w, x, y, z, r;
	u := PermutationsList(digits);
	v := Tuples("+-*/", 3);
	w := ["xx*x*x*", "xx*xx**", "xxx**x*", "xxx*x**", "xxxx***"];
	for x in u do
		for y in v do
			for z in w do
				r := check(x, y, z);
				if r <> fail then
					return r;
				fi;
			od;
		od;
	od;
	return fail;
end;

Player24([1,2,7,7]);
# "77*1-2/"
Player24([9,8,7,6]);
# "68*97-/"
Player24([1,1,7,7]);
# fail

# Solutions with only one distinct digit are found only for 3, 4, 5, 6:
Player24([3,3,3,3]);
# "33*3*3-"
Player24([4,4,4,4]);
# "44*4+4+"
Player24([5,5,5,5]);
# "55*55/-"
Player24([6,6,6,6]);
# "66*66+-"

# A tricky one:
Player24([3,3,8,8]);
"8383/-/"
```




## Go


```go
package main

import (
	"fmt"
	"math/rand"
	"time"
)

const (
	op_num = iota
	op_add
	op_sub
	op_mul
	op_div
)

type frac struct {
	num, denom int
}

// Expression: can either be a single number, or a result of binary
// operation from left and right node
type Expr struct {
	op          int
	left, right *Expr
	value       frac
}

var n_cards = 4
var goal = 24
var digit_range = 9

func (x *Expr) String() string {
	if x.op == op_num {
		return fmt.Sprintf("%d", x.value.num)
	}

	var bl1, br1, bl2, br2, opstr string
	switch {
	case x.left.op == op_num:
	case x.left.op >= x.op:
	case x.left.op == op_add && x.op == op_sub:
		bl1, br1 = "", ""
	default:
		bl1, br1 = "(", ")"
	}

	if x.right.op == op_num || x.op < x.right.op {
		bl2, br2 = "", ""
	} else {
		bl2, br2 = "(", ")"
	}

	switch {
	case x.op == op_add:
		opstr = " + "
	case x.op == op_sub:
		opstr = " - "
	case x.op == op_mul:
		opstr = " * "
	case x.op == op_div:
		opstr = " / "
	}

	return bl1 + x.left.String() + br1 + opstr +
		bl2 + x.right.String() + br2
}

func expr_eval(x *Expr) (f frac) {
	if x.op == op_num {
		return x.value
	}

	l, r := expr_eval(x.left), expr_eval(x.right)

	switch x.op {
	case op_add:
		f.num = l.num*r.denom + l.denom*r.num
		f.denom = l.denom * r.denom
		return

	case op_sub:
		f.num = l.num*r.denom - l.denom*r.num
		f.denom = l.denom * r.denom
		return

	case op_mul:
		f.num = l.num * r.num
		f.denom = l.denom * r.denom
		return

	case op_div:
		f.num = l.num * r.denom
		f.denom = l.denom * r.num
		return
	}
	return
}

func solve(ex_in []*Expr) bool {
	// only one expression left, meaning all numbers are arranged into
	// a binary tree, so evaluate and see if we get 24
	if len(ex_in) == 1 {
		f := expr_eval(ex_in[0])
		if f.denom != 0 && f.num == f.denom*goal {
			fmt.Println(ex_in[0].String())
			return true
		}
		return false
	}

	var node Expr
	ex := make([]*Expr, len(ex_in)-1)

	// try to combine a pair of expressions into one, thus reduce
	// the list length by 1, and recurse down
	for i := range ex {
		copy(ex[i:len(ex)], ex_in[i+1:len(ex_in)])

		ex[i] = &node
		for j := i + 1; j < len(ex_in); j++ {
			node.left = ex_in[i]
			node.right = ex_in[j]

			// try all 4 operators
			for o := op_add; o <= op_div; o++ {
				node.op = o
				if solve(ex) {
					return true
				}
			}

			// also - and / are not commutative, so swap arguments
			node.left = ex_in[j]
			node.right = ex_in[i]

			node.op = op_sub
			if solve(ex) {
				return true
			}

			node.op = op_div
			if solve(ex) {
				return true
			}

			if j < len(ex) {
				ex[j] = ex_in[j]
			}
		}
		ex[i] = ex_in[i]
	}
	return false
}

func main() {
	cards := make([]*Expr, n_cards)
	rand.Seed(time.Now().Unix())

	for k := 0; k < 10; k++ {
		for i := 0; i < n_cards; i++ {
			cards[i] = &Expr{op_num, nil, nil,
				frac{rand.Intn(digit_range-1) + 1, 1}}
			fmt.Printf(" %d", cards[i].value.num)
		}
		fmt.Print(":  ")
		if !solve(cards) {
			fmt.Println("No solution")
		}
	}
}
```

{{out}}

```txt
 8 6 7 6:  No solution
 7 2 6 6:  (7 - 2) * 6 - 6
 4 8 7 3:  4 * (7 - 3) + 8
 3 8 8 7:  3 * 8 * (8 - 7)
 5 7 3 7:  No solution
 5 7 8 3:  5 * 7 - 8 - 3
 3 6 5 2:  ((3 + 5) * 6) / 2
 8 4 5 4:  (8 - 4) * 5 + 4
 2 2 8 8:  (2 + 2) * 8 - 8
 6 8 8 2:  6 + 8 + 8 + 2

```



## Gosu


```Gosu

uses java.lang.Integer
uses java.lang.Double
uses java.lang.System
uses java.util.ArrayList
uses java.util.LinkedList
uses java.util.List
uses java.util.Scanner
uses java.util.Stack

function permutations( lst : List ) : List> {
    if( lst.size() == 0 ) return {}
    if( lst.size() == 1 ) return { lst }

    var pivot = lst.get(lst.size()-1)

    var sublist = new ArrayList( lst )
    sublist.remove( sublist.size() - 1 )

    var subPerms = permutations( sublist )

    var ret = new ArrayList>()
    for( x in subPerms ) {
        for( e in x index i ) {
            var next = new LinkedList( x )
            next.add( i, pivot )
            ret.add( next )
        }
        x.add( pivot )
        ret.add( x )
    }
    return ret
}

function readVals() : List {
    var line = new java.io.BufferedReader( new java.io.InputStreamReader( System.in ) ).readLine()
    var scan = new Scanner( line )

    var ret = new ArrayList()
    for( i in 0..3 ) {
        var next = scan.nextInt()
        if( 0 >= next || next >= 10 ) {
            print( "Invalid entry: ${next}" )
            return null
        }
        ret.add( next )
    }
    return ret
}

function getOp( i : int ) : char[] {
    var ret = new char[3]
    var ops = { '+', '-', '*', '/' }
    ret[0] = ops[i / 16]
    ret[1] = ops[(i / 4) % 4 ]
    ret[2] = ops[i % 4 ]
    return ret
}

function isSoln( nums : List, ops : char[] ) : boolean {
    var stk = new Stack()
    for( n in nums ) {
        stk.push( n )
    }

    for( c in ops ) {
        var r = stk.pop().doubleValue()
        var l = stk.pop().doubleValue()
        if( c == '+' ) {
            stk.push( l + r )
        } else if( c == '-' ) {
            stk.push( l - r )
        } else if( c == '*' ) {
            stk.push( l * r )
        } else if( c == '/' ) {
            // Avoid division by 0
            if( r == 0.0 ) {
                return false
            }
            stk.push( l / r )
        }
    }

    return java.lang.Math.abs( stk.pop().doubleValue() - 24.0 ) < 0.001
}

function printSoln( nums : List, ops : char[] ) {
    // RPN: a b c d + - *
    // Infix (a * (b - (c + d)))
    print( "Found soln: (${nums.get(0)} ${ops[0]} (${nums.get(1)} ${ops[1]} (${nums.get(2)} ${ops[2]} ${nums.get(3)})))" )
}

System.out.print( "#> " )
var vals = readVals()

var opPerms = 0..63
var solnFound = false

for( i in permutations( vals ) ) {
    for( j in opPerms ) {
        var opList = getOp( j )
        if( isSoln( i, opList ) ) {
            printSoln( i, opList )
            solnFound = true
        }
    }
}

if( ! solnFound ) {
    print( "No solution!" )
}

```



## Haskell



```haskell
import Data.List
import Data.Ratio
import Control.Monad
import System.Environment (getArgs)

data Expr = Constant Rational |
    Expr :+ Expr | Expr :- Expr |
    Expr :* Expr | Expr :/ Expr
    deriving (Eq)

ops = [(:+), (:-), (:*), (:/)]

instance Show Expr where
    show (Constant x) = show $ numerator x
      -- In this program, we need only print integers.
    show (a :+ b)     = strexp "+" a b
    show (a :- b)     = strexp "-" a b
    show (a :* b)     = strexp "*" a b
    show (a :/ b)     = strexp "/" a b

strexp :: String -> Expr -> Expr -> String
strexp op a b = "(" ++ show a ++ " " ++ op ++ " " ++ show b ++ ")"

templates :: [[Expr] -> Expr]
templates = do
    op1 <- ops
    op2 <- ops
    op3 <- ops
    [\[a, b, c, d] -> op1 a $ op2 b $ op3 c d,
     \[a, b, c, d] -> op1 (op2 a b) $ op3 c d,
     \[a, b, c, d] -> op1 a $ op2 (op3 b c) d,
     \[a, b, c, d] -> op1 (op2 a $ op3 b c) d,
     \[a, b, c, d] -> op1 (op2 (op3 a b) c) d]

eval :: Expr -> Maybe Rational
eval (Constant c) = Just c
eval (a :+ b)     = liftM2 (+) (eval a) (eval b)
eval (a :- b)     = liftM2 (-) (eval a) (eval b)
eval (a :* b)     = liftM2 (*) (eval a) (eval b)
eval (a :/ b)     = do
    denom <- eval b
    guard $ denom /= 0
    liftM (/ denom) $ eval a

solve :: Rational -> [Rational] -> [Expr]
solve target r4 = filter (maybe False (== target) . eval) $
    liftM2 ($) templates $
    nub $ permutations $ map Constant r4

main = getArgs >>= mapM_ print . solve 24 . map (toEnum . read)
```


Example use:


```txt
$ runghc 24Player.hs 2 3 8 9
(8 * (9 - (3 * 2)))
(8 * (9 - (2 * 3)))
((9 - (2 * 3)) * 8)
((9 - (3 * 2)) * 8)
((9 - 3) * (8 / 2))
((8 / 2) * (9 - 3))
(8 * ((9 - 3) / 2))
(((9 - 3) / 2) * 8)
((9 - 3) / (2 / 8))
((8 * (9 - 3)) / 2)
(((9 - 3) * 8) / 2)
(8 / (2 / (9 - 3)))
```


### Alternative version


```haskell
import Control.Applicative
import Data.List
import Text.PrettyPrint


data Expr = C Int | Op String Expr Expr

toDoc (C     x  ) = int x
toDoc (Op op x y) = parens $ toDoc x <+> text op <+> toDoc y

ops :: [(String, Int -> Int -> Int)]
ops = [("+",(+)), ("-",(-)), ("*",(*)), ("/",div)]


solve :: Int -> [Int] -> [Expr]
solve res = filter ((Just res ==) . eval) . genAst
  where
    genAst [x] = [C x]
    genAst xs  = do
      (ys,zs) <- split xs
      let f (Op op _ _) = op `notElem` ["+","*"] || ys <= zs
      filter f $ Op <$> map fst ops <*> genAst ys <*> genAst zs

    eval (C      x  ) = Just x
    eval (Op "/" _ y) | Just 0 <- eval y = Nothing
    eval (Op op  x y) = lookup op ops <*> eval x <*> eval y


select :: Int -> [Int] -> [[Int]]
select 0 _  = [[]]
select n xs = [x:zs | k <- [0..length xs - n]
                    , let (x:ys) = drop k xs
                    , zs <- select (n - 1) ys
                    ]

split :: [Int] -> [([Int],[Int])]
split xs = [(ys, xs \\ ys) | n <- [1..length xs - 1]
                           , ys <- nub . sort $ select n xs
                           ]


main = mapM_ (putStrLn . render . toDoc) $ solve 24 [2,3,8,9]
```

{{out}}

```txt
((8 / 2) * (9 - 3))
((2 / 9) + (3 * 8))
((3 * 8) - (2 / 9))
((8 - (2 / 9)) * 3)
(((2 / 9) + 8) * 3)
(((8 + 9) / 2) * 3)
((2 + (8 * 9)) / 3)
((3 - (2 / 9)) * 8)
((9 - (2 * 3)) * 8)
(((2 / 9) + 3) * 8)
(((2 + 9) / 3) * 8)
(((9 - 3) / 2) * 8)
(((9 - 3) * 8) / 2)
```


== {{header|Icon}} and {{header|Unicon}} ==
This shares code with and solves the [[24_game#Icon_and_Unicon|24 game]].  A series of pattern expressions are built up and then populated with the permutations of the selected digits.  Equations are skipped if they have been seen before.  The procedure 'eval' was modified to catch zero divides.  The solution will find either all occurrences or just the first occurrence of a solution.


```Icon
invocable all
link strings   # for csort, deletec, permutes

procedure main()
static eL
initial {
   eoP := []  # set-up expression and operator permutation patterns
   every ( e := !["a@b#c$d", "a@(b#c)$d", "a@b#(c$d)", "a@(b#c$d)", "a@(b#(c$d))"] ) &
         ( o := !(opers := "+-*/") || !opers || !opers ) do
      put( eoP, map(e,"@#$",o) )    # expr+oper perms

   eL := []   # all cases
   every ( e := !eoP ) & ( p := permutes("wxyz") ) do
      put(eL, map(e,"abcd",p))

   }

write("This will attempt to find solutions to 24 for sets of numbers by\n",
      "combining 4 single digits between 1 and 9 to make 24 using only + - * / and ( ).\n",
      "All operations have equal precedence and are evaluated left to right.\n",
      "Enter 'use n1 n2 n3 n4' or just hit enter (to use a random set),",
      "'first'/'all' shows the first or all solutions, 'quit' to end.\n\n")

repeat {
   e := trim(read()) | fail
   e ?  case tab(find(" ")|0) of {
      "q"|"quit" : break
      "u"|"use"  : e := tab(0)
      "f"|"first": first := 1 & next
      "a"|"all"  : first := &null & next
      ""         : e := " " ||(1+?8) || " " || (1+?8) ||" " || (1+?8) || " " || (1+?8)
      }

   writes("Attempting to solve 24 for",e)

   e := deletec(e,' \t') # no whitespace
   if e ? ( tab(many('123456789')), pos(5), pos(0) ) then
      write(":")
   else write(" - invalid, only the digits '1..9' are allowed.") & next

   eS := set()
   every ex := map(!eL,"wxyz",e) do {
      if member(eS,ex) then next # skip duplicates of final expression
      insert(eS,ex)
      if ex ? (ans := eval(E()), pos(0)) then # parse and evaluate
         if ans = 24 then {
            write("Success ",image(ex)," evaluates to 24.")
            if \first then break
            }
      }
   }
write("Quiting.")
end

procedure eval(X)    #: return the evaluated AST
   if type(X) == "list" then {
      x := eval(get(X))
      while o := get(X) do
         if y := get(X) then
            x := o( real(x), (o ~== "/" | fail, eval(y) ))
         else write("Malformed expression.") & fail
   }
   return \x | X
end

procedure E()    #: expression
   put(lex := [],T())
   while put(lex,tab(any('+-*/'))) do
      put(lex,T())
   suspend if *lex = 1 then lex[1] else lex     # strip useless []
end

procedure T()                   #: Term
   suspend 2(="(", E(), =")") | # parenthesized subexpression, or ...
       tab(any(&digits))        # just a value
end
```



{{libheader|Icon Programming Library}}
[http://www.cs.arizona.edu/icon/library/src/procs/strings.icn strings.icn provides deletec and permutes]


## J


```J
perm=: (A.&i.~ !) 4
ops=: ' ',.'+-*%' {~ >,{i.each 4 4 4
cmask=: 1 + 0j1 * i.@{:@$@[ e. ]
left=:  [ #!.'('~"1 cmask
right=: [ #!.')'~"1 cmask
paren=: 2 :'[: left&m right&n'
parens=: ], 0 paren 3, 0 paren 5, 2 paren 5, [: 0 paren 7 (0 paren 3)
all=: [: parens [:,/ ops ,@,."1/ perm { [:;":each
answer=: ({.@#~ 24 = ".)@all
```


This implementation tests all 7680 candidate sentences.

Example use:

    answer 2 3 5 7
  2+7+3*5
    answer 8 4 7 1
  8*7-4*1
   answer 1 1 2 7
 (1+2)*1+7

The answer will be either a suitable J sentence or blank if none can be found.  "J sentence" means that, for example, the sentence 8*7-4*1 is equivalent to the sentence 8*(7-(4*1)).  [Many infix languages use operator precedence to make polynomials easier to express without parenthesis, but J has other mechanisms for expressing polynomials and minimal operator precedence makes the language more regular.]


## Java

{{works with|Java|7}}
Playable version, will print solution on request.

Note that this version does not extend to different digit ranges.

```java
import java.util.*;

public class Game24Player {
    final String[] patterns = {"nnonnoo", "nnonono", "nnnoono", "nnnonoo",
        "nnnnooo"};
    final String ops = "+-*/^";

    String solution;
    List digits;

    public static void main(String[] args) {
        new Game24Player().play();
    }

    void play() {
        digits = getSolvableDigits();

        Scanner in = new Scanner(System.in);
        while (true) {
            System.out.print("Make 24 using these digits: ");
            System.out.println(digits);
            System.out.println("(Enter 'q' to quit, 's' for a solution)");
            System.out.print("> ");

            String line = in.nextLine();
            if (line.equalsIgnoreCase("q")) {
                System.out.println("\nThanks for playing");
                return;
            }

            if (line.equalsIgnoreCase("s")) {
                System.out.println(solution);
                digits = getSolvableDigits();
                continue;
            }

            char[] entry = line.replaceAll("[^*+-/)(\\d]", "").toCharArray();

            try {
                validate(entry);

                if (evaluate(infixToPostfix(entry))) {
                    System.out.println("\nCorrect! Want to try another? ");
                    digits = getSolvableDigits();
                } else {
                    System.out.println("\nNot correct.");
                }

            } catch (Exception e) {
                System.out.printf("%n%s Try again.%n", e.getMessage());
            }
        }
    }

    void validate(char[] input) throws Exception {
        int total1 = 0, parens = 0, opsCount = 0;

        for (char c : input) {
            if (Character.isDigit(c))
                total1 += 1 << (c - '0') * 4;
            else if (c == '(')
                parens++;
            else if (c == ')')
                parens--;
            else if (ops.indexOf(c) != -1)
                opsCount++;
            if (parens < 0)
                throw new Exception("Parentheses mismatch.");
        }

        if (parens != 0)
            throw new Exception("Parentheses mismatch.");

        if (opsCount != 3)
            throw new Exception("Wrong number of operators.");

        int total2 = 0;
        for (int d : digits)
            total2 += 1 << d * 4;

        if (total1 != total2)
            throw new Exception("Not the same digits.");
    }

    boolean evaluate(char[] line) throws Exception {
        Stack s = new Stack<>();
        try {
            for (char c : line) {
                if ('0' <= c && c <= '9')
                    s.push((float) c - '0');
                else
                    s.push(applyOperator(s.pop(), s.pop(), c));
            }
        } catch (EmptyStackException e) {
            throw new Exception("Invalid entry.");
        }
        return (Math.abs(24 - s.peek()) < 0.001F);
    }

    float applyOperator(float a, float b, char c) {
        switch (c) {
            case '+':
                return a + b;
            case '-':
                return b - a;
            case '*':
                return a * b;
            case '/':
                return b / a;
            default:
                return Float.NaN;
        }
    }

    List randomDigits() {
        Random r = new Random();
        List result = new ArrayList<>(4);
        for (int i = 0; i < 4; i++)
            result.add(r.nextInt(9) + 1);
        return result;
    }

    List getSolvableDigits() {
        List result;
        do {
            result = randomDigits();
        } while (!isSolvable(result));
        return result;
    }

    boolean isSolvable(List digits) {
        Set> dPerms = new HashSet<>(4 * 3 * 2);
        permute(digits, dPerms, 0);

        int total = 4 * 4 * 4;
        List> oPerms = new ArrayList<>(total);
        permuteOperators(oPerms, 4, total);

        StringBuilder sb = new StringBuilder(4 + 3);

        for (String pattern : patterns) {
            char[] patternChars = pattern.toCharArray();

            for (List dig : dPerms) {
                for (List opr : oPerms) {

                    int i = 0, j = 0;
                    for (char c : patternChars) {
                        if (c == 'n')
                            sb.append(dig.get(i++));
                        else
                            sb.append(ops.charAt(opr.get(j++)));
                    }

                    String candidate = sb.toString();
                    try {
                        if (evaluate(candidate.toCharArray())) {
                            solution = postfixToInfix(candidate);
                            return true;
                        }
                    } catch (Exception ignored) {
                    }
                    sb.setLength(0);
                }
            }
        }
        return false;
    }

    String postfixToInfix(String postfix) {
        class Expression {
            String op, ex;
            int prec = 3;

            Expression(String e) {
                ex = e;
            }

            Expression(String e1, String e2, String o) {
                ex = String.format("%s %s %s", e1, o, e2);
                op = o;
                prec = ops.indexOf(o) / 2;
            }
        }

        Stack expr = new Stack<>();

        for (char c : postfix.toCharArray()) {
            int idx = ops.indexOf(c);
            if (idx != -1) {

                Expression r = expr.pop();
                Expression l = expr.pop();

                int opPrec = idx / 2;

                if (l.prec < opPrec)
                    l.ex = '(' + l.ex + ')';

                if (r.prec <= opPrec)
                    r.ex = '(' + r.ex + ')';

                expr.push(new Expression(l.ex, r.ex, "" + c));
            } else {
                expr.push(new Expression("" + c));
            }
        }
        return expr.peek().ex;
    }

    char[] infixToPostfix(char[] infix) throws Exception {
        StringBuilder sb = new StringBuilder();
        Stack s = new Stack<>();
        try {
            for (char c : infix) {
                int idx = ops.indexOf(c);
                if (idx != -1) {
                    if (s.isEmpty())
                        s.push(idx);
                    else {
                        while (!s.isEmpty()) {
                            int prec2 = s.peek() / 2;
                            int prec1 = idx / 2;
                            if (prec2 >= prec1)
                                sb.append(ops.charAt(s.pop()));
                            else
                                break;
                        }
                        s.push(idx);
                    }
                } else if (c == '(') {
                    s.push(-2);
                } else if (c == ')') {
                    while (s.peek() != -2)
                        sb.append(ops.charAt(s.pop()));
                    s.pop();
                } else {
                    sb.append(c);
                }
            }
            while (!s.isEmpty())
                sb.append(ops.charAt(s.pop()));

        } catch (EmptyStackException e) {
            throw new Exception("Invalid entry.");
        }
        return sb.toString().toCharArray();
    }

    void permute(List lst, Set> res, int k) {
        for (int i = k; i < lst.size(); i++) {
            Collections.swap(lst, i, k);
            permute(lst, res, k + 1);
            Collections.swap(lst, k, i);
        }
        if (k == lst.size())
            res.add(new ArrayList<>(lst));
    }

    void permuteOperators(List> res, int n, int total) {
        for (int i = 0, npow = n * n; i < total; i++)
            res.add(Arrays.asList((i / npow), (i % npow) / n, i % n));
    }
}
```


{{out}}

```txt
Make 24 using these digits: [5, 7, 1, 8]
(Enter 'q' to quit, 's' for a solution)
> (8-5) * (7+1)

Correct! Want to try another?
Make 24 using these digits: [3, 9, 2, 9]
(Enter 'q' to quit, 's' for a solution)
> (3*2) + 9 + 9

Correct! Want to try another?
Make 24 using these digits: [4, 4, 8, 5]
(Enter 'q' to quit, 's' for a solution)
> s
4 * 5 - (4 - 8)
Make 24 using these digits: [2, 5, 9, 1]
(Enter 'q' to quit, 's' for a solution)
> 2+5+9+1

Not correct.
Make 24 using these digits: [2, 5, 9, 1]
(Enter 'q' to quit, 's' for a solution)
> 2 * 9 + 5 + 1

Correct! Want to try another?
Make 24 using these digits: [8, 4, 3, 1]
(Enter 'q' to quit, 's' for a solution)
> s
(8 + 4) * (3 - 1)
Make 24 using these digits: [9, 4, 5, 6]
(Enter 'q' to quit, 's' for a solution)
> (9 +4) * 2 - 2

Not the same digits. Try again.
Make 24 using these digits: [9, 4, 5, 6]
(Enter 'q' to quit, 's' for a solution)
> q

Thanks for playing
```



## JavaScript

This is a translation of the C code.

```javascript
var ar=[],order=[0,1,2],op=[],val=[];
var NOVAL=9999,oper="+-*/",out;

function rnd(n){return Math.floor(Math.random()*n)}

function say(s){
 try{document.write(s+"
")}
 catch(e){WScript.Echo(s)}
}

function getvalue(x,dir){
 var r=NOVAL;
 if(dir>0)++x;
 while(1){
  if(val[x]!=NOVAL){
   r=val[x];
   val[x]=NOVAL;
   break;
  }
  x+=dir;
 }
 return r*1;
}

function calc(){
 var c=0,l,r,x;
 val=ar.join('/').split('/');
 while(c<3){
  x=order[c];
  l=getvalue(x,-1);
  r=getvalue(x,1);
  switch(op[x]){
   case 0:val[x]=l+r;break;
   case 1:val[x]=l-r;break;
   case 2:val[x]=l*r;break;
   case 3:
   if(!r||l%r)return 0;
   val[x]=l/r;
  }
  ++c;
 }
 return getvalue(-1,1);
}

function shuffle(s,n){
 var x=n,p=eval(s),r,t;
 while(x--){
  r=rnd(n);
  t=p[x];
  p[x]=p[r];
  p[r]=t;
 }
}

function parenth(n){
 while(n>0)--n,out+='(';
 while(n<0)++n,out+=')';
}

function getpriority(x){
 for(var z=3;z--;)if(order[z]==x)return 3-z;
 return 0;
}

function showsolution(){
 var x=0,p=0,lp=0,v=0;
 while(x<4){
  if(x<3){
   lp=p;
   p=getpriority(x);
   v=p-lp;
   if(v>0)parenth(v);
  }
  out+=ar[x];
  if(x<3){
   if(v<0)parenth(v);
   out+=oper.charAt(op[x]);
  }
  ++x;
 }
 parenth(-p);
 say(out);
}

function solve24(s){
 var z=4,r;
 while(z--)ar[z]=s.charCodeAt(z)-48;
 out="";
 for(z=100000;z--;){
  r=rnd(256);
  op[0]=r&3;
  op[1]=(r>>2)&3;
  op[2]=(r>>4)&3;
  shuffle("ar",4);
  shuffle("order",3);
  if(calc()!=24)continue;
  showsolution();
  break;
 }
}

solve24("1234");
solve24("6789");
solve24("1127");
```


Examples:


```txt
(((3*1)*4)*2)
((6*8)/((9-7)))
(((1+7))*(2+1))
```



## jq

{{works with|jq|1.4}}
The following solution is generic: the objective (e.g. 24) is specified as
the argument to solve/1, and the user may specify any number of numbers.

'''Infrastructure:'''

```jq
# Generate a stream of the permutations of the input array.
def permutations:
  if length == 0 then []
  else range(0;length) as $i
  | [.[$i]] + (del(.[$i])|permutations)
  end ;

# Generate a stream of arrays of length n,
# with members drawn from the input array.
def take(n):
  length as $l |
  if n == 1 then range(0;$l) as $i | [ .[$i] ]
  else take(n-1) + take(1)
  end;

# Emit an array with elements that alternate between those in the input array and those in short,
# starting with the former, and using nothing if "short" is too too short.
def intersperse(short):
 . as $in
 | reduce range(0;length) as $i
     ([]; . + [ $in[$i], (short[$i] // empty) ]);

# Emit a stream of all the nested triplet groupings of the input array elements,
# e.g. [1,2,3,4,5] =>
# [1,2,[3,4,5]]
# [[1,2,3],4,5]
#
def triples:
  . as $in
  | if   length == 3 then .
    elif length == 1 then $in[0]
    elif length < 3 then empty
    else
      (range(0; (length-1) / 2) * 2 + 1)  as $i
      | ($in[0:$i] | triples)  as $head
      | ($in[$i+1:] | triples) as $tail
      | [$head, $in[$i], $tail]
    end;
```

'''Evaluation and pretty-printing of allowed expressions'''

```jq
# Evaluate the input, which must be a number or a triple: [x, op, y]
def eval:
  if type == "array" then
    .[1] as $op
    | if .[0] == null or .[2] == null then null
      else
       (.[0] | eval) as $left | (.[2] | eval) as $right
       | if $left == null or $right == null then null
        elif  $op == "+" then $left + $right
        elif  $op == "-" then $left - $right
        elif  $op == "*" then $left * $right
        elif  $op == "/" then
          if $right == 0 then null
  	  else $left / $right
	  end
        else "invalid arithmetic operator: \($op)" | error
	end
      end
  else .
  end;

def pp:
  "\(.)" | explode | map([.] | implode | if . == "," then " " elif . == "\"" then "" else . end) | join("");
```


'''24 Game''':

```jq
def OPERATORS: ["+", "-", "*", "/"];

# Input: an array of 4 digits
# o: an array of 3 operators
# Output: a stream
def EXPRESSIONS(o):
   intersperse( o ) | triples;

def solve(objective):
  length as $length
  | [ (OPERATORS | take($length-1)) as $poperators
    | permutations | EXPRESSIONS($poperators)
    | select( eval == objective)
  ] as $answers
  | if $answers|length > 3 then "That was too easy. I found \($answers|length) answers, e.g. \($answers[0] | pp)"
    elif $answers|length > 1 then $answers[] | pp
    else "You lose! There are no solutions."
    end
;

solve(24), "Please try again."
```

{{out}}

```sh
$ jq -r -f Solve.jq
[1,2,3,4]
That was too easy. I found 242 answers, e.g. [4 * [1 + [2 + 3]]]
Please try again.
[1,2,3,40,1]
That was too easy. I found 636 answers, e.g. [[[1 / 2] * 40] + [3 + 1]]
Please try again.
[3,8,9]
That was too easy. I found 8 answers, e.g. [[8 / 3] * 9]
Please try again.
[4,5,6]
You lose! There are no solutions.
Please try again.
[1,2,3,4,5,6]
That was too easy. I found 197926 answers, e.g. [[2 * [1 + 4]] + [3 + [5 + 6]]]
Please try again.
```



## Julia


For julia version 0.5 and higher, the Combinatorics package must be installed and imported (`using Combinatorics`). Combinatorial functions like `nthperm` have been moved from Base to that package and are not available by default anymore.

```julia
function solve24(nums)
    length(nums) != 4 && error("Input must be a 4-element Array")
    syms = [+,-,*,/]
    for x in syms, y in syms, z in syms
        for i = 1:24
            a,b,c,d = nthperm(nums,i)
            if round(x(y(a,b),z(c,d)),5) == 24
                return "($a$y$b)$x($c$z$d)"
            elseif round(x(a,y(b,z(c,d))),5) == 24
                return "$a$x($b$y($c$z$d))"
            elseif round(x(y(z(c,d),b),a),5) == 24
                return "(($c$z$d)$y$b)$x$a"
            elseif round(x(y(b,z(c,d)),a),5) == 24
                return "($b$y($c$z$d))$x$a"
            end
        end
    end
    return "0"
end
```

{{out}}

```txt
julia> for i in 1:10
            nums = rand(1:9, 4)
            println("solve24($nums) -> $(solve24(nums))")
       end
solve24([9,4,4,5]) -> 0
solve24([1,7,2,7]) -> ((7*7)-1)/2
solve24([5,7,5,4]) -> 4*(7-(5/5))
solve24([1,4,6,6]) -> 6+(6*(4-1))
solve24([2,3,7,3]) -> ((2+7)*3)-3
solve24([8,7,9,7]) -> 0
solve24([1,6,2,6]) -> 6+(6*(1+2))
solve24([7,9,4,1]) -> (7-4)*(9-1)
solve24([6,4,2,2]) -> (2-2)+(6*4)
solve24([5,7,9,7]) -> (5+7)*(9-7)
```



## Kotlin

{{trans|C}}

```scala
// version 1.1.3

import java.util.Random

const val N_CARDS = 4
const val SOLVE_GOAL = 24
const val MAX_DIGIT = 9

class Frac(val num: Int, val den: Int)

enum class OpType { NUM, ADD, SUB, MUL, DIV }

class Expr(
    var op:    OpType = OpType.NUM,
    var left:  Expr?  = null,
    var right: Expr?  = null,
    var value: Int    = 0
)

fun showExpr(e: Expr?, prec: OpType, isRight: Boolean) {
    if (e == null) return
    val op = when (e.op) {
        OpType.NUM -> { print(e.value); return }
        OpType.ADD -> " + "
        OpType.SUB -> " - "
        OpType.MUL -> " x "
        OpType.DIV -> " / "
    }

    if ((e.op == prec && isRight) || e.op < prec) print("(")
    showExpr(e.left, e.op, false)
    print(op)
    showExpr(e.right, e.op, true)
    if ((e.op == prec && isRight) || e.op < prec) print(")")
}

fun evalExpr(e: Expr?): Frac {
    if (e == null) return Frac(0, 1)
    if (e.op == OpType.NUM) return Frac(e.value, 1)
    val l = evalExpr(e.left)
    val r = evalExpr(e.right)
    return when (e.op) {
        OpType.ADD -> Frac(l.num * r.den + l.den * r.num, l.den * r.den)
        OpType.SUB -> Frac(l.num * r.den - l.den * r.num, l.den * r.den)
        OpType.MUL -> Frac(l.num * r.num, l.den * r.den)
        OpType.DIV -> Frac(l.num * r.den, l.den * r.num)
        else       -> throw IllegalArgumentException("Unknown op: ${e.op}")
    }
}

fun solve(ea: Array, len: Int): Boolean {
    if (len == 1) {
        val final = evalExpr(ea[0])
        if (final.num == final.den * SOLVE_GOAL && final.den != 0) {
            showExpr(ea[0], OpType.NUM, false)
            return true
        }
    }

    val ex = arrayOfNulls(N_CARDS)
    for (i in 0 until len - 1) {
        for (j in i + 1 until len) ex[j - 1] = ea[j]
        val node = Expr()
        ex[i] = node
        for (j in i + 1 until len) {
            node.left = ea[i]
            node.right = ea[j]
            for (k in OpType.values().drop(1)) {
                node.op = k
                if (solve(ex, len - 1)) return true
            }
            node.left = ea[j]
            node.right = ea[i]
            node.op = OpType.SUB
            if (solve(ex, len - 1)) return true
            node.op = OpType.DIV
            if (solve(ex, len - 1)) return true
            ex[j] = ea[j]
        }
        ex[i] = ea[i]
    }
    return false
}

fun solve24(n: IntArray) =
    solve (Array(N_CARDS) { Expr(value = n[it]) }, N_CARDS)

fun main(args: Array) {
    val r = Random()
    val n = IntArray(N_CARDS)
    for (j in 0..9) {
        for (i in 0 until N_CARDS) {
            n[i] = 1 + r.nextInt(MAX_DIGIT)
            print(" ${n[i]}")
        }
        print(":  ")
        println(if (solve24(n)) "" else "No solution")
    }
}
```


Sample output:

```txt

 8 4 1 7:  (8 - 4) x (7 - 1)
 6 1 4 1:  ((6 + 1) - 1) x 4
 8 8 5 4:  (8 / 8 + 5) x 4
 9 6 9 8:  8 / ((9 - 6) / 9)
 6 6 9 6:  (6 x 6) / 9 x 6
 9 9 7 7:  No solution
 1 1 2 5:  No solution
 6 9 4 1:  6 x (9 - 4 - 1)
 7 7 6 4:  7 + 7 + 6 + 4
 4 8 8 4:  4 + 8 + 8 + 4

```



## Liberty BASIC


```lb
dim d(4)
input "Enter 4 digits: "; a$
nD=0
for i =1 to len(a$)
    c$=mid$(a$,i,1)
    if instr("123456789",c$) then
        nD=nD+1
        d(nD)=val(c$)
    end if
next
'for i = 1 to 4
'    print d(i);
'next

'precompute permutations. Dumb way.
nPerm = 1*2*3*4
dim perm(nPerm, 4)
n = 0
for i = 1 to 4
    for j = 1 to 4
        for k = 1 to 4
            for l = 1 to 4
            'valid permutation (no dupes?)
                if i<>j and i<>k and i<>l _
                    and j<>k and j<>l _
                        and k<>l then
                    n=n+1
                    '
'                    perm(n,1)=i
'                    perm(n,2)=j
'                    perm(n,3)=k
'                    perm(n,4)=l
                    'actually, we can as well permute given digits
                    perm(n,1)=d(i)
                    perm(n,2)=d(j)
                    perm(n,3)=d(k)
                    perm(n,4)=d(l)
                end if
            next
        next
    next
next
'check if permutations look OK. They are
'for i =1 to n
'    print i,
'    for j =1 to 4: print perm(i,j);:next
'    print
'next

'possible brackets
NBrackets = 11
dim Brakets$(NBrackets)
DATA "4#4#4#4"
DATA "(4#4)#4#4"
DATA "4#(4#4)#4"
DATA "4#4#(4#4)"
DATA "(4#4)#(4#4)"
DATA "(4#4#4)#4"
DATA "4#(4#4#4)"
DATA "((4#4)#4)#4"
DATA "(4#(4#4))#4"
DATA "4#((4#4)#4)"
DATA "4#(4#(4#4))"
for i = 1 to NBrackets
    read Tmpl$: Brakets$(i) = Tmpl$
next

'operations: full search
count = 0
Ops$="+ - * /"
dim Op$(3)
For op1=1 to 4
    Op$(1)=word$(Ops$,op1)
    For op2=1 to 4
        Op$(2)=word$(Ops$,op2)
        For op3=1 to 4
            Op$(3)=word$(Ops$,op3)
            'print "*"
            'substitute all brackets
            for t = 1 to NBrackets
                Tmpl$=Brakets$(t)
                'print , Tmpl$
                'now, substitute all digits: permutations.
                for p = 1 to nPerm
                    res$= ""
                    nOp=0
                    nD=0
                    for i = 1 to len(Tmpl$)
                        c$ = mid$(Tmpl$, i, 1)
                        select case c$
                        case "#"                'operations
                            nOp = nOp+1
                            res$ = res$+Op$(nOp)
                        case "4"                'digits
                            nD = nOp+1
                            res$ = res$; perm(p,nD)
                        case else               'brackets goes here
                            res$ = res$+ c$
                        end select
                    next
                    'print,, res$
                    'eval here
                    if evalWithErrCheck(res$) = 24 then
                        print "24 = ";res$
                        end 'comment it out if you want to see all versions
                    end if
                    count = count + 1
                next
            next
        Next
    Next
next

print "If you see this, probably task cannot be solved with these digits"
'print count
end

function evalWithErrCheck(expr$)
    on error goto [handler]
    evalWithErrCheck=eval(expr$)
    exit function
[handler]
end function
```



## Lua


Generic solver: pass card of any size with 1st argument and target number with second.


```lua

local SIZE = #arg[1]
local GOAL = tonumber(arg[2]) or 24

local input = {}
for v in arg[1]:gmatch("%d") do
	table.insert(input, v)
end
assert(#input == SIZE, 'Invalid input')

local operations = {'+', '-', '*', '/'}

local function BinaryTrees(vert)
	if vert == 0 then
		return {false}
	else
		local buf = {}
		for leften = 0, vert - 1 do
			local righten = vert - leften - 1
			for _, left in pairs(BinaryTrees(leften)) do
				for _, right in pairs(BinaryTrees(righten)) do
					table.insert(buf, {left, right})
				end
			end
		end
		return buf
	end
end
local trees = BinaryTrees(SIZE-1)
local c, opc, oper, str
local max = math.pow(#operations, SIZE-1)
local function op(a,b)
	opc = opc + 1
	local i = math.floor(oper/math.pow(#operations, opc-1))%#operations+1
	return '('.. a .. operations[i] .. b ..')'
end

local function EvalTree(tree)
	if tree == false then
		c = c + 1
		return input[c-1]
	else
		return op(EvalTree(tree[1]), EvalTree(tree[2]))
	end
end

local function printResult()
	for _, v in ipairs(trees) do
		for i = 0, max do
			c, opc, oper = 1, 0, i
			str = EvalTree(v)
			loadstring('res='..str)()
			if(res == GOAL) then print(str, '=', res) end
		end
	end
end

local uniq = {}
local function permgen (a, n)
	if n == 0 then
		local str = table.concat(a)
		if not uniq[str] then
			printResult()
			uniq[str] = true
		end
	else
		for i = 1, n do
			a[n], a[i] = a[i], a[n]
			permgen(a, n - 1)
			a[n], a[i] = a[i], a[n]
		end
	end
end

permgen(input, SIZE)

```


{{out}}

```txt

$ lua 24game.solve.lua 2389
(8*(9-(3*2)))	=	24
(8*((9-3)/2))	=	24
((8*(9-3))/2)	=	24
((9-3)*(8/2))	=	24
(((9-3)*8)/2)	=	24
(8*(9-(2*3)))	=	24
(8/(2/(9-3)))	=	24
((8/2)*(9-3))	=	24
((9-3)/(2/8))	=	24
((9-(3*2))*8)	=	24
(((9-3)/2)*8)	=	24
((9-(2*3))*8)	=	24
$ lua 24game.solve.lua 1172
((1+7)*(2+1))	=	24
((7+1)*(2+1))	=	24
((1+2)*(7+1))	=	24
((2+1)*(7+1))	=	24
((1+2)*(1+7))	=	24
((2+1)*(1+7))	=	24
((1+7)*(1+2))	=	24
((7+1)*(1+2))	=	24
$ lua 24game.solve.lua 123456789 1000
(2*(3+(4-(5+(6-(7*(8*(9*1))))))))	=	1000
(2*(3+(4-(5+(6-(7*(8*(9/1))))))))	=	1000
(2*(3*(4*(5+(6*(7-(8/(9*1))))))))	=	1000
(2*(3*(4*(5+(6*(7-(8/(9/1))))))))	=	1000
(2*(3+(4-(5+(6-(7*((8*9)*1)))))))	=	1000
(2*(3+(4-(5+(6-(7*((8*9)/1)))))))	=	1000
(2*(3*(4*(5+(6*(7-((8/9)*1)))))))	=	1000
(2*(3*(4*(5+(6*(7-((8/9)/1)))))))	=	1000
.....

```


=={{header|Mathematica}} / {{header|Wolfram Language}}==
The code:

```Mathematica

treeR[n_] := Table[o[trees[a], trees[n - a]], {a, 1, n - 1}]
treeR[1] := n
tree[n_] :=
 Flatten[treeR[n] //. {o[a_List, b_] :> (o[#, b] & /@ a),
    o[a_, b_List] :> (o[a, #] & /@ b)}]
game24play[val_List] :=
 Union[StringReplace[StringTake[ToString[#, InputForm], {10, -2}],
     "-1*" ~~ n_ :> "-" <> n] & /@ (HoldForm /@
      Select[Union@
        Flatten[Outer[# /. {o[q_Integer] :> #2[[q]],
             n[q_] :> #3[[q]]} &,
          Block[{O = 1, N = 1}, # /. {o :> o[O++], n :> n[N++]}] & /@
           tree[4], Tuples[{Plus, Subtract, Times, Divide}, 3],
          Permutations[Array[v, 4]], 1]],
       Quiet[(# /. v[q_] :> val[[q]]) == 24] &] /.
     Table[v[q] -> val[[q]], {q, 4}])]
```


The treeR method recursively computes all possible operator trees for a certain number of inputs. It does this by tabling all combinations of distributions of inputs across the possible values. (For example, treeR[4] is allotted 4 inputs, so it returns {o[treeR[3],treeR[1]],o[treeR[2],treeR[2]],o[treeR[1],treeR[3]]}, where o is the operator (generic at this point).
The base case treeR[1] returns n (the input).
The final output of tree[4] (the 24 game has 4 random inputs) (tree cleans up the output of treeR) is:

```txt

{o[n, o[n, o[n, n]]],
 o[n, o[o[n, n], n]],
 o[o[n, n], o[n, n]],
 o[o[n, o[n, n]], n],
 o[o[o[n, n], n], n]}
```


game24play takes the four random numbers as input and does the following (the % refers to code output from previous bullets):
*Block[{O = 1, N = 1}, # /. {o :> o[O++], n :> n[N++]}] & /@ tree[4]
** Assign ascending numbers to the input and operator placeholders.
** Ex: o[1][o[2][n[1], n[2]], o[3][n[3], n[4]]]
*Tuples[{Plus, Subtract, Times, Divide}, 3]
** Find all combinations (Tuples allows repeats) of the four allowed operations.
** Ex: {{Plus, Plus, Plus}, {Plus, Plus, Subtract}, <<60>>, {Divide, Divide, Times}, {Divide, Divide, Divide}}
*Permutations[Array[v, 4]]
** Find all permutations (Permutations does not allow repeats) of the four given values.
** Ex: {{v[1],v[2],v[3],v[4]}, {v[1],v[2],v[4],v[3]}, <<20>>, {v[4],v[3],v[1],v[2]}, {v[4],v[3],v[2],v[1]}}
*Outer[# /. {o[q_Integer] :> #2[[q]], n[q_] :> #3[[q]]} &, %%%, %%, %, 1]
** Perform an outer join on the three above lists (every combination of each element) and with each combination put into the first (the operator tree) the second (the operation at each level) and the third (the value ''indexes'', not actual values).
** Ex: v[1] + v[2] - v[3] + v[4]
*Union@Flatten[%]
** Get rid of any sublists caused by Outer and remove any duplicates (Union).
*Select[%, Quiet[(# /. v[q_] :> val[[q]]) == 24] &]
** Select the elements of the above list where substituting the real values returns 24 (and do it Quietly because of div-0 concerns).
*HoldForm /@ % /. Table[v[q] -> val[[q]], {q, 4}]
** Apply HoldForm so that substituting numbers will not cause evaluation (otherwise it would only ever return lists like {24, 24, 24}!) and substitute the numbers in.
*Union[StringReplace[StringTake[ToString[#, InputForm], {10, -2}],  "-1*" ~~ n_ :> "-" <> n] & /@ %]
**For each result, turn the expression into a string (for easy manipulation), strip the "HoldForm" wrapper, replace numbers like "-1*7" with "-7" (a idiosyncrasy of the conversion process), and remove any lingering duplicates. Some duplicates will still remain, notably constructs like "3 - 3" vs. "-3 + 3" and trivially similar expressions like "(8*3)*(6-5)" vs "(8*3)/(6-5)". Example run input and outputs:


```Mathematica
game24play[RandomInteger[{1, 9}, 4]]
```


{{out}}

```txt
{7, 2, 9, 5}
{-2 - 9 + 7*5}
```



```txt
{7, 5, 6, 2}
{6*(7 - 5 + 2), (7 - 5)*6*2, 7 + 5 + 6*2}
```



```txt
{7, 6, 7, 7}
{}
```



```txt
{3, 7, 6, 1}
{(-3 + 6)*(7 + 1), ((-3 + 7)*6)/1, (-3 + 7)*6*1,
 6 - 3*(-7 + 1), 6*(-3 + 7*1), 6*(-3 + 7/1),
 6 + 3*(7 - 1), 6*(7 - 3*1), 6*(7 - 3/1), 7 + 3*6 - 1}
```


Note that although this program is designed to be extensible to higher numbers of inputs, the largest working set in the program (the output of the Outer function can get very large:
*tree[n] returns a list with the length being the (n-1)-th [[wp:Catalan number|Catalan number]].
*Tuples[{Plus, Subtract, Times, Divide}, 3] has fixed length 64 (or ''p3'' for ''p'' operations).
*Permutations[Array[v, n]] returns n! permutations.
Therefore, the size of the working set is 64 \cdot n!\, C_{n-1} = 64 \cdot (n-1)!!!! = 64 \frac{(2n-2)!}{(n-1)!}, where n!!!! is the [[wp:quadruple factorial|quadruple factorial]]. It goes without saying that this number increases very fast. For this game, the total is 7680 elements. For higher numbers of inputs, it is {7 680, 107 520, 1 935 360, 42 577 920, 1 107 025 920, ...}.

An alternative solution operates on Mathematica expressions directly without using any inert intermediate form for the expression tree, but by using Hold to prevent Mathematica from evaluating the expression tree.


```Mathematica
evaluate[HoldForm[op_[l_, r_]]] := op[evaluate[l], evaluate[r]];
evaluate[x_] := x;
combine[l_, r_ /; evaluate[r] != 0] := {HoldForm[Plus[l, r]],
   HoldForm[Subtract[l, r]], HoldForm[Times[l, r]],
   HoldForm[Divide[l, r]] };
combine[l_, r_] := {HoldForm[Plus[l, r]], HoldForm[Subtract[l, r]],
   HoldForm[Times[l, r]]};
split[items_] :=
  Table[{items[[1 ;; i]], items[[i + 1 ;; Length[items]]]}, {i, 1,
    Length[items] - 1}];
expressions[{x_}] := {x};
expressions[items_] :=
  Flatten[Table[
    Flatten[Table[
      combine[l, r], {l, expressions[sp[[1]]]}, {r,
       expressions[sp[[2]]]}], 2], {sp, split[items]}]];

(* Must use all atoms in given order. *)
solveMaintainOrder[goal_, items_] :=
  Select[expressions[items], (evaluate[#] == goal) &];
(* Must use all atoms, but can permute them. *)
solveCanPermute[goal_, items_] :=
  Flatten[Table[
    solveMaintainOrder[goal, pitems], {pitems,
     Permutations[items]}]];
(* Can use any subset of atoms. *)
solveSubsets[goal_, items_] :=
  Flatten[Table[
    solveCanPermute[goal, is], {is,
     Subsets[items, {1, Length[items]}]}], 2];

(* Demonstration to find all the ways to create 1/5 from {2, 3, 4, 5}. *)
solveMaintainOrder[1/5, Range[2, 5]]
solveCanPermute[1/5, Range[2, 5]]
solveSubsets[1/5, Range[2, 5]]
```



## Nim


{{trans|Python Succinct}}
{{works with|Nim Compiler|0.19.4}}


```nim
import algorithm, sequtils, strformat

type
  Operation = enum
    opAdd = "+"
    opSub = "-"
    opMul = "*"
    opDiv = "/"

const Ops = @[opAdd, opSub, opMul, opDiv]

func opr(o: Operation, a, b: float): float =
  case o
  of opAdd: a + b
  of opSub: a - b
  of opMul: a * b
  of opDiv: a / b

func solve(nums: array[4, int]): string =
  func `~=`(a, b: float): bool =
    abs(a - b) <= 1e-5

  result = "not found"
  let sortedNums = nums.sorted.mapIt float it
  for i in product Ops.repeat 3:
    let (x, y, z) = (i[0], i[1], i[2])
    var nums = sortedNums
    while true:
      let (a, b, c, d) = (nums[0], nums[1], nums[2], nums[3])
      if x.opr(y.opr(a, b), z.opr(c, d)) ~= 24.0:
        return fmt"({a:0} {y} {b:0}) {x} ({c:0} {z} {d:0})"
      if x.opr(a, y.opr(b, z.opr(c, d))) ~= 24.0:
        return fmt"{a:0} {x} ({b:0} {y} ({c:0} {z} {d:0}))"
      if x.opr(y.opr(z.opr(c, d), b), a) ~= 24.0:
        return fmt"(({c:0} {z} {d:0}) {y} {b:0}) {x} {a:0}"
      if x.opr(y.opr(b, z.opr(c, d)), a) ~= 24.0:
        return fmt"({b:0} {y} ({c:0} {z} {d:0})) {x} {a:0}"
      if not nextPermutation(nums): break

proc main() =
  for nums in [
               [9, 4, 4, 5],
               [1, 7, 2, 7],
               [5, 7, 5, 4],
               [1, 4, 6, 6],
               [2, 3, 7, 3],
               [8, 7, 9, 7],
               [1, 6, 2, 6],
               [7, 9, 4, 1],
               [6, 4, 2, 2],
               [5, 7, 9, 7],
               [3, 3, 8, 8], # Difficult case requiring precise division
              ]:
    echo fmt"solve({nums}) -> {solve(nums)}"

when isMainModule: main()
```


{{out}}

```txt

solve([9, 4, 4, 5]) -> not found
solve([1, 7, 2, 7]) -> ((7 * 7) - 1) / 2
solve([5, 7, 5, 4]) -> 4 * (7 - (5 / 5))
solve([1, 4, 6, 6]) -> 6 - (6 * (1 - 4))
solve([2, 3, 7, 3]) -> (7 - 3) * (2 * 3)
solve([8, 7, 9, 7]) -> not found
solve([1, 6, 2, 6]) -> (6 - 2) / (1 / 6)
solve([7, 9, 4, 1]) -> (1 - 9) * (4 - 7)
solve([6, 4, 2, 2]) -> 2 * (4 / (2 / 6))
solve([5, 7, 9, 7]) -> (5 + 7) * (9 - 7)
solve([3, 3, 8, 8]) -> 8 / (3 - (8 / 3))

```



## OCaml



```ocaml
type expression =
  | Const of float
  | Sum  of expression * expression   (* e1 + e2 *)
  | Diff of expression * expression   (* e1 - e2 *)
  | Prod of expression * expression   (* e1 * e2 *)
  | Quot of expression * expression   (* e1 / e2 *)

let rec eval = function
  | Const c -> c
  | Sum (f, g) -> eval f +. eval g
  | Diff(f, g) -> eval f -. eval g
  | Prod(f, g) -> eval f *. eval g
  | Quot(f, g) -> eval f /. eval g

let print_expr expr =
  let open_paren prec op_prec =
    if prec > op_prec then print_string "(" in
  let close_paren prec op_prec =
    if prec > op_prec then print_string ")" in
  let rec print prec = function   (* prec is the current precedence *)
    | Const c -> Printf.printf "%g" c
    | Sum(f, g) ->
        open_paren prec 0;
        print 0 f; print_string " + "; print 0 g;
        close_paren prec 0
    | Diff(f, g) ->
        open_paren prec 0;
        print 0 f; print_string " - "; print 1 g;
        close_paren prec 0
    | Prod(f, g) ->
        open_paren prec 2;
        print 2 f; print_string " * "; print 2 g;
        close_paren prec 2
    | Quot(f, g) ->
        open_paren prec 2;
        print 2 f; print_string " / "; print 3 g;
        close_paren prec 2
  in
  print 0 expr

let rec insert v = function
  | [] -> [[v]]
  | x::xs as li -> (v::li) :: (List.map (fun y -> x::y) (insert v xs))

let permutations li =
  List.fold_right (fun x z -> List.concat (List.map (insert x) z)) li [[]]

let rec comp expr = function
  | x::xs ->
      comp (Sum (expr, x)) xs;
      comp (Diff(expr, x)) xs;
      comp (Prod(expr, x)) xs;
      comp (Quot(expr, x)) xs;
  | [] ->
      if (eval expr) = 24.0
      then (print_expr expr; print_newline())
;;

let () =
  Random.self_init();
  let digits = Array.init 4 (fun _ -> 1 + Random.int 9) in
  print_string "Input digits: ";
  Array.iter (Printf.printf " %d") digits; print_newline();
  let digits = Array.to_list(Array.map float_of_int digits) in
  let digits = List.map (fun v -> Const v) digits in
  let all = permutations digits in
  List.iter (function
    | x::xs -> comp x xs
    | [] -> assert false
  ) all
```



```txt

Input digits: 5 7 4 1
7 * 4 - 5 + 1
7 * 4 + 1 - 5
4 * 7 - 5 + 1
4 * 7 + 1 - 5
(5 - 1) * 7 - 4

```

(notice that the printer only puts parenthesis when needed)


## Perl

Will generate all possible solutions of any given four numbers according to the rules of the [[24 game]].

Note: the permute function was taken from [http://faq.perl.org/perlfaq4.html#How_do_I_permute_N_e here]

```Perl
# Fischer-Krause ordered permutation generator
# http://faq.perl.org/perlfaq4.html#How_do_I_permute_N_e
sub permute (&@) {
		my $code = shift;
		my @idx = 0..$#_;
		while ( $code->(@_[@idx]) ) {
			my $p = $#idx;
			--$p while $idx[$p-1] > $idx[$p];
			my $q = $p or return;
			push @idx, reverse splice @idx, $p;
			++$q while $idx[$p-1] > $idx[$q];
			@idx[$p-1,$q]=@idx[$q,$p-1];
		}
	}

@formats = (
	'((%d %s %d) %s %d) %s %d',
	'(%d %s (%d %s %d)) %s %d',
	'(%d %s %d) %s (%d %s %d)',
	'%d %s ((%d %s %d) %s %d)',
	'%d %s (%d %s (%d %s %d))',
	);

# generate all possible combinations of operators
@op = qw( + - * / );
@operators = map{ $a=$_; map{ $b=$_; map{ "$a $b $_" }@op }@op }@op;

while(1)
{
	print "Enter four integers or 'q' to exit: ";
	chomp($ent = <>);
	last if $ent eq 'q';


	if($ent !~ /^[1-9] [1-9] [1-9] [1-9]$/){ print "invalid input\n"; next }

	@n = split / /,$ent;
	permute { push @numbers,join ' ',@_ }@n;

	for $format (@formats)
	{
		for(@numbers)
		{
			@n = split;
			for(@operators)
			{
				@o = split;
				$str = sprintf $format,$n[0],$o[0],$n[1],$o[1],$n[2],$o[2],$n[3];
				$r = eval($str);
				print "$str\n" if $r == 24;
			}
		}
	}
}
```

{{out}}

```txt
E:\Temp>24solve.pl
Enter four integers or 'q' to exit: 1 3 3 8
((1 + 8) * 3) - 3
((1 + 8) * 3) - 3
((8 + 1) * 3) - 3
((8 - 1) * 3) + 3
((8 + 1) * 3) - 3
((8 - 1) * 3) + 3
(3 * (1 + 8)) - 3
(3 * (8 + 1)) - 3
(3 * (8 - 1)) + 3
(3 * (1 + 8)) - 3
(3 * (8 + 1)) - 3
(3 * (8 - 1)) + 3
3 - ((1 - 8) * 3)
3 + ((8 - 1) * 3)
3 - ((1 - 8) * 3)
3 + ((8 - 1) * 3)
3 - (3 * (1 - 8))
3 + (3 * (8 - 1))
3 - (3 * (1 - 8))
3 + (3 * (8 - 1))
Enter four integers or 'q' to exit: q

E:\Temp>
```



## Perl 6



### With EVAL

A loose translation of the Perl entry. Does not return every possible permutation of the possible solutions. Filters out duplicates (from repeated digits) and only reports the solution for a particular order of digits and operators with the fewest parenthesis (avoids reporting duplicate solutions only differing by unnecessary parenthesis). Does not guarantee the order in which results are returned.

Since Perl 6 uses Rational numbers for division (whenever possible) there is no loss of precision as is common with floating point division. So a comparison like  (1 + 7) / (1 / 3) == 24 "Just Works"


```perl6
use MONKEY-SEE-NO-EVAL;

my @digits;
my $amount = 4;

# Get $amount digits from the user,
# ask for more if they don't supply enough
while @digits.elems < $amount {
    @digits.append: (prompt "Enter {$amount - @digits} digits from 1 to 9, "
    ~ '(repeats allowed): ').comb(/<[1..9]>/);
}
# Throw away any extras
@digits = @digits[^$amount];

# Generate combinations of operators
my @ops = [X,] <+ - * /> xx 3;

# Enough sprintf formats to cover most precedence orderings
my @formats = (
    '%d %s %d %s %d %s %d',
    '(%d %s %d) %s %d %s %d',
    '(%d %s %d %s %d) %s %d',
    '((%d %s %d) %s %d) %s %d',
    '(%d %s %d) %s (%d %s %d)',
    '%d %s (%d %s %d %s %d)',
    '%d %s (%d %s (%d %s %d))',
);

# Brute force test the different permutations
(unique @digits.permutations).race.map: -> @p {
    for @ops -> @o {
        for @formats -> $format {
            my $string = sprintf $format, flat roundrobin(|@p; |@o);
            my $result = EVAL($string);
            say "$string = 24" and last if $result and $result == 24;
        }
    }
}

# Only return unique sub-arrays
sub unique (@array) {
    my %h = map { $_.Str => $_ }, @array;
    %h.values;
}
```


{{out}}

```txt

Enter 4 digits from 1 to 9, (repeats allowed): 3711
(1 + 7) * 3 * 1 = 24
(1 + 7) * 3 / 1 = 24
(1 * 3) * (1 + 7) = 24
3 * (1 + 1 * 7) = 24
(3 * 1) * (1 + 7) = 24
3 * (1 / 1 + 7) = 24
(3 / 1) * (1 + 7) = 24
3 / (1 / (1 + 7)) = 24
(1 + 7) * 1 * 3 = 24
(1 + 7) / 1 * 3 = 24
(1 + 7) / (1 / 3) = 24
(1 * 7 + 1) * 3 = 24
(7 + 1) * 3 * 1 = 24
(7 + 1) * 3 / 1 = 24
(7 - 1) * (3 + 1) = 24
(1 + 1 * 7) * 3 = 24
(1 * 1 + 7) * 3 = 24
(1 / 1 + 7) * 3 = 24
(3 + 1) * (7 - 1) = 24
3 * (1 + 7 * 1) = 24
3 * (1 + 7 / 1) = 24
(3 * 1) * (7 + 1) = 24
(3 / 1) * (7 + 1) = 24
3 / (1 / (7 + 1)) = 24
(1 + 3) * (7 - 1) = 24
(1 * 3) * (7 + 1) = 24
(7 + 1) * 1 * 3 = 24
(7 + 1) / 1 * 3 = 24
(7 + 1) / (1 / 3) = 24
(7 - 1) * (1 + 3) = 24
(7 * 1 + 1) * 3 = 24
(7 / 1 + 1) * 3 = 24
3 * (7 + 1 * 1) = 24
3 * (7 + 1 / 1) = 24
3 * (7 * 1 + 1) = 24
3 * (7 / 1 + 1) = 24

Enter 4 digits from 1 to 9, (repeats allowed):  5 5 5 5
5 * 5 - 5 / 5 = 24

Enter 4 digits from 1 to 9, (repeats allowed): 8833
8 / (3 - 8 / 3) = 24

```



### No EVAL

Alternately, a version that doesn't use EVAL. More general case. Able to handle 3 or 4 integers, able to select the goal value.


```perl6
my %*SUB-MAIN-OPTS = :named-anywhere;

sub MAIN (*@parameters, Int :$goal = 24) {
    my @numbers;
    if +@parameters == 1 {
        @numbers = @parameters[0].comb(/\d/);
        USAGE() and exit unless 2 < @numbers < 5;
    } elsif +@parameters > 4 {
        USAGE() and exit;
    } elsif +@parameters == 3|4 {
        @numbers = @parameters;
        USAGE() and exit if @numbers.any ~~ /<-[-\d]>/;
    } else {
        USAGE();
        exit if +@parameters == 2;
        @numbers = 3,3,8,8;
        say 'Running demonstration with: ', |@numbers, "\n";
    }
    solve @numbers, $goal
}

sub solve (@numbers, $goal = 24) {
    my @operators = < + - * / >;
    my @ops   = [X] @operators xx (@numbers - 1);
    my @perms = @numbers.permutations.unique( :with(&[eqv]) );
    my @order = (^(@numbers - 1)).permutations;
    my @sol;
    @sol[250]; # preallocate some stack space

    my $batch = ceiling +@perms/4;

    my atomicint $i;
    @perms.race(:batch($batch)).map: -> @p {
        for @ops -> @o {
            for @order -> @r {
                my $result = evaluate(@p, @o, @r);
                @sol[$i⚛++] = $result[1] if $result[0] and $result[0] == $goal;
            }
        }
    }
    @sol.=unique;
    say @sol.join: "\n";
    my $pl = +@sol == 1 ?? '' !! 's';
    my $sg = $pl ?? '' !! 's';
    say +@sol, " equation{$pl} evaluate{$sg} to $goal using: {@numbers}";
}

sub evaluate ( @digit, @ops, @orders ) {
    my @result = @digit.map: { [ $_, $_ ] };
    my @offset = 0 xx +@orders;

    for ^@orders {
        my $this  = @orders[$_];
        my $order = $this - @offset[$this];
        my $op    = @ops[$this];
        my $result = op( $op, @result[$order;0], @result[$order+1;0] );
        return [ NaN, Str ] unless defined $result;
        my $string = "({@result[$order;1]} $op {@result[$order+1;1]})";
        @result.splice: $order, 2, [ $[ $result, $string ] ];
        @offset[$_]++ if $order < $_ for ^@offset;
    }
    @result[0];
}

multi op ( '+', $m, $n ) { $m + $n }
multi op ( '-', $m, $n ) { $m - $n }
multi op ( '/', $m, $n ) { $n == 0 ?? fail() !! $m / $n }
multi op ( '*', $m, $n ) { $m * $n }

my $txt = "\e[0;96m";
my $cmd = "\e[0;92m> {$*EXECUTABLE-NAME} {$*PROGRAM-NAME}";
sub USAGE {
    say qq:to
    '
### ==================================================================
'
    {$txt}Supply 3 or 4 integers on the command line, and optionally a value
    to equate to.

    Integers may be all one group: {$cmd} 2233{$txt}
          Or, separated by spaces: {$cmd} 2 4 6 7{$txt}

    If you wish to supply multi-digit or negative numbers, you must
        separate them with spaces: {$cmd} -2 6 12{$txt}

    If you wish to use a different equate value,
    supply a new --goal parameter: {$cmd} --goal=17 2 -3 1 9{$txt}

    If you don't supply any parameters, will use 24 as the goal, will run a
    demo and will show this message.\e[0m

### ==================================================================

}
```

{{out}}
When supplied 1399 on the command line:

```txt
(((9 - 1) / 3) * 9)
((9 - 1) / (3 / 9))
((9 / 3) * (9 - 1))
(9 / (3 / (9 - 1)))
((9 * (9 - 1)) / 3)
(9 * ((9 - 1) / 3))
(((9 - 1) * 9) / 3)
((9 - 1) * (9 / 3))
8 equations evaluate to 24 using: 1 3 9 9
```



## Phix


```Phix
--
-- 24_game_solve.exw
--
### ===========

--
-- Write a function that given four digits subject to the rules of the 24 game, computes an expression to solve the game if possible.
-- Show examples of solutions generated by the function
--
-- The following 5 parse expressions are possible.
-- Obviously numbers 1234 represent 24 permutations from
--  {1,2,3,4} to {4,3,2,1} of indexes to the real numbers.
-- Likewise "+-*" is like "123" representing 64 combinations
--  from {1,1,1} to {4,4,4} of indexes to "+-*/".
-- Both will be replaced if/when the strings get printed.
--
constant OPS = "+-*/"
constant expressions = {"1+(2-(3*4))",
                        "1+((2-3)*4)",
                        "(1+2)-(3*4)",
                        "(1+(2-3))*4",
                        "((1+2)-3)*4"}  -- (equivalent to "1+2-3*4")
--TODO: I'm sure there is a simple (recursive) way to programatically
--      generate the above (for n=2..9) but I'm not seeing it yet...

-- The above represented as three sequential operations (the result gets
--  left in <(map)1>, ie vars[perms[operations[i][3][1]]] aka vars[lhs]):
constant operations = {{{3,'*',4},{2,'-',3},{1,'+',2}}, --3*=4; 2-=3; 1+=2
                       {{2,'-',3},{2,'*',4},{1,'+',2}}, --2-=3; 2*=4; 1+=2
                       {{1,'+',2},{3,'*',4},{1,'-',3}}, --1+=2; 3*=4; 1-=3
                       {{2,'-',3},{1,'+',2},{1,'*',4}}, --2-=3; 1+=2; 1*=4
                       {{1,'+',2},{1,'-',3},{1,'*',4}}} --1+=2; 1-=3; 1*=4
--TODO: ... and likewise for parsing "expressions" to yield "operations".

function evalopset(sequence opset, sequence perms, sequence ops, sequence vars)
-- invoked 5*24*64 = 7680 times, to try all possible expressions/vars/operators
-- (btw, vars is copy-on-write, like all parameters not explicitly returned, so
--       we can safely re-use it without clobbering the callee version.)
integer lhs,op,rhs
atom inf
    for i=1 to length(opset) do
        {lhs,op,rhs} = opset[i]
        lhs = perms[lhs]
        op = ops[find(op,OPS)]
        rhs = perms[rhs]
        if op='+' then
            vars[lhs] += vars[rhs]
        elsif op='-' then
            vars[lhs] -= vars[rhs]
        elsif op='*' then
            vars[lhs] *= vars[rhs]
        elsif op='/' then
            if vars[rhs]=0 then inf = 1e300*1e300 return inf end if
            vars[lhs] /= vars[rhs]
        end if
    end for
    return vars[lhs]
end function

integer nSolutions
sequence xSolutions

procedure success(string expr, sequence perms, sequence ops, sequence vars, atom r)
integer ch
    for i=1 to length(expr) do
        ch = expr[i]
        if ch>='1' and ch<='9' then
            expr[i] = vars[perms[ch-'0']]+'0'
        else
            ch = find(ch,OPS)
            if ch then
                expr[i] = ops[ch]
            end if
        end if
    end for
    if not find(expr,xSolutions) then
        -- avoid duplicates for eg {1,1,2,7} because this has found
        -- the "same" solution but with the 1st and 2nd 1s swapped,
        -- and likewise whenever an operator is used more than once.
        printf(1,"success: %s = %s\n",{expr,sprint(r)})
        nSolutions += 1
        xSolutions = append(xSolutions,expr)
    end if
end procedure

procedure tryperms(sequence perms, sequence ops, sequence vars)
atom r
    for i=1 to length(operations) do
        -- 5 parse expressions
        r = evalopset(operations[i], perms, ops, vars)
        if r=24 then
            success(expressions[i], perms, ops, vars, r)
        end if
    end for
end procedure

include builtins/factorial.e
include builtins/permute.e

procedure tryops(sequence ops, sequence vars)
    for p=1 to factorial(4) do
        -- 24 var permutations
        tryperms(permute(p,{1,2,3,4}),ops, vars)
    end for
end procedure

global procedure solve24(sequence vars)
    nSolutions = 0
    xSolutions = {}
    for op1=1 to 4 do
        for op2=1 to 4 do
            for op3=1 to 4 do
                -- 64 operator combinations
                tryops({OPS[op1],OPS[op2],OPS[op3]},vars)
            end for
        end for
    end for

    printf(1,"\n%d solutions\n",{nSolutions})
end procedure

    solve24({1,1,2,7})
    if getc(0) then end if
```

{{out}}

```txt

success: (1+2)*(7+1) = 24
success: (1+7)*(1+2) = 24
success: (1+2)*(1+7) = 24
success: (2+1)*(7+1) = 24
success: (7+1)*(1+2) = 24
success: (2+1)*(1+7) = 24
success: (1+7)*(2+1) = 24
success: (7+1)*(2+1) = 24

8 solutions

```



## Picat


```Picat
import util.

main =>
  Target=24,
  Nums = [5,6,7,8],

  All=findall(Expr, solve_num(Nums,Target,Expr)),
  foreach(Expr in All) println(Expr.flatten()) end,
  println(len=All.length),
  nl.

% A string based approach, inspired by - among others - the Perl6 solution.
solve_num(Nums, Target,Expr) =>
   Patterns = [
               "A X B Y C Z D",
               "(A X B) Y C Z D",
               "(A X B Y C) Z D",
               "((A X B) Y C) Z D",
               "(A X B) Y (C Z D)",
               "A X (B Y C Z D)",
               "A X (B Y (C Z D))"
               ],
   permutation(Nums,[A,B,C,D]),
   Syms = [+,-,*,/],
   member(X ,Syms),
   member(Y ,Syms),
   member(Z ,Syms),
   member(Pattern,Patterns),
   Expr = replace_all(Pattern,
                     "ABCDXYZ",
                     [A,B,C,D,X,Y,Z]),
   catch(Target =:= Expr.eval(), E, ignore(E)).

eval(Expr) = parse_term(Expr.flatten()).apply().

ignore(_E) => fail. % ignore zero_divisor errors

% Replace all occurrences in S with From -> To.
replace_all(S,From,To) = Res =>
   R = S,
   foreach({F,T} in zip(From,To))
     R := replace(R, F,T.to_string())
   end,
   Res = R.


```


Test:


```txt

Picat> main

(5 + 7 - 8) * 6
((5 + 7) - 8) * 6
(5 + 7) * (8 - 6)
(5 - 8 + 7) * 6
((5 - 8) + 7) * 6
6 * (5 + 7 - 8)
6 * (5 + (7 - 8))
6 * (5 - 8 + 7)
6 * (5 - (8 - 7))
6 * (7 + 5 - 8)
6 * (7 + (5 - 8))
6 * (7 - 8 + 5)
6 * (7 - (8 - 5))
(6 * 8) / (7 - 5)
6 * (8 / (7 - 5))
(7 + 5 - 8) * 6
((7 + 5) - 8) * 6
(7 + 5) * (8 - 6)
(7 - 8 + 5) * 6
((7 - 8) + 5) * 6
(8 - 6) * (5 + 7)
(8 - 6) * (7 + 5)
(8 * 6) / (7 - 5)
8 * (6 / (7 - 5))
len = 24


```


Another approach:


```Picat
import util.

main =>
  Target=24,
  Nums = [5,6,7,8],
  _ = findall(Expr, solve_num2(Nums,Target)),
  nl.


solve_num2(Nums, Target) =>
    Syms = [+,-,*,/],
    Perms = permutations([I.to_string() : I in Nums]),
    Seen = new_map(), % weed out duplicates
    foreach(X in Syms,Y in Syms, Z in Syms)
       foreach(P in Perms)
         [A,B,C,D] = P,
         if catch(check(A,X,B,Y,C,Z,D,Target,Expr),E,ignore(E)),
            not Seen.has_key(Expr) then
              println(Expr.flatten()=Expr.eval().round()),
              Seen.put(Expr,1)
         end
      end
   end.

to_string2(Expr) = [E.to_string() : E in Expr].flatten().

ignore(_E) => fail. % ignore zero_divisor errors

check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
   Expr = ["(",A,Y,B,")",X,"(",C,Z,D,")"].to_string2(),
   Target =:= Expr.eval().

check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
   Expr = [A,X,"(",B,Y,"(",C,Z,D,")",")"].to_string2(),
   Target =:= Expr.eval().

check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
   Expr = ["(","(",C,Z,D,")",Y,B,")",X,A].to_string2(),
   Target =:= Expr.eval().

check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
   Expr = ["(",B,Y,"(",C,Z,D,")",")",X,A].to_string2(),
   Target =:= Expr.eval().

check(A,X,B,Y,C,Z,D,Target,Expr) =>
   Expr = [A,X,"(","(",B,Y,C,")", Z,D,")"].to_string2(),
   Target =:= Expr.eval().

```


Test:


```txt

> main
6*(5+(7-8)) = 24
6*(7+(5-8)) = 24
(5+7)*(8-6) = 24
(7+5)*(8-6) = 24
6*((7-8)+5) = 24
6*((5-8)+7) = 24
((5+7)-8)*6 = 24
((7+5)-8)*6 = 24
(8-6)*(5+7) = 24
(8-6)*(7+5) = 24
6*(7-(8-5)) = 24
6*(5-(8-7)) = 24
6*(8/(7-5)) = 24
8*(6/(7-5)) = 24
6/((7-5)/8) = 24
8/((7-5)/6) = 24
(6*8)/(7-5) = 24
(8*6)/(7-5) = 24


```



## PicoLisp

We use Pilog (PicoLisp Prolog) to solve this task

```PicoLisp
(be play24 (@Lst @Expr)                # Define Pilog rule
   (permute @Lst (@A @B @C @D))
   (member @Op1 (+ - * /))
   (member @Op2 (+ - * /))
   (member @Op3 (+ - * /))
   (or
      ((equal @Expr (@Op1 (@Op2 @A @B) (@Op3 @C @D))))
      ((equal @Expr (@Op1 @A (@Op2 @B (@Op3 @C @D))))) )
   (^ @ (= 24 (catch '("Div/0") (eval (-> @Expr))))) )

(de play24 (A B C D)                   # Define PicoLisp function
   (pilog
      (quote
         @L (list A B C D)
         (play24 @L @X) )
      (println @X) ) )

(play24 5 6 7 8)                       # Call 'play24' function
```

{{out}}

```txt
(* (+ 5 7) (- 8 6))
(* 6 (+ 5 (- 7 8)))
(* 6 (- 5 (- 8 7)))
(* 6 (- 5 (/ 8 7)))
(* 6 (+ 7 (- 5 8)))
(* 6 (- 7 (- 8 5)))
(* 6 (/ 8 (- 7 5)))
(/ (* 6 8) (- 7 5))
(* (+ 7 5) (- 8 6))
(* (- 8 6) (+ 5 7))
(* (- 8 6) (+ 7 5))
(* 8 (/ 6 (- 7 5)))
(/ (* 8 6) (- 7 5))
```



## ProDOS

Note
This example uses the math module:

```ProDOS
editvar /modify -random- = <10
:a
editvar /newvar /withothervar /value=-random- /title=1
editvar /newvar /withothervar /value=-random- /title=2
editvar /newvar /withothervar /value=-random- /title=3
editvar /newvar /withothervar /value=-random- /title=4
printline These are your four digits: -1- -2- -3- -4-
printline Use an algorithm to make the number 24.
editvar /newvar /value=a /userinput=1 /title=Algorithm:
do -a-
if -a- /hasvalue 24 printline Your algorithm worked! & goto :b (
) else printline Your algorithm did not work.
editvar /newvar /value=b /userinput=1 /title=Do you want to see how you could have done it?
if -b- /hasvalue y goto :c else goto :b
:b
editvar /newvar /value=c /userinput=1 /title=Do you want to play again?
if -c- /hasvalue y goto :a else exitcurrentprogram
:c
editvar /newvar /value=do -1- + -2- + -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- - -2- + -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- / -2- + -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- * -2- + -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- - -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- / -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- * -3- + -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- + -3- - -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- + -3- / -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- + -2- + -3- * -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- - -2- - -3- - -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- / -2- / -3- / -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
editvar /newvar /value=do -1- * -2- * -3- * -4- /title=c & do -c- >d & if -d- /hasvalue 24 goto :solve
:solve
printline you could have done it by doing -c-
stoptask
goto :b
```


{{out}}

```txt
These are your four digits: 1 4 5 2
Use an algorithm to make the number 24.
Algorithm: 4 + 2 - 5 + 1
Your algorithm did not work.
Do you want to play again? y

These are your four digits: 1 8 9 6
Use an algorithm to make the number 24.
Algorithm: 1 + 8 + 9 + 6
Your algorithm worked!
Do you want to play again? n
```



## Prolog

Works with SWI-Prolog.
The game is generic, you can choose to play with a goal different of 24, any number of numbers in other ranges than 1 .. 9 !
rdiv/2 is use instead of //2 to enable the program to solve difficult cases as [3 3 8 8]. ```Prolog play24(Len, Range, Goal) :- game(Len, Range, Goal, L, S), maplist(my_write, L), format(': ~w~n', [S]). game(Len, Range, Value, L, S) :- length(L, Len), maplist(choose(Range), L), compute(L, Value, [], S). choose(Range, V) :- V is random(Range) + 1. write_tree([M], [M]). write_tree([+, M, N], S) :- write_tree(M, MS), write_tree(N, NS), append(MS, [+ | NS], S). write_tree([-, M, N], S) :- write_tree(M, MS), write_tree(N, NS), ( is_add(N) -> append(MS, [-, '(' | NS], Temp), append(Temp, ')', S) ; append(MS, [- | NS], S)). write_tree([Op, M, N], S) :- member(Op, [*, /]), write_tree(M, MS), write_tree(N, NS), ( is_add(M) -> append(['(' | MS], [')'], TempM) ; TempM = MS), ( is_add(N) -> append(['(' | NS], [')'], TempN) ; TempN = NS), append(TempM, [Op | TempN], S). is_add([Op, _, _]) :- member(Op, [+, -]). compute([Value], Value, [[_R-S1]], S) :- write_tree(S1, S2), with_output_to(atom(S), maplist(write, S2)). compute(L, Value, CS, S) :- select(M, L, L1), select(N, L1, L2), next_value(M, N, R, CS, Expr), compute([R|L2], Value, Expr, S). next_value(M, N, R, CS,[[R - [+, M1, N1]] | CS2]) :- R is M+N, ( member([M-ExprM], CS) -> select([M-ExprM], CS, CS1), M1 = ExprM ; M1 = [M], CS1 = CS ), ( member([N-ExprN], CS1) -> select([N-ExprN], CS1, CS2), N1 = ExprN ; N1 = [N], CS2 = CS1 ). next_value(M, N, R, CS,[[R - [-, M1, N1]] | CS2]) :- R is M-N, ( member([M-ExprM], CS) -> select([M-ExprM], CS, CS1), M1 = ExprM ; M1 = [M], CS1 = CS ), ( member([N-ExprN], CS1) -> select([N-ExprN], CS1, CS2), N1 = ExprN ; N1 = [N], CS2 = CS1 ). next_value(M, N, R, CS,[[R - [*, M1, N1]] | CS2]) :- R is M*N, ( member([M-ExprM], CS) -> select([M-ExprM], CS, CS1), M1 = ExprM ; M1 = [M], CS1 = CS ), ( member([N-ExprN], CS1) -> select([N-ExprN], CS1, CS2), N1 = ExprN ; N1 = [N], CS2 = CS1 ). next_value(M, N, R, CS,[[R - [/, M1, N1]] | CS2]) :- N \= 0, R is rdiv(M,N), ( member([M-ExprM], CS) -> select([M-ExprM], CS, CS1), M1 = ExprM ; M1 = [M], CS1 = CS ), ( member([N-ExprN], CS1) -> select([N-ExprN], CS1, CS2), N1 = ExprN ; N1 = [N], CS2 = CS1 ). my_write(V) :- format('~w ', [V]). ``` {{out}} ```txt ?- play24(4,9, 24). 6 2 3 4 : (6-2+4)*3 true ; 6 2 3 4 : 3*(6-2+4) true ; 6 2 3 4 : (6-2+4)*3 true ; 6 2 3 4 : 3*(6-2+4) true ; 6 2 3 4 : (6*2-4)*3 true ; 6 2 3 4 : 3*(6*2-4) true ; 6 2 3 4 : 3*4+6*2 true ; 6 2 3 4 : 3*4+6*2 true ; 6 2 3 4 : 4*3+6*2 true ; 6 2 3 4 : 4*3+6*2 true ; 6 2 3 4 : (6/2+3)*4 true ; 6 2 3 4 : 4*(6/2+3) true ; 6 2 3 4 : (6/2+3)*4 true ; 6 2 3 4 : 4*(6/2+3) true ; 6 2 3 4 : (6-3)*2*4 true ; 6 2 3 4 : 4*(6-3)*2 true ; 6 2 3 4 : (6-3)*4*2 ... ?- play24(7,99, 1). 66 40 2 76 95 59 12 : (66+40)/2-76+95-59-12 true ; 66 40 2 76 95 59 12 : (66+40)/2-76+95-12-59 true ; 66 40 2 76 95 59 12 : (66+40)/2-76-59+95-12 true ; 66 40 2 76 95 59 12 : (66+40)/2-76-59-12+95 true ; 66 40 2 76 95 59 12 : 95+(66+40)/2-76-59-12 true ; 66 40 2 76 95 59 12 : 95+(66+40)/2-76-59-12 true ; 66 40 2 76 95 59 12 : 95-12+(66+40)/2-76-59 true ; 66 40 2 76 95 59 12 : (66+40)/2-76-59+95-12 .... ``` ### Minimal version {{incorrect|Prolog|Does not follow 24 game rules for division: Division should use floating point or rational arithmetic, etc, to preserve remainders.}} {{Works with|GNU Prolog|1.4.4}} Little efforts to remove duplicates (e.g. output for [4,6,9,9]). ```prolog :- initialization(main). solve(N,Xs,Ast) :- Err = evaluation_error(zero_divisor) , gen_ast(Xs,Ast), catch(Ast =:= N, error(Err,_), fail) . gen_ast([N],N) :- between(1,9,N). gen_ast(Xs,Ast) :- Ys = [_|_], Zs = [_|_], split(Xs,Ys,Zs) , ( member(Op, [(+),(*)]), Ys @=< Zs ; member(Op, [(-),(//)]) ) , gen_ast(Ys,A), gen_ast(Zs,B), Ast =.. [Op,A,B] . split(Xs,Ys,Zs) :- sublist(Ys,Xs), select_all(Ys,Xs,Zs). % where select_all([],Xs,Xs). select_all([Y|Ys],Xs,Zs) :- select(Y,Xs,X1), !, select_all(Ys,X1,Zs). test(T) :- solve(24, [2,3,8,9], T). main :- forall(test(T), (write(T), nl)), halt. ``` {{Output}} ```txt (9-3)*8//2 3*8-2//9 (8+9)//2*3 (8-2//9)*3 (2//9+8)*3 (2+8*9)//3 2//9+3*8 8//2*(9-3) (9-3)//2*8 (9-2*3)*8 (3-2//9)*8 (2//9+3)*8 (2+9)//3*8 ``` ## Python ==={{header|Python}} Original=== The function is called '''solve''', and is integrated into the game player. The docstring of the solve function shows examples of its use when isolated at the Python command line. ```Python ''' The 24 Game Player Given any four digits in the range 1 to 9, which may have repetitions, Using just the +, -, *, and / operators; and the possible use of brackets, (), show how to make an answer of 24. An answer of "q" will quit the game. An answer of "!" will generate a new set of four digits. An answer of "!!" will ask you for a new set of four digits. An answer of "?" will compute an expression for the current digits. Otherwise you are repeatedly asked for an expression until it evaluates to 24 Note: you cannot form multiple digit numbers from the supplied digits, so an answer of 12+12 when given 1, 2, 2, and 1 would not be allowed. ''' from __future__ import division, print_function from itertools import permutations, combinations, product, \ chain from pprint import pprint as pp from fractions import Fraction as F import random, ast, re import sys if sys.version_info[0] < 3: input = raw_input from itertools import izip_longest as zip_longest else: from itertools import zip_longest def choose4(): 'four random digits >0 as characters' return [str(random.randint(1,9)) for i in range(4)] def ask4(): 'get four random digits >0 from the player' digits = '' while len(digits) != 4 or not all(d in '123456789' for d in digits): digits = input('Enter the digits to solve for: ') digits = ''.join(digits.strip().split()) return list(digits) def welcome(digits): print (__doc__) print ("Your four digits: " + ' '.join(digits)) def check(answer, digits): allowed = set('() +-*/\t'+''.join(digits)) ok = all(ch in allowed for ch in answer) and \ all(digits.count(dig) == answer.count(dig) for dig in set(digits)) \ and not re.search('\d\d', answer) if ok: try: ast.parse(answer) except: ok = False return ok def solve(digits): """\ >>> for digits in '3246 4788 1111 123456 1127 3838'.split(): solve(list(digits)) Solution found: 2 + 3 * 6 + 4 '2 + 3 * 6 + 4' Solution found: ( 4 + 7 - 8 ) * 8 '( 4 + 7 - 8 ) * 8' No solution found for: 1 1 1 1 '!' Solution found: 1 + 2 + 3 * ( 4 + 5 ) - 6 '1 + 2 + 3 * ( 4 + 5 ) - 6' Solution found: ( 1 + 2 ) * ( 1 + 7 ) '( 1 + 2 ) * ( 1 + 7 )' Solution found: 8 / ( 3 - 8 / 3 ) '8 / ( 3 - 8 / 3 )' >>> """ digilen = len(digits) # length of an exp without brackets exprlen = 2 * digilen - 1 # permute all the digits digiperm = sorted(set(permutations(digits))) # All the possible operator combinations opcomb = list(product('+-*/', repeat=digilen-1)) # All the bracket insertion points: brackets = ( [()] + [(x,y) for x in range(0, exprlen, 2) for y in range(x+4, exprlen+2, 2) if (x,y) != (0,exprlen+1)] + [(0, 3+1, 4+2, 7+3)] ) # double brackets case for d in digiperm: for ops in opcomb: if '/' in ops: d2 = [('F(%s)' % i) for i in d] # Use Fractions for accuracy else: d2 = d ex = list(chain.from_iterable(zip_longest(d2, ops, fillvalue=''))) for b in brackets: exp = ex[::] for insertpoint, bracket in zip(b, '()'*(len(b)//2)): exp.insert(insertpoint, bracket) txt = ''.join(exp) try: num = eval(txt) except ZeroDivisionError: continue if num == 24: if '/' in ops: exp = [ (term if not term.startswith('F(') else term[2]) for term in exp ] ans = ' '.join(exp).rstrip() print ("Solution found:",ans) return ans print ("No solution found for:", ' '.join(digits)) return '!' def main(): digits = choose4() welcome(digits) trial = 0 answer = '' chk = ans = False while not (chk and ans == 24): trial +=1 answer = input("Expression %i: " % trial) chk = check(answer, digits) if answer == '?': solve(digits) answer = '!' if answer.lower() == 'q': break if answer == '!': digits = choose4() trial = 0 print ("\nNew digits:", ' '.join(digits)) continue if answer == '!!': digits = ask4() trial = 0 print ("\nNew digits:", ' '.join(digits)) continue if not chk: print ("The input '%s' was wonky!" % answer) else: if '/' in answer: # Use Fractions for accuracy in divisions answer = ''.join( (('F(%s)' % char) if char in '123456789' else char) for char in answer ) ans = eval(answer) print (" = ", ans) if ans == 24: print ("Thats right!") print ("Thank you and goodbye") main() ``` {{out}} ```txt The 24 Game Player Given any four digits in the range 1 to 9, which may have repetitions, Using just the +, -, *, and / operators; and the possible use of brackets, (), show how to make an answer of 24. An answer of "q" will quit the game. An answer of "!" will generate a new set of four digits. An answer of "?" will compute an expression for the current digits. Otherwise you are repeatedly asked for an expression until it evaluates to 24 Note: you cannot form multiple digit numbers from the supplied digits, so an answer of 12+12 when given 1, 2, 2, and 1 would not be allowed. Your four digits: 6 7 9 5 Expression 1: ? Solution found: 6 - ( 5 - 7 ) * 9 Thank you and goodbye ``` ### Difficult case requiring precise division The digits 3,3,8 and 8 have a solution that is not equal to 24 when using Pythons double-precision floating point because of a division in all answers. The solver above switches to precise fractional arithmetic when division is involved and so can both recognise and solve for cases like this, (rather than allowing some range of closeness to 24). '''Evaluation needing precise division''' {{out}} ```txt ... Expression 1: !! Enter the digits to solve for: 3388 New digits: 3 3 8 8 Expression 1: 8/(3-(8/3)) = 24 Thats right! Thank you and goodbye ``` '''Solving needing precise division''' {{out}} ```txt ... Expression 1: !! Enter the digits to solve for: 3388 New digits: 3 3 8 8 Expression 1: ? Solution found: 8 / ( 3 - 8 / 3 ) ``` ==={{header|Python}} Succinct=== Based on the Julia example above. ```python # -*- coding: utf-8 -*- import operator from itertools import product, permutations def mydiv(n, d): return n / d if d != 0 else 9999999 syms = [operator.add, operator.sub, operator.mul, mydiv] op = {sym: ch for sym, ch in zip(syms, '+-*/')} def solve24(nums): for x, y, z in product(syms, repeat=3): for a, b, c, d in permutations(nums): if round(x(y(a,b),z(c,d)),5) == 24: return f"({a} {op[y]} {b}) {op[x]} ({c} {op[z]} {d})" elif round(x(a,y(b,z(c,d))),5) == 24: return f"{a} {op[x]} ({b} {op[y]} ({c} {op[z]} {d}))" elif round(x(y(z(c,d),b),a),5) == 24: return f"(({c} {op[z]} {d}) {op[y]} {b}) {op[x]} {a}" elif round(x(y(b,z(c,d)),a),5) == 24: return f"({b} {op[y]} ({c} {op[z]} {d})) {op[x]} {a}" return '--Not Found--' if __name__ == '__main__': #nums = eval(input('Four integers in the range 1:9 inclusive, separated by commas: ')) for nums in [ [9,4,4,5], [1,7,2,7], [5,7,5,4], [1,4,6,6], [2,3,7,3], [8,7,9,7], [1,6,2,6], [7,9,4,1], [6,4,2,2], [5,7,9,7], [3,3,8,8], # Difficult case requiring precise division ]: print(f"solve24({nums}) -> {solve24(nums)}") ``` {{out}} ```txt solve24([9, 4, 4, 5]) -> --Not Found-- solve24([1, 7, 2, 7]) -> ((7 * 7) - 1) / 2 solve24([5, 7, 5, 4]) -> 4 * (7 - (5 / 5)) solve24([1, 4, 6, 6]) -> 6 + (6 * (4 - 1)) solve24([2, 3, 7, 3]) -> ((2 + 7) * 3) - 3 solve24([8, 7, 9, 7]) -> --Not Found-- solve24([1, 6, 2, 6]) -> 6 + (6 * (1 + 2)) solve24([7, 9, 4, 1]) -> (7 - 4) * (9 - 1) solve24([6, 4, 2, 2]) -> (2 - 2) + (6 * 4) solve24([5, 7, 9, 7]) -> (5 + 7) * (9 - 7) solve24([3, 3, 8, 8]) -> 8 / (3 - (8 / 3)) ``` ==={{header|Python}} Recursive === This works for any amount of numbers by recursively picking two and merging them using all available operands until there is only one value left. ```python # -*- coding: utf-8 -*- # Python 3 from operator import mul, sub, add def div(a, b): if b == 0: return 999999.0 return a / b ops = {mul: '*', div: '/', sub: '-', add: '+'} def solve24(num, how, target): if len(num) == 1: if round(num[0], 5) == round(target, 5): yield str(how[0]).replace(',', '').replace("'", '') else: for i, n1 in enumerate(num): for j, n2 in enumerate(num): if i != j: for op in ops: new_num = [n for k, n in enumerate(num) if k != i and k != j] + [op(n1, n2)] new_how = [h for k, h in enumerate(how) if k != i and k != j] + [(how[i], ops[op], how[j])] yield from solve24(new_num, new_how, target) tests = [ [1, 7, 2, 7], [5, 7, 5, 4], [1, 4, 6, 6], [2, 3, 7, 3], [1, 6, 2, 6], [7, 9, 4, 1], [6, 4, 2, 2], [5, 7, 9, 7], [3, 3, 8, 8], # Difficult case requiring precise division [8, 7, 9, 7], # No solution [9, 4, 4, 5], # No solution ] for nums in tests: print(nums, end=' : ') try: print(next(solve24(nums, nums, 24))) except StopIteration: print("No solution found") ``` {{out}} ```txt [1, 7, 2, 7] : (((7 * 7) - 1) / 2) [5, 7, 5, 4] : (4 * (7 - (5 / 5))) [1, 4, 6, 6] : (6 - (6 * (1 - 4))) [2, 3, 7, 3] : ((2 * 3) * (7 - 3)) [1, 6, 2, 6] : ((1 * 6) * (6 - 2)) [7, 9, 4, 1] : ((7 - 4) * (9 - 1)) [6, 4, 2, 2] : ((6 * 4) * (2 / 2)) [5, 7, 9, 7] : ((5 + 7) * (9 - 7)) [3, 3, 8, 8] : (8 / (3 - (8 / 3))) [8, 7, 9, 7] : No solution found [9, 4, 4, 5] : No solution found ``` ## R This uses exhaustive search and makes use of R's ability to work with expressions as data. It is in principle general for any set of operands and binary operators. ```r library(gtools) solve24 <- function(vals=c(8, 4, 2, 1), goal=24, ops=c("+", "-", "*", "/")) { val.perms <- as.data.frame(t( permutations(length(vals), length(vals)))) nop <- length(vals)-1 op.perms <- as.data.frame(t( do.call(expand.grid, replicate(nop, list(ops))))) ord.perms <- as.data.frame(t( do.call(expand.grid, replicate(n <- nop, 1:((n <<- n-1)+1))))) for (val.perm in val.perms) for (op.perm in op.perms) for (ord.perm in ord.perms) { expr <- as.list(vals[val.perm]) for (i in 1:nop) { expr[[ ord.perm[i] ]] <- call(as.character(op.perm[i]), expr[[ ord.perm[i] ]], expr[[ ord.perm[i]+1 ]]) expr <- expr[ -(ord.perm[i]+1) ] } if (identical(eval(expr[[1]]), goal)) return(expr[[1]]) } return(NA) } ``` {{out}} ```r > solve24() 8 * (4 - 2 + 1) > solve24(c(6,7,9,5)) 6 + (7 - 5) * 9 > solve24(c(8,8,8,8)) [1] NA > solve24(goal=49) #different goal value 8 * (4 + 2) + 1 > solve24(goal=52) #no solution [1] NA > solve24(ops=c('-', '/')) #restricted set of operators (8 - 2)/(1/4) ``` ## Racket The sequence of all possible variants of expressions with given numbers ''n1, n2, n3, n4'' and operations ''o1, o2, o3''. ```racket (define (in-variants n1 o1 n2 o2 n3 o3 n4) (let ([o1n (object-name o1)] [o2n (object-name o2)] [o3n (object-name o3)]) (with-handlers ((exn:fail:contract:divide-by-zero? (λ (_) empty-sequence))) (in-parallel (list (o1 (o2 (o3 n1 n2) n3) n4) (o1 (o2 n1 (o3 n2 n3)) n4) (o1 (o2 n1 n2) (o3 n3 n4)) (o1 n1 (o2 (o3 n2 n3) n4)) (o1 n1 (o2 n2 (o3 n3 n4)))) (list `(((,n1 ,o3n ,n2) ,o2n ,n3) ,o1n ,n4) `((,n1 ,o2n (,n2 ,o3n ,n3)) ,o1n ,n4) `((,n1 ,o2n ,n2) ,o1n (,n3 ,o3n ,n4)) `(,n1 ,o1n ((,n2 ,o3n ,n3) ,o2n ,n4)) `(,n1 ,o1n (,n2 ,o2n (,n3 ,o3n ,n4)))))))) ``` Search for all solutions using brute force: ```racket (define (find-solutions numbers (goal 24)) (define in-operations (list + - * /)) (remove-duplicates (for*/list ([n1 numbers] [n2 (remove-from numbers n1)] [n3 (remove-from numbers n1 n2)] [n4 (remove-from numbers n1 n2 n3)] [o1 in-operations] [o2 in-operations] [o3 in-operations] [(res expr) (in-variants n1 o1 n2 o2 n3 o3 n4)] #:when (= res goal)) expr))) (define (remove-from numbers . n) (foldr remq numbers n)) ``` Examples: ```txt > (find-solutions '(3 8 3 8)) '((8 / (3 - (8 / 3)))) > (find-solutions '(3 8 2 9)) '(((8 / 2) * (9 - 3)) (8 / (2 / (9 - 3))) (8 * (9 - (3 * 2))) (8 * ((9 - 3) / 2)) ((8 * (9 - 3)) / 2) (8 * (9 - (2 * 3))) ((9 - 3) * (8 / 2)) (((9 - 3) * 8) / 2) ((9 - (3 * 2)) * 8) (((9 - 3) / 2) * 8) ((9 - 3) / (2 / 8)) ((9 - (2 * 3)) * 8)) ``` In order to find just one solution effectively one needs to change for*/list to for*/first in the function find-solutions. ## REXX ```rexx /*REXX program helps the user find solutions to the game of 24. */ /* start-of-help ┌───────────────────────────────────────────────────────────────────────┐ │ Argument is either of three forms: (blank) │~ │ ssss │~ │ ssss,tot │~ │ ssss-ffff │~ │ ssss-ffff,tot │~ │ -ssss │~ │ +ssss │~ │ │~ │ where SSSS and/or FFFF must be exactly four numerals (digits) │~ │ comprised soley of the numerals (digits) 1 ──> 9 (no zeroes). │~ │ │~ │ SSSS is the start, │~ │ FFFF is the start. │~ │ │~ │ │~ │ If ssss has a leading plus (+) sign, it is used as the number, and │~ │ the user is prompted to find a solution. │~ │ │~ │ If ssss has a leading minus (-) sign, a solution is looked for and │~ │ the user is told there is a solution (but no solutions are shown). │~ │ │~ │ If no argument is specified, this program finds a four digits (no │~ │ zeroes) which has at least one solution, and shows the digits to │~ │ the user, requesting that they enter a solution. │~ │ │~ │ If tot is entered, it is the desired answer. The default is 24. │~ │ │~ │ A solution to be entered can be in the form of: │ │ │ │ digit1 operator digit2 operator digit3 operator digit4 │ │ │ │ where DIGITn is one of the digits shown (in any order), and │ │ OPERATOR can be any one of: + - * / │ │ │ │ Parentheses () may be used in the normal manner for grouping, as │ │ well as brackets [] or braces {}. Blanks can be used anywhere. │ │ │ │ I.E.: for the digits 3448 the following could be entered. │ │ │ │ 3*8 + (4-4) │ └───────────────────────────────────────────────────────────────────────┘ end-of-help */ numeric digits 12 /*where rational arithmetic is needed. */ parse arg orig /*get the guess from the command line*/ orig= space(orig, 0) /*remove all blanks from ORIG. */ negatory= left(orig,1)=='-' /*=1, suppresses showing. */ pository= left(orig,1)=='+' /*=1, force $24 to use specific number.*/ if pository | negatory then orig=substr(orig,2) /*now, just use the absolute vaue. */ parse var orig orig ',' ?? /*get ?? (if specified, def=24). */ parse var orig start '-' finish /*get start and finish (maybe). */ opers= '*' || "/+-" /*legal arith. opers;order is important*/ ops= length(opers) /*the number of arithmetic operators. */ groupsym= '()[]{}' /*allowed grouping symbols. */ indent= left('', 30) /*indents display of solutions. */ show= 1 /*=1, shows solutions (semifore). */ digs= 123456789 /*numerals/digs that can be used. */ abuttals = 0 /*=1, allows digit abutal: 12+12 */ if ??=='' then ??= 24 /*the name of the game. */ ??= ?? / 1 /*normalize the answer. */ @abc= 'abcdefghijklmnopqrstuvwxyz' /*the Latin alphabet in order. */ @abcu= @abc; upper @abcu /*an uppercase version of @abc. */ x.= 0 /*method used to not re-interpret. */ do j=1 for ops; o.j=substr(opers, j, 1) end /*j*/ /*used for fast execution. */ y= ?? if \datatype(??,'N') then do; call ger "isn't numeric"; exit 13; end if start\=='' & \pository then do; call ranger start,finish; exit 13; end show= 0 /*stop SOLVE blabbing solutions. */ do forever while \negatory /*keep truckin' until a solution. */ x.= 0 /*way to hold unique expressions. */ rrrr= random(1111, 9999) /*get a random set of digits. */ if pos(0, rrrr)\==0 then iterate /*but don't the use of zeroes. */ if solve(rrrr)\==0 then leave /*try to solve for these digits. */ end /*forever*/ if left(orig,1)=='+' then rrrr=start /*use what's specified. */ show= 1 /*enable SOLVE to show solutions. */ rrrr= sortc(rrrr) /*sort four elements. */ rd.= 0 do j=1 for 9 /*count for each digit in RRRR. */ _= substr(rrrr, j, 1); rd._= countchars(rrrr, _) end do guesses=1; say say 'Using the digits' rrrr", enter an expression that equals" ?? ' (? or QUIT):' pull y; y= space(y, 0) if countchars(y, @abcu)>2 then exit /*the user must be desperate. */ helpstart= 0 if y=='?' then do j=1 for sourceline() /*use a lazy way to show help. */ _= sourceline(j) if p(_)=='start-of-help' then do; helpstart=1; iterate; end if p(_)=='end-of-help' then iterate guesses if \helpstart then iterate if right(_,1)=='~' then iterate say ' ' _ end _v= verify(y, digs || opers || groupsym) /*any illegal characters? */ if _v\==0 then do; call ger 'invalid character:' substr(y, _v, 1); iterate; end if y='' then do; call validate y; iterate; end do j=1 for length(y)-1 while \abuttals /*check for two digits adjacent. */ if \datatype(substr(y,j,1), 'W') then iterate if datatype(substr(y,j+1,1),'W') then do call ger 'invalid use of digit abuttal' substr(y,j,2) iterate guesses end end /*j*/ yd= countchars(y, digs) /*count of legal digits 123456789 */ if yd<4 then do; call ger 'not enough digits entered.'; iterate guesses; end if yd>4 then do; call ger 'too many digits entered.' ; iterate guesses; end do j=1 for length(groupsym) by 2 if countchars(y,substr(groupsym,j ,1))\==, countchars(y,substr(groupsym,j+1,1)) then do call ger 'mismatched' substr(groupsym,j,2) iterate guesses end end /*j*/ do k=1 for 2 /*check for ** and // */ _= copies( substr( opers, k, 1), 2) if pos(_, y)\==0 then do; call ger 'illegal operator:' _; iterate guesses; end end /*k*/ do j=1 for 9; if rd.j==0 then iterate; _d= countchars(y, j) if _d==rd.j then iterate if _d /div(yyy) */ origE= e /*keep original version for the display*/ pd= pos('/(', e) /*find pos of /( in E. */ if pd\==0 then do /*Found? Might have possible ÷ by zero*/ eo= e lr= lastpos(')', e) /*find last right ) */ lm= pos('-', e, pd+1) /*find - after ( */ if lm>pd & lm 1156-1162 }}
                               a solution for 1156: 24= [1*5-1]*6
                               a solution for 1156: 24= [[1*5-1]*6]
                               a solution for 1156: 24= 1*[5-1]*6
                               a solution for 1156: 24= 1*[[5-1]*6]
                               a solution for 1156: 24= [1*6]*[5-1]
                               a solution for 1156: 24= 1*[6*[5-1]]
                               a solution for 1156: 24= [5*1-1]*6
                               a solution for 1156: 24= [[5*1-1]*6]
                               a solution for 1156: 24= [5/1-1]*6
                               a solution for 1156: 24= [[5/1-1]*6]
                               a solution for 1156: 24= [5-1]*1*6
                               a solution for 1156: 24= [5-1*1]*6
                               a solution for 1156: 24= [5-1]*[1*6]
                               a solution for 1156: 24= [[5-1*1]*6]
                               a solution for 1156: 24= [5-1]/1*6
                               a solution for 1156: 24= [5-1/1]*6
                               a solution for 1156: 24= [[5-1/1]*6]
                               a solution for 1156: 24= [5-1]/[1/6]
                               a solution for 1156: 24= [5-1]*6*1
                               a solution for 1156: 24= [5-1]*[6*1]
                               a solution for 1156: 24= [5-1]*6/1
                               a solution for 1156: 24= [5-1]*[6/1]
                               a solution for 1156: 24= 5*[6-1]-1
                               a solution for 1156: 24= [6*1]*[5-1]
                               a solution for 1156: 24= [6*[1*5-1]]
                               a solution for 1156: 24= 6*[1*5-1]
                               a solution for 1156: 24= 6*[1*[5-1]]
                               a solution for 1156: 24= 6*[[1*5]-1]
                               a solution for 1156: 24= [6/1]*[5-1]
                               a solution for 1156: 24= 6/[1/[5-1]]
                               a solution for 1156: 24= [6-1]*5-1
                               a solution for 1156: 24= [6*[5*1-1]]
                               a solution for 1156: 24= 6*[5*1-1]
                               a solution for 1156: 24= 6*[[5*1]-1]
                               a solution for 1156: 24= [6*[5/1-1]]
                               a solution for 1156: 24= 6*[5/1-1]
                               a solution for 1156: 24= 6*[[5/1]-1]
                               a solution for 1156: 24= [6*[5-1*1]]
                               a solution for 1156: 24= 6*[5-1]*1
                               a solution for 1156: 24= 6*[5-1*1]
                               a solution for 1156: 24= 6*[5-[1*1]]
                               a solution for 1156: 24= 6*[[5-1]*1]
                               a solution for 1156: 24= [6*[5-1/1]]
                               a solution for 1156: 24= 6*[5-1]/1
                               a solution for 1156: 24= 6*[5-1/1]
                               a solution for 1156: 24= 6*[5-[1/1]]
                               a solution for 1156: 24= 6*[[5-1]/1]

47 solutions found for 1156
                               a solution for 1157: 24= [1+1]*[5+7]
                               a solution for 1157: 24= [1+1]*[7+5]
                               a solution for 1157: 24= [1-5]*[1-7]
                               a solution for 1157: 24= [1-7]*[1-5]
                               a solution for 1157: 24= [5-1]*[7-1]
                               a solution for 1157: 24= [5+7]*[1+1]
                               a solution for 1157: 24= [7-1]*[5-1]
                               a solution for 1157: 24= [7+5]*[1+1]

8 solutions found for 1157
                               a solution for 1158: 24= [5-1-1]*8
                               a solution for 1158: 24= [[5-1-1]*8]
                               a solution for 1158: 24= 8*[5-[1+1]]
                               a solution for 1158: 24= [8*[5-1-1]]
                               a solution for 1158: 24= 8*[5-1-1]
                               a solution for 1158: 24= 8*[[5-1]-1]

6 solutions found for 1158

No solutions found for 1159

No solutions found for 1161
                               a solution for 1162: 24= [1+1]*2*6
                               a solution for 1162: 24= [1+1]*[2*6]
                               a solution for 1162: 24= [1+1+2]*6
                               a solution for 1162: 24= [[1+1+2]*6]
                               a solution for 1162: 24= [1+1]*6*2
                               a solution for 1162: 24= [1+1]*[6*2]
                               a solution for 1162: 24= [1+2+1]*6
                               a solution for 1162: 24= [[1+2+1]*6]
                               a solution for 1162: 24= 2*[1+1]*6
                               a solution for 1162: 24= 2*[[1+1]*6]
                               a solution for 1162: 24= [2+1+1]*6
                               a solution for 1162: 24= [[2+1+1]*6]
                               a solution for 1162: 24= [2*6]*[1+1]
                               a solution for 1162: 24= 2*[6*[1+1]]
                               a solution for 1162: 24= 6*[1+1]*2
                               a solution for 1162: 24= 6*[[1+1]*2]
                               a solution for 1162: 24= [6*[1+1+2]]
                               a solution for 1162: 24= 6*[1+1+2]
                               a solution for 1162: 24= 6*[1+[1+2]]
                               a solution for 1162: 24= 6*[[1+1]+2]
                               a solution for 1162: 24= [6*[1+2+1]]
                               a solution for 1162: 24= 6*[1+2+1]
                               a solution for 1162: 24= 6*[1+[2+1]]
                               a solution for 1162: 24= 6*[[1+2]+1]
                               a solution for 1162: 24= [6*2]*[1+1]
                               a solution for 1162: 24= 6*[2*[1+1]]
                               a solution for 1162: 24= [6*[2+1+1]]
                               a solution for 1162: 24= 6*[2+1+1]
                               a solution for 1162: 24= 6*[2+[1+1]]
                               a solution for 1162: 24= 6*[[2+1]+1]

30 solutions found for 1162

```



## Ruby

{{trans|Tcl}}
{{works with|Ruby|2.1}}

```ruby
class TwentyFourGame
  EXPRESSIONS = [
    '((%dr %s %dr) %s %dr) %s %dr',
    '(%dr %s (%dr %s %dr)) %s %dr',
    '(%dr %s %dr) %s (%dr %s %dr)',
    '%dr %s ((%dr %s %dr) %s %dr)',
    '%dr %s (%dr %s (%dr %s %dr))',
  ]

  OPERATORS = [:+, :-, :*, :/].repeated_permutation(3).to_a

  def self.solve(digits)
    solutions = []
    perms = digits.permutation.to_a.uniq
    perms.product(OPERATORS, EXPRESSIONS) do |(a,b,c,d), (op1,op2,op3), expr|
      # evaluate using rational arithmetic
      text = expr % [a, op1, b, op2, c, op3, d]
      value = eval(text)  rescue next                 # catch division by zero
      solutions << text.delete("r")  if value == 24
    end
    solutions
  end
end

# validate user input
digits = ARGV.map do |arg|
  begin
    Integer(arg)
  rescue ArgumentError
    raise "error: not an integer: '#{arg}'"
  end
end
digits.size == 4 or raise "error: need 4 digits, only have #{digits.size}"

solutions = TwentyFourGame.solve(digits)
if solutions.empty?
  puts "no solutions"
else
  puts "found #{solutions.size} solutions, including #{solutions.first}"
  puts solutions.sort
end
```


{{out}}

```txt
$ ruby game24_solver.rb 1 1 1 1
no solutions

$ ruby game24_solver.rb 1 1 2 7
found 8 solutions, including (1 + 2) * (1 + 7)
(1 + 2) * (1 + 7)
(1 + 2) * (7 + 1)
(1 + 7) * (1 + 2)
(1 + 7) * (2 + 1)
(2 + 1) * (1 + 7)
(2 + 1) * (7 + 1)
(7 + 1) * (1 + 2)
(7 + 1) * (2 + 1)

$ ruby game24_solver.rb 2 3 8 9
found 12 solutions, including (8 / 2) * (9 - 3)
((9 - 3) * 8) / 2
((9 - 3) / 2) * 8
(8 * (9 - 3)) / 2
(8 / 2) * (9 - 3)
(9 - (2 * 3)) * 8
(9 - (3 * 2)) * 8
(9 - 3) * (8 / 2)
(9 - 3) / (2 / 8)
8 * ((9 - 3) / 2)
8 * (9 - (2 * 3))
8 * (9 - (3 * 2))
8 / (2 / (9 - 3))
```



## Rust

{{works with|Rust|1.17}}

```rust
#[derive(Clone, Copy, Debug)]
enum Operator {
    Sub,
    Plus,
    Mul,
    Div,
}

#[derive(Clone, Debug)]
struct Factor {
    content: String,
    value: i32,
}

fn apply(op: Operator, left: &[Factor], right: &[Factor]) -> Vec {
    let mut ret = Vec::new();
    for l in left.iter() {
        for r in right.iter() {
            use Operator::*;
            ret.push(match op {
                Sub if l.value > r.value => Factor {
                    content: format!("({} - {})", l.content, r.content),
                    value: l.value - r.value,
                },
                Plus => Factor {
                    content: format!("({} + {})", l.content, r.content),
                    value: l.value + r.value,
                },
                Mul => Factor {
                    content: format!("({} x {})", l.content, r.content),
                    value: l.value * r.value,
                },
                Div if l.value >= r.value && r.value > 0 && l.value % r.value == 0 => Factor {
                    content: format!("({} / {})", l.content, r.content),
                    value: l.value / r.value,
                },
                _ => continue,
            })
        }
    }
    ret
}

fn calc(op: [Operator; 3], numbers: [i32; 4]) -> Vec {
    fn calc(op: &[Operator], numbers: &[i32], acc: &[Factor]) -> Vec {
        use Operator::*;
        if op.is_empty() {
            return Vec::from(acc)
        }
        let mut ret = Vec::new();
        let mono_factor = [Factor {
            content: numbers[0].to_string(),
            value: numbers[0],
        }];
        match op[0] {
            Mul => ret.extend_from_slice(&apply(op[0], acc, &mono_factor)),
            Div => {
                ret.extend_from_slice(&apply(op[0], acc, &mono_factor));
                ret.extend_from_slice(&apply(op[0], &mono_factor, acc));
            },
            Sub => {
                ret.extend_from_slice(&apply(op[0], acc, &mono_factor));
                ret.extend_from_slice(&apply(op[0], &mono_factor, acc));
            },
            Plus => ret.extend_from_slice(&apply(op[0], acc, &mono_factor)),
        }
        calc(&op[1..], &numbers[1..], &ret)
    }
    calc(&op, &numbers[1..], &[Factor { content: numbers[0].to_string(), value: numbers[0] }])
}

fn solutions(numbers: [i32; 4]) -> Vec {
    use std::collections::hash_set::HashSet;
    let mut ret = Vec::new();
    let mut hash_set = HashSet::new();

    for ops in OpIter(0) {
        for o in orders().iter() {
            let numbers = apply_order(numbers, o);
            let r = calc(ops, numbers);
            ret.extend(r.into_iter().filter(|&Factor { value, ref content }| value == 24 && hash_set.insert(content.to_owned())))
        }
    }
    ret
}

fn main() {
    let mut numbers = Vec::new();
    if let Some(input) = std::env::args().skip(1).next() {
        for c in input.chars() {
            if let Ok(n) = c.to_string().parse() {
                numbers.push(n)
            }
            if numbers.len() == 4 {
                let numbers = [numbers[0], numbers[1], numbers[2], numbers[3]];
                let solutions = solutions(numbers);
                let len = solutions.len();
                if len == 0 {
                    println!("no solution for {}, {}, {}, {}", numbers[0], numbers[1], numbers[2], numbers[3]);
                    return
                }
                println!("solutions for {}, {}, {}, {}", numbers[0], numbers[1], numbers[2], numbers[3]);
                for s in solutions {
                    println!("{}", s.content)
                }
                println!("{} solutions found", len);
                return
            }
        }
    } else {
        println!("empty input")
    }
}


struct OpIter (usize);

impl Iterator for OpIter {
    type Item = [Operator; 3];
    fn next(&mut self) -> Option<[Operator; 3]> {
        use Operator::*;
        const OPTIONS: [Operator; 4] = [Mul, Sub, Plus, Div];
        if self.0 >= 1 << 6 {
            return None
        }
        let f1 = OPTIONS[(self.0 & (3 << 4)) >> 4];
        let f2 = OPTIONS[(self.0 & (3 << 2)) >> 2];
        let f3 = OPTIONS[(self.0 & (3 << 0)) >> 0];
        self.0 += 1;
        Some([f1, f2, f3])
    }
}

fn orders() -> [[usize; 4]; 24] {
    [
        [0, 1, 2, 3],
        [0, 1, 3, 2],
        [0, 2, 1, 3],
        [0, 2, 3, 1],
        [0, 3, 1, 2],
        [0, 3, 2, 1],
        [1, 0, 2, 3],
        [1, 0, 3, 2],
        [1, 2, 0, 3],
        [1, 2, 3, 0],
        [1, 3, 0, 2],
        [1, 3, 2, 0],
        [2, 0, 1, 3],
        [2, 0, 3, 1],
        [2, 1, 0, 3],
        [2, 1, 3, 0],
        [2, 3, 0, 1],
        [2, 3, 1, 0],
        [3, 0, 1, 2],
        [3, 0, 2, 1],
        [3, 1, 0, 2],
        [3, 1, 2, 0],
        [3, 2, 0, 1],
        [3, 2, 1, 0]
    ]
}

fn apply_order(numbers: [i32; 4], order: &[usize; 4]) -> [i32; 4] {
    [numbers[order[0]], numbers[order[1]], numbers[order[2]], numbers[order[3]]]
}

```

{{out}}

```txt

$cargo run 5598
solutions for 5, 5, 9, 8
(((5 x 5) - 9) + 8)
(((5 x 5) + 8) - 9)
(((8 - 5) x 5) + 9)
3 solutions found

```



## Scala

A non-interactive player.


```scala
def permute(l: List[Double]): List[List[Double]] = l match {
  case Nil => List(Nil)
  case x :: xs =>
    for {
      ys <- permute(xs)
      position <- 0 to ys.length
      (left, right) = ys splitAt position
    } yield left ::: (x :: right)
}

def computeAllOperations(l: List[Double]): List[(Double,String)] = l match {
  case Nil => Nil
  case x :: Nil => List((x, "%1.0f" format x))
  case x :: xs =>
    for {
      (y, ops) <- computeAllOperations(xs)
      (z, op) <-
        if (y == 0)
          List((x*y, "*"), (x+y, "+"), (x-y, "-"))
        else
          List((x*y, "*"), (x/y, "/"), (x+y, "+"), (x-y, "-"))
    } yield (z, "(%1.0f%s%s)" format (x,op,ops))
}

def hasSolution(l: List[Double]) = permute(l) flatMap computeAllOperations filter (_._1 == 24) map (_._2)
```


Example:


```txt

val problemsIterator = (
    Iterator
    continually List.fill(4)(scala.util.Random.nextInt(9) + 1 toDouble)
    filter (!hasSolution(_).isEmpty)
)

val solutionIterator = problemsIterator map hasSolution

scala> solutionIterator.next
res8: List[String] = List((3*(5-(3-6))), (3*(5-(3-6))), (3*(5+(6-3))), (3+(6+(3*5))), (3*(6-(3-5))), (3+(6+(5*3))), (3*(
6+(5-3))), (3*(5+(6-3))), (3+(6+(5*3))), (3*(6+(5-3))), (6+(3+(5*3))), (6*(5-(3/3))), (6*(5-(3/3))), (3+(6+(3*5))), (3*(
6-(3-5))), (6+(3+(3*5))), (6+(3+(3*5))), (6+(3+(5*3))))

scala> solutionIterator.next
res9: List[String] = List((4-(5*(5-9))), (4-(5*(5-9))), (4+(5*(9-5))), (4+(5*(9-5))), (9-(5-(4*5))), (9-(5-(5*4))), (9-(
5-(4*5))), (9-(5-(5*4))))

scala> solutionIterator.next
res10: List[String] = List((2*(4+(3+5))), (2*(3+(4+5))), (2*(3+(5+4))), (4*(3-(2-5))), (4*(3+(5-2))), (2*(4+(5+3))), (2*
(5+(4+3))), (2*(5+(3+4))), (4*(5-(2-3))), (4*(5+(3-2))))

scala> solutionIterator.next
res11: List[String] = List((4*(5-(2-3))), (2*(4+(5+3))), (2*(5+(4+3))), (2*(5+(3+4))), (2*(4+(3+5))), (2*(3+(4+5))), (2*
(3+(5+4))), (4*(5+(3-2))), (4*(3+(5-2))), (4*(3-(2-5))))

```



## Scheme

This version outputs an S-expression that will '''eval''' to 24 (rather than converting to infix notation).


```scheme

#!r6rs

(import (rnrs)
        (rnrs eval)
        (only (srfi :1 lists) append-map delete-duplicates iota))

(define (map* fn . lis)
  (if (null? lis)
      (list (fn))
      (append-map (lambda (x)
                    (apply map*
                           (lambda xs (apply fn x xs))
                           (cdr lis)))
                  (car lis))))

(define (insert x li n)
  (if (= n 0)
      (cons x li)
      (cons (car li) (insert x (cdr li) (- n 1)))))

(define (permutations li)
  (if (null? li)
      (list ())
      (map* insert (list (car li)) (permutations (cdr li)) (iota (length li)))))

(define (evaluates-to-24 expr)
  (guard (e ((assertion-violation? e) #f))
    (= 24 (eval expr (environment '(rnrs base))))))

(define (tree n o0 o1 o2 xs)
  (list-ref
   (list
    `(,o0 (,o1 (,o2 ,(car xs) ,(cadr xs)) ,(caddr xs)) ,(cadddr xs))
    `(,o0 (,o1 (,o2 ,(car xs) ,(cadr xs)) ,(caddr xs)) ,(cadddr xs))
    `(,o0 (,o1 ,(car xs) (,o2 ,(cadr xs) ,(caddr xs))) ,(cadddr xs))
    `(,o0 (,o1 ,(car xs) ,(cadr xs)) (,o2 ,(caddr xs) ,(cadddr xs)))
    `(,o0 ,(car xs) (,o1 (,o2 ,(cadr xs) ,(caddr xs)) ,(cadddr xs)))
    `(,o0 ,(car xs) (,o1 ,(cadr xs) (,o2 ,(caddr xs) ,(cadddr xs)))))
   n))

(define (solve a b c d)
  (define ops '(+ - * /))
  (define perms (delete-duplicates (permutations (list a b c d))))
  (delete-duplicates
   (filter evaluates-to-24
           (map* tree (iota 6) ops ops ops perms))))

```


Example output:

```scheme

> (solve 1 3 5 7)
((* (+ 1 5) (- 7 3))
 (* (+ 5 1) (- 7 3))
 (* (+ 5 7) (- 3 1))
 (* (+ 7 5) (- 3 1))
 (* (- 3 1) (+ 5 7))
 (* (- 3 1) (+ 7 5))
 (* (- 7 3) (+ 1 5))
 (* (- 7 3) (+ 5 1)))
> (solve 3 3 8 8)
((/ 8 (- 3 (/ 8 3))))
> (solve 3 4 9 10)
()

```



## Sidef


'''With eval():'''


```ruby
var formats = [
    '((%d %s %d) %s %d) %s %d',
    '(%d %s (%d %s %d)) %s %d',
    '(%d %s %d) %s (%d %s %d)',
    '%d %s ((%d %s %d) %s %d)',
    '%d %s (%d %s (%d %s %d))',
]

var op = %w( + - * / )
var operators = op.map { |a| op.map {|b| op.map {|c| "#{a} #{b} #{c}" } } }.flat

loop {
    var input = read("Enter four integers or 'q' to exit: ", String)
    input == 'q' && break

    if (input !~ /^\h*[1-9]\h+[1-9]\h+[1-9]\h+[1-9]\h*$/) {
        say "Invalid input!"
        next
    }

    var n = input.split.map{.to_n}
    var numbers = n.permutations

    formats.each { |format|
        numbers.each { |n|
            operators.each { |operator|
                var o = operator.split;
                var str = (format % (n[0],o[0],n[1],o[1],n[2],o[2],n[3]))
                eval(str) == 24 && say str
            }
        }
    }
}
```


'''Without eval():'''

```ruby
var formats = [
    {|a,b,c|
        Hash(
            func   => {|d,e,f,g| ((d.$a(e)).$b(f)).$c(g) },
            format => "((%d #{a} %d) #{b} %d) #{c} %d"
        )
    },
    {|a,b,c|
        Hash(
            func   => {|d,e,f,g| (d.$a((e.$b(f)))).$c(g) },
            format => "(%d #{a} (%d #{b} %d)) #{c} %d",
        )
    },
    {|a,b,c|
        Hash(
            func   => {|d,e,f,g| (d.$a(e)).$b(f.$c(g)) },
            format => "(%d #{a} %d) #{b} (%d #{c} %d)",
        )
    },
    {|a,b,c|
        Hash(
            func   => {|d,e,f,g| (d.$a(e)).$b(f.$c(g)) },
            format => "(%d #{a} %d) #{b} (%d #{c} %d)",
        )
    },
    {|a,b,c|
        Hash(
            func   => {|d,e,f,g| d.$a(e.$b(f.$c(g))) },
            format => "%d #{a} (%d #{b} (%d #{c} %d))",
        )
    },
];

var op = %w( + - * / )
var blocks = op.map { |a| op.map { |b| op.map { |c| formats.map { |format|
    format(a,b,c)
}}}}.flat

loop {
    var input = Sys.scanln("Enter four integers or 'q' to exit: ");
    input == 'q' && break;

    if (input !~ /^\h*[1-9]\h+[1-9]\h+[1-9]\h+[1-9]\h*$/) {
        say "Invalid input!"
        next
    }

    var n = input.split.map{.to_n}
    var numbers = n.permutations

    blocks.each { |block|
        numbers.each { |n|
            if (block{:func}.call(n...) == 24) {
                say (block{:format} % (n...))
            }
        }
    }
}
```


{{out}}

```txt

Enter four integers or 'q' to exit: 8 7 9 6
(8 / (9 - 7)) * 6
(6 / (9 - 7)) * 8
(8 * 6) / (9 - 7)
(6 * 8) / (9 - 7)
8 / ((9 - 7) / 6)
6 / ((9 - 7) / 8)
8 * (6 / (9 - 7))
6 * (8 / (9 - 7))
Enter four integers or 'q' to exit: q

```



## Simula


```simula
BEGIN



    CLASS EXPR;
    BEGIN


        REAL PROCEDURE POP;
        BEGIN
            IF STACKPOS > 0 THEN
            BEGIN STACKPOS := STACKPOS - 1; POP := STACK(STACKPOS); END;
        END POP;


        PROCEDURE PUSH(NEWTOP); REAL NEWTOP;
        BEGIN
            STACK(STACKPOS) := NEWTOP;
            STACKPOS := STACKPOS + 1;
        END PUSH;


        REAL PROCEDURE CALC(OPERATOR, ERR); CHARACTER OPERATOR; LABEL ERR;
        BEGIN
            REAL X, Y; X := POP; Y := POP;
            IF      OPERATOR = '+' THEN PUSH(Y + X)
            ELSE IF OPERATOR = '-' THEN PUSH(Y - X)
            ELSE IF OPERATOR = '*' THEN PUSH(Y * X)
            ELSE IF OPERATOR = '/' THEN BEGIN
                                            IF X = 0 THEN
                                            BEGIN
                                                EVALUATEDERR :- "DIV BY ZERO";
                                                GOTO ERR;
                                            END;
                                            PUSH(Y / X);
                                        END
            ELSE
            BEGIN
                EVALUATEDERR :- "UNKNOWN OPERATOR";
                GOTO ERR;
            END
        END CALC;


        PROCEDURE READCHAR(CH); NAME CH; CHARACTER CH;
        BEGIN
            IF T.MORE THEN CH := T.GETCHAR ELSE CH := EOT;
        END READCHAR;


        PROCEDURE SKIPWHITESPACE(CH); NAME CH; CHARACTER CH;
        BEGIN
            WHILE (CH = SPACE) OR (CH = TAB) OR (CH = CR) OR (CH = LF) DO
                READCHAR(CH);
        END SKIPWHITESPACE;


        PROCEDURE BUSYBOX(OP, ERR); INTEGER OP; LABEL ERR;
        BEGIN
            CHARACTER OPERATOR;
            REAL NUMBR;
            BOOLEAN NEGATIVE;

            SKIPWHITESPACE(CH);

            IF OP = EXPRESSION THEN
            BEGIN

                NEGATIVE := FALSE;
                WHILE (CH = '+') OR (CH = '-') DO
                BEGIN
                    IF CH = '-' THEN NEGATIVE :=  NOT NEGATIVE;
                    READCHAR(CH);
                END;

                BUSYBOX(TERM, ERR);

                IF NEGATIVE THEN
                BEGIN
                    NUMBR := POP; PUSH(0 - NUMBR);
                END;

                WHILE (CH = '+') OR (CH = '-') DO
                BEGIN
                    OPERATOR := CH; READCHAR(CH);
                    BUSYBOX(TERM, ERR); CALC(OPERATOR, ERR);
                END;

            END
            ELSE IF OP = TERM THEN
            BEGIN

                BUSYBOX(FACTOR, ERR);
                WHILE (CH = '*') OR (CH = '/') DO
                BEGIN
                    OPERATOR := CH; READCHAR(CH);
                    BUSYBOX(FACTOR, ERR); CALC(OPERATOR, ERR)
                END

            END
            ELSE IF OP = FACTOR THEN
            BEGIN

                IF (CH = '+') OR (CH = '-') THEN
                  BUSYBOX(EXPRESSION, ERR)
                ELSE IF (CH >= '0') AND (CH <= '9') THEN
                  BUSYBOX(NUMBER, ERR)
                ELSE IF CH = '(' THEN
                BEGIN
                    READCHAR(CH);
                    BUSYBOX(EXPRESSION, ERR);
                    IF CH = ')' THEN READCHAR(CH) ELSE GOTO ERR;
                END
                ELSE GOTO ERR;

            END
            ELSE IF OP = NUMBER THEN
            BEGIN

                NUMBR := 0;
                WHILE (CH >= '0') AND (CH <= '9') DO
                BEGIN
                    NUMBR := 10 * NUMBR + RANK(CH) - RANK('0'); READCHAR(CH);
                END;
                IF CH = '.' THEN
                BEGIN
                    REAL FAKTOR;
                    READCHAR(CH);
                    FAKTOR := 10;
                    WHILE (CH >= '0') AND (CH <= '9') DO
                    BEGIN
                        NUMBR := NUMBR + (RANK(CH) - RANK('0')) / FAKTOR;
                        FAKTOR := 10 * FAKTOR;
                        READCHAR(CH);
                    END;
                END;
                PUSH(NUMBR);

            END;

            SKIPWHITESPACE(CH);

        END BUSYBOX;


        BOOLEAN PROCEDURE EVAL(INP); TEXT INP;
        BEGIN
            EVALUATEDERR :- NOTEXT;
            STACKPOS := 0;
            T :- COPY(INP.STRIP);
            READCHAR(CH);
            BUSYBOX(EXPRESSION, ERRORLABEL);
            IF NOT T.MORE AND STACKPOS = 1 AND CH = EOT THEN
            BEGIN
                EVALUATED := POP;
                EVAL := TRUE;
                GOTO NOERRORLABEL;
            END;
    ERRORLABEL:
            EVAL := FALSE;
            IF EVALUATEDERR = NOTEXT THEN
                EVALUATEDERR :- "INVALID EXPRESSION: " & INP;
    NOERRORLABEL:
        END EVAL;


        REAL PROCEDURE RESULT;
            RESULT := EVALUATED;

        TEXT PROCEDURE ERR;
            ERR :- EVALUATEDERR;

        TEXT T;

        INTEGER EXPRESSION;
        INTEGER TERM;
        INTEGER FACTOR;
        INTEGER NUMBER;

        CHARACTER TAB;
        CHARACTER LF;
        CHARACTER CR;
        CHARACTER SPACE;
        CHARACTER EOT;

        CHARACTER CH;
        REAL ARRAY STACK(0:31);
        INTEGER STACKPOS;

        REAL EVALUATED;
        TEXT EVALUATEDERR;

        EXPRESSION := 1;
        TERM := 2;
        FACTOR := 3;
        NUMBER := 4;

        TAB := CHAR(9);
        LF := CHAR(10);
        CR := CHAR(13);
        SPACE := CHAR(32);
        EOT := CHAR(0);

    END EXPR;


    INTEGER ARRAY DIGITS(1:4);
    INTEGER SEED, I;
    REF(EXPR) E;

    INTEGER SOLUTION;
    INTEGER D1,D2,D3,D4;
    INTEGER O1,O2,O3;
    TEXT OPS;

    OPS :- "+-*/";

    E :- NEW EXPR;
    OUTTEXT("ENTER FOUR INTEGERS: ");
    OUTIMAGE;
    FOR I := 1 STEP 1 UNTIL 4 DO DIGITS(I) := ININT; !RANDINT(0, 9, SEED);

    ! DIGITS ;
    FOR D1 := 1 STEP 1 UNTIL 4 DO
    FOR D2 := 1 STEP 1 UNTIL 4 DO IF D2 <> D1 THEN
    FOR D3 := 1 STEP 1 UNTIL 4 DO IF D3 <> D2 AND
                                     D3 <> D1 THEN
    FOR D4 := 1 STEP 1 UNTIL 4 DO IF D4 <> D3 AND
                                     D4 <> D2 AND
                                     D4 <> D1 THEN
    ! OPERATORS ;
    FOR O1 := 1 STEP 1 UNTIL 4 DO
    FOR O2 := 1 STEP 1 UNTIL 4 DO
    FOR O3 := 1 STEP 1 UNTIL 4 DO
    BEGIN
        PROCEDURE P(FMT); TEXT FMT;
        BEGIN
            INTEGER PLUS;
            TRY.SETPOS(1);
            WHILE FMT.MORE DO
            BEGIN
                CHARACTER C;
                C := FMT.GETCHAR;
                IF (C >= '1') AND (C <= '4') THEN
                BEGIN
                    INTEGER DIG; CHARACTER NCH;
                    DIG := IF C = '1' THEN DIGITS(D1)
                      ELSE IF C = '2' THEN DIGITS(D2)
                      ELSE IF C = '3' THEN DIGITS(D3)
                                      ELSE DIGITS(D4);
                    NCH := CHAR( DIG + RANK('0') );
                    TRY.PUTCHAR(NCH);
                END
                ELSE IF C = '+' THEN
                BEGIN
                    PLUS := PLUS + 1;
                    OPS.SETPOS(IF PLUS = 1 THEN O1 ELSE
                               IF PLUS = 2 THEN O2
                                           ELSE O3);
                    TRY.PUTCHAR(OPS.GETCHAR);
                END
                ELSE IF (C = '(') OR (C = ')') OR (C = ' ') THEN
                    TRY.PUTCHAR(C)
                ELSE
                    ERROR("ILLEGAL EXPRESSION");
            END;
            IF E.EVAL(TRY) THEN
            BEGIN
                IF ABS(E.RESULT - 24) < 0.001 THEN
                BEGIN
                    SOLUTION := SOLUTION + 1;
                    OUTTEXT(TRY); OUTTEXT(" = ");
                    OUTFIX(E.RESULT, 4, 10);
                    OUTIMAGE;
                END;
            END
            ELSE
            BEGIN
                IF E.ERR <> "DIV BY ZERO" THEN
                BEGIN
                    OUTTEXT(TRY); OUTIMAGE;
                    OUTTEXT(E.ERR); OUTIMAGE;
                END;
            END;
        END P;
        TEXT TRY;
        TRY :- BLANKS(17);
        P("(1 + 2) + (3 + 4)");
        P("(1 + (2 + 3)) + 4");
        P("((1 + 2) + 3) + 4");
        P("1 + ((2 + 3) + 4)");
        P("1 + (2 + (3 + 4))");
    END;
    OUTINT(SOLUTION, 0);
    OUTTEXT(" SOLUTIONS FOUND");
    OUTIMAGE;
END.

```

{{out}}

```txt

ENTER FOUR INTEGERS: 8 7 9 6
(8 / (9 - 7)) * 6 =    24.0000
8 / ((9 - 7) / 6) =    24.0000
(8 * 6) / (9 - 7) =    24.0000
8 * (6 / (9 - 7)) =    24.0000
(6 * 8) / (9 - 7) =    24.0000
6 * (8 / (9 - 7)) =    24.0000
(6 / (9 - 7)) * 8 =    24.0000
6 / ((9 - 7) / 8) =    24.0000
8 SOLUTIONS FOUND

2 garbage collection(s) in 0.0 seconds.

```



## Swift



```swift

import Darwin
import Foundation

var solution = ""

println("24 Game")
println("Generating 4 digits...")

func randomDigits() -> [Int] {
  var result = [Int]()
  for i in 0 ..< 4 {
    result.append(Int(arc4random_uniform(9)+1))
  }
  return result
}

// Choose 4 digits
let digits = randomDigits()

print("Make 24 using these digits : ")

for digit in digits {
  print("\(digit) ")
}
println()

// get input from operator
var input = NSString(data:NSFileHandle.fileHandleWithStandardInput().availableData, encoding:NSUTF8StringEncoding)!

var enteredDigits = [Double]()

var enteredOperations = [Character]()

let inputString = input as String

// store input in the appropriate table
for character in inputString {
  switch character {
  case "1", "2", "3", "4", "5", "6", "7", "8", "9":
    let digit = String(character)
    enteredDigits.append(Double(digit.toInt()!))
  case "+", "-", "*", "/":
    enteredOperations.append(character)
  case "\n":
    println()
  default:
    println("Invalid expression")
  }
}

// check value of expression provided by the operator
var value = 0.0

if enteredDigits.count == 4 && enteredOperations.count == 3 {
  value = enteredDigits[0]
  for (i, operation) in enumerate(enteredOperations) {
    switch operation {
    case "+":
      value = value + enteredDigits[i+1]
    case "-":
      value = value - enteredDigits[i+1]
    case "*":
      value = value * enteredDigits[i+1]
    case "/":
      value = value / enteredDigits[i+1]
    default:
      println("This message should never happen!")
    }
  }
}

func evaluate(dPerm: [Double], oPerm: [String]) -> Bool {
  var value = 0.0

  if dPerm.count == 4 && oPerm.count == 3 {
    value = dPerm[0]
    for (i, operation) in enumerate(oPerm) {
      switch operation {
      case "+":
        value = value + dPerm[i+1]
      case "-":
        value = value - dPerm[i+1]
      case "*":
        value = value * dPerm[i+1]
      case "/":
        value = value / dPerm[i+1]
      default:
        println("This message should never happen!")
      }
    }
  }
  return (abs(24 - value) < 0.001)
}

func isSolvable(inout digits: [Double]) -> Bool {

  var result = false
  var dPerms = [[Double]]()
  permute(&digits, &dPerms, 0)

  let total = 4 * 4 * 4
  var oPerms = [[String]]()
  permuteOperators(&oPerms, 4, total)


  for dig in dPerms {
    for opr in oPerms {
      var expression = ""

      if evaluate(dig, opr) {
        for digit in dig {
          expression += "\(digit)"
        }

        for oper in opr {
          expression += oper
        }

        solution = beautify(expression)
        result = true
      }
    }
  }
  return result
}

func permute(inout lst: [Double], inout res: [[Double]], k: Int) -> Void {
  for i in k ..< lst.count {
    swap(&lst[i], &lst[k])
    permute(&lst, &res, k + 1)
    swap(&lst[k], &lst[i])
  }
  if k == lst.count {
    res.append(lst)
  }
}

// n=4, total=64, npow=16
func permuteOperators(inout res: [[String]], n: Int, total: Int) -> Void {
  let posOperations = ["+", "-", "*", "/"]
  let npow = n * n
  for i in 0 ..< total {
    res.append([posOperations[(i / npow)], posOperations[((i % npow) / n)], posOperations[(i % n)]])
  }
}

func beautify(infix: String) -> String {
  let newString = infix as NSString

  var solution = ""

  solution += newString.substringWithRange(NSMakeRange(0, 1))
  solution += newString.substringWithRange(NSMakeRange(12, 1))
  solution += newString.substringWithRange(NSMakeRange(3, 1))
  solution += newString.substringWithRange(NSMakeRange(13, 1))
  solution += newString.substringWithRange(NSMakeRange(6, 1))
  solution += newString.substringWithRange(NSMakeRange(14, 1))
  solution += newString.substringWithRange(NSMakeRange(9, 1))

  return solution
}

if value != 24 {
  println("The value of the provided expression is \(value) instead of 24!")
  if isSolvable(&enteredDigits) {
    println("A possible solution could have been " + solution)
  } else {
    println("Anyway, there was no known solution to this one.")
  }
} else {
  println("Congratulations, you found a solution!")
}
```


{{out}}The program in action:
24 Game
Generating 4 digits...
Make 24 using these digits : 2 4 1 9
2+1*4+9

The value of the provided expression is 21.0 instead of 24!
A possible solution could have been 9-2-1*4

24 Game
Generating 4 digits...
Make 24 using these digits : 2 7 2 3
7-2*2*3

The value of the provided expression is 30.0 instead of 24!
A possible solution could have been 3+7+2*2

24 Game
Generating 4 digits...
Make 24 using these digits : 4 6 3 4
4+4+6+3

The value of the provided expression is 17.0 instead of 24!
A possible solution could have been 3*4-6*4

24 Game
Generating 4 digits...
Make 24 using these digits : 8 8 2 6
8+8+2+6

Congratulations, you found a solution!

24 Game
Generating 4 digits...
Make 24 using these digits : 6 7 8 9
6+7+8+9

The value of the provided expression is 30.0 instead of 24!
Anyway, there was no known solution to this one.

```



## Tcl

This is a complete Tcl script, intended to be invoked from the command line.
{{tcllib|struct::list}}

```tcl
package require struct::list
# Encoding the various expression trees that are possible
set patterns {
    {((A x B) y C) z D}
     {(A x (B y C)) z D}
     {(A x B) y (C z D)}
      {A x ((B y C) z D)}
      {A x (B y (C z D))}
}
# Encoding the various permutations of digits
set permutations [struct::list map [struct::list permutations {a b c d}] \
        {apply {v {lassign $v a b c d; list A $a B $b C $c D $d}}}]
# The permitted operations
set operations {+ - * /}

# Given a list of four integers (precondition not checked!)
# return a list of solutions to the 24 game using those four integers.
proc find24GameSolutions {values} {
    global operations patterns permutations
    set found {}
    # For each possible structure with numbers at the leaves...
    foreach pattern $patterns {
	foreach permutation $permutations {
	    set p [string map [subst {
		a [lindex $values 0].0
		b [lindex $values 1].0
		c [lindex $values 2].0
		d [lindex $values 3].0
	    }] [string map $permutation $pattern]]

            # For each possible structure with operators at the branches...
	    foreach x $operations {
		foreach y $operations {
		    foreach z $operations {
			set e [string map [subst {x $x y $y z $z}] $p]

			# Try to evaluate (div-zero is an issue!) and add it to
			# the result if it is 24
			catch {
			    if {[expr $e] == 24.0} {
				lappend found [string map {.0 {}} $e]
			    }
			}
		    }
		}
	    }
	}
    }
    return $found
}

# Wrap the solution finder into a player
proc print24GameSolutionFor {values} {
    set found [lsort -unique [find24GameSolutions $values]]
    if {![llength $found]} {
	puts "No solution possible"
    } else {
	puts "Total [llength $found] solutions (may include logical duplicates)"
        puts "First solution: [lindex $found 0]"
    }
}
print24GameSolutionFor $argv
```

{{out}}
Demonstrating it in use:
 ''bash$'' tclsh8.4 24player.tcl 3 2 8 9
 '''Total 12 solutions (may include logical duplicates)'''
 '''First solution: ((9 - 3) * 8) / 2'''
 ''bash$'' tclsh8.4 24player.tcl 1 1 2 7
 '''Total 8 solutions (may include logical duplicates)'''
 '''First solution: (1 + 2) * (1 + 7)'''
 ''bash$'' tclsh8.4 24player.tcl 1 1 1 1
 '''No solution possible'''


## Ursala

This uses exhaustive search and exact rational arithmetic to enumerate all solutions. The algorithms accommodate data sets with any number of digits and any target value, but will be limited in practice by combinatorial explosion as noted elsewhere. (Rationals are stored as pairs of integers, hence
("n",1) for n/1, etc..)

The tree_shapes function generates a list of binary trees of all possible shapes for a given
number of leaves. The with_leaves function substitutes a list of numbers into the leaves of
a tree in every possible way. The with_roots function substitutes a list of operators into the
non-terminal nodes of a tree in every possible way. The value function evaluates a tree and the
format function displays it in a readable form.

```Ursala
#import std
#import nat
#import rat

tree_shapes = "n". (@vLPiYo //eql iota "n")*~ (rep"n" ~&iiiK0NlrNCCVSPTs) {0^:<>}
with_leaves = ^|DrlDrlK34SPSL/permutations ~&
with_roots  = ^DrlDrlK35dlPvVoPSPSL\~&r @lrhvdNCBvLPTo2DlS @hiNCSPtCx ~&K0=>
value       = *^ ~&v?\(@d ~&\1) ^|H\~&hthPX '+-*/'-$
format      = *^ ~&v?\-+~&h,%zP@d+- ^H/mat@d *v ~&t?\~& :/`(+ --')'

game"n" "d" = format* value==("n",1)*~ with_roots/'+-*/' with_leaves/"d"*-1 tree_shapes length "d"
```

test program:

```Ursala
#show+

test_games = mat` * pad` *K7 pad0 game24* <<2,3,8,9>,<5,7,4,1>,<5,6,7,8>>
```

output:

```txt

8/(2/(9-3)) 1-(5-(7*4)) 6*(5+(7-8))
8*(9-(2*3)) 1-(5-(4*7)) 6*(7+(5-8))
8*(9-(3*2)) 1+((7*4)-5) 6*(7-(8-5))
8*((9-3)/2) 1+((4*7)-5) 6*(5-(8-7))
(8/2)*(9-3) (7*4)-(5-1) 6*(8/(7-5))
(9-3)/(2/8) (7*4)+(1-5) 8*(6/(7-5))
(9-3)*(8/2) (4*7)-(5-1) 6*((5+7)-8)
(8*(9-3))/2 (4*7)+(1-5) 6*((7+5)-8)
(9-(2*3))*8 (1-5)+(7*4) 6/((7-5)/8)
(9-(3*2))*8 (1-5)+(4*7) 6*((7-8)+5)
((9-3)/2)*8 (7*(5-1))-4 6*((5-8)+7)
((9-3)*8)/2 (1+(7*4))-5 8/((7-5)/6)
            (1+(4*7))-5 (5+7)*(8-6)
            ((7*4)-5)+1 (7+5)*(8-6)
            ((7*4)+1)-5 (6*8)/(7-5)
            ((4*7)-5)+1 (8-6)*(5+7)
            ((4*7)+1)-5 (8-6)*(7+5)
            ((5-1)*7)-4 (8*6)/(7-5)
                        (6/(7-5))*8
                        (5+(7-8))*6
                        (7+(5-8))*6
                        (7-(8-5))*6
                        (5-(8-7))*6
                        (8/(7-5))*6
                        ((5+7)-8)*6
                        ((7+5)-8)*6
                        ((7-8)+5)*6
                        ((5-8)+7)*6

```



## Yabasic


```Yabasic
operators$ = "*+-/"
space$ = "                                                                                "

sub present()
	clear screen
	print "24 Game"
	print "
### ======
\n"
	print "Computer provide 4 numbers (1 to 9). With operators +, -, * and / you try to\nobtain 24."
	print "Use Reverse Polish Notation (first operand and then the operators)"
	print "For example: instead of 2 + 4, type 2 4 +\n\n"
end sub

repeat
	present()
	serie$ = sortString$(genSerie$())
	valid$ = serie$+operators$
	print "If you give up, press ENTER and the program attempts to find a solution."
	line input "Write your solution: " input$
	if input$ = "" then
		print "Thinking ... "
		res$ = explorer$()
		if res$ = "" print "Can not get 24 with these numbers.."
	else
		input$ = delSpace$(input$)
		inputSort$ = sortString$(input$)
		if (right$(inputSort$,4) <> serie$) or (len(inputSort$)<>7) then
			print "Syntax error"
		else
			result = evalInput(input$)
			print "Your solution = ",result," is ";
			if result = 24 then
				print "Correct!"
			else
				print "Wrong!"
			end if
		end if
	end if
	print "\nDo you want to try again? (press N for exit, other key to continue)"
until(upper$(left$(inkey$(),1)) = "N")

exit

sub genSerie$()
	local i, c$, s$

	print "The numbers you should use are: ";
	i = ran()
	for i = 1 to 4
		c$ = str$(int(ran(9))+1)
		print c$," ";
		s$ = s$ + c$
	next i
	print
	return s$
end sub


sub evalInput(entr$)
	local d1, d2, c$, n(4), i

	while(entr$<>"")
		c$ = left$(entr$,1)
		entr$ = mid$(entr$,2)
		if instr(serie$,c$) then
			i = i + 1
			n(i) = val(c$)
		elseif instr(operators$,c$) then
			d2 = n(i)
			n(i) = 0
			i = i - 1
			if i = 0 return
			d1 = n(i)
			n(i) = evaluator(d1, d2, c$)
		else
			print "Invalid symbol"
			return
		end if
	wend

	return n(i)

end sub


sub evaluator(d1, d2, op$)
	local t

	switch op$
		case "+": t = d1 + d2 : break
		case "-": t = d1 - d2 : break
		case "*": t = d1 * d2 : break
		case "/": t = d1 / d2 : break
	end switch

	return t
end sub


sub delSpace$(entr$)
	local n, i, s$, t$(1)

	n = token(entr$,t$()," ")

	for i=1 to n
		s$ = s$ + t$(i)
	next i
	return s$
end sub


sub sortString$(string$)
	local signal, n, fin, c$

	fin = len(string$)-1
	repeat
		signal = false
		for n = 1 to fin
			if mid$(string$,n,1) > mid$(string$,n+1,1) then
				signal = true
				c$ = mid$(string$,n,1)
				mid$(string$,n,1) = mid$(string$,n+1,1)
				mid$(string$,n+1,1) = c$
			end if
		next n
	until(signal = false)
	return string$
end sub


sub explorer$()
	local d1,d2,o3,x4,x5,x6,o7,p$,result,solution,solutions$,n

	for d1 = 1 to 4
		for d2 = 1 to 4
			for o3 = 1 to 4
				for x4 = 1 to 8
					for x5 = 1 to 8
						for x6 = 1 to 8
							for o7 = 1 to 4
								p$ = mid$(serie$,d1,1)+mid$(serie$,d2,1)+mid$(operators$,o3,1)
								p$ = p$+mid$(valid$,x4,1)+mid$(valid$,x5,1)+mid$(valid$,x6,1)
								p$ = p$+mid$(operators$,o7,1)
								if not instr(solutions$,p$) then
									if validateInput(p$) then
										result = evalInput(p$)
										if result = 24 then
											solution = solution + 1
											print "Solution: ",solution," = ";
											solutions$ = solutions$ + p$
											for n = 1 to 7
												print mid$(p$,n,1)," ";
											next n
											print
										end if
									end if
								end if
							next o7
						next x6
					next x5
				next x4
			next o3
		next d2
	next d1
	return p$
end sub


sub validateInput(e$)
	local n, inputSort$

	inputSort$ = sortString$(e$)
	if serie$ <> right$(inputSort$,4) return false
	for n=1 to 3
		if not instr(operators$,mid$(inputSort$,n,1)) then
			return false
		end if
	next n
	return true
end sub
```



## zkl

A brute for search for all solutions. Lexicographical duplicates are removed.

File solve24.zkl:

```zkl
var [const] H=Utils.Helpers;
fcn u(xs){ xs.reduce(fcn(us,s){us.holds(s) and us or us.append(s) },L()) }
var ops=u(H.combosK(3,"+-*/".split("")).apply(H.permute).flatten());
var fs=T(
   fcn f0(a,b,c,d,x,y,z){ Op(z)(Op(y)(Op(x)(a,b),c),d) }, // ((AxB)yC)zD
   fcn f1(a,b,c,d,x,y,z){ Op(y)(Op(x)(a,b),Op(z)(c,d)) }, // (AxB)y(CzD)
   fcn f2(a,b,c,d,x,y,z){ Op(z)(Op(x)(a,Op(y)(b,c)),d) }, // (Ax(ByC))zD
   fcn f3(a,b,c,d,x,y,z){ Op(x)(a,Op(z)(Op(y)(b,c),d)) }, // Ax((ByC)zD)
   fcn f4(a,b,c,d,x,y,z){ Op(x)(a,Op(y)(b,Op(z)(c,d))) }, // Ax(By(CzD))
);

var fts= // format strings for human readable formulas
  T("((d.d).d).d", "(d.d).(d.d)", "(d.(d.d)).d", "d.((d.d).d)", "d.(d.(d.d))")
  .pump(List,T("replace","d","%d"),T("replace",".","%s"));

fcn f2s(digits,ops,f){
   fts[f.name[1].toInt()].fmt(digits.zip(ops).flatten().xplode(),digits[3]);
}

fcn game24Solver(digitsString){
   digits:=digitsString.split("").apply("toFloat");
   [[(digits4,ops3,f); H.permute(digits); ops;    // list comprehension
     fs,{ try{f(digits4.xplode(),ops3.xplode()).closeTo(24,0.001) }
          catch(MathError){ False } };
     { f2s(digits4,ops3,f) }]];
}
```


```zkl
solutions:=u(game24Solver(ask(0,"digits: ")));
println(solutions.len()," solutions:");
solutions.apply2(Console.println);
```

One trick used is to look at the solving functions name and use the digit in it to index into the formats list.
{{out}}

```txt

zkl solve24.zkl 6795
6 solutions:
6+((7-5)*9)
6-((5-7)*9)
6-(9*(5-7))
6+(9*(7-5))
(9*(7-5))+6
((7-5)*9)+6

zkl solve24.zkl 1111
0 solutions:

zkl solve24.zkl 3388
1 solutions:
8/(3-(8/3))

zkl solve24.zkl 1234
242 solutions:
((1+2)+3)*4
...

```


{{omit from|GUISS}}
{{omit from|ML/I}}

[[Category:Puzzles]]