The procedure **NumbersGame ** generalizes the well-known 24 game (implementation in Maple see here), as well as related issues (see here and here).

Required parameters of the procedure:

**Result** is an integer or a fraction of any sign.

**Numbers** is a list of positive integers.

Optional parameters:

**Operators** is a list of permitted arithmetic operations. By default **Operators** is **["+","-","*","/"]**

**NumbersOrder** is a string. It is equal to **"strict order"** or **"arbitrary order" **. By default **NumbersOrder **is **"strict order"**

**Parentheses** is a symbol **no** or **yes** . By default Parentheses is ** no**

The procedure puts the signs of operations from the list **Operators **between the numbers from **Numbers** so that the result is equal to **Result**. The procedure finds all possible solutions. The global **M **saves the list of the all solutions.

Code the procedure:

**restart;**

**NumbersGame:=proc(Result::{integer,fraction}, Numbers::list(posint), Operators::list:=["+","-","*","/"], NumbersOrder::string:="strict order", Parentheses::symbol:=no)**

**local MyHandler, It, K, i, P, S, n, s, L, c;**

**global M;**

**uses StringTools, ListTools, combinat;**** **

** MyHandler := proc(operator,operands,default_value)**

** NumericStatus( division_by_zero = false );**

** return infinity;**

** end proc;**

** NumericEventHandler(division_by_zero=MyHandler);**** **

**if Parentheses=yes then**** **

**It:=proc(L1,L2)**

**local i, j, L;**

**for i in L1 do**

**for j in L2 do**

**L[i,j]:=seq(Substitute(Substitute(Substitute("( i Op j )","i",convert(i,string)),"j",convert(j,string)),"Op",Operators[k]), k=1..nops(Operators));**

**od; od;**

**L:=convert(L, list);**

**end proc;**** **

**P:=proc(L::list)**

**local n, K, i, M1, M2, S;**

**n:=nops(L); **

**if n=1 then return L else**

**for i to n-1 do**

**M1:=P(L[1..i]); M2:=P(L[i+1..n]);**

**K[i]:=seq(seq(It(M1[j], M2[k]), k=1..nops(M2)), j=1..nops(M1)) **

**od; fi;**

**K:=convert(K,list);**

**end proc;**

**if NumbersOrder="arbitrary order" then S:=permute(Numbers); K:=[seq(op(Flatten([op(P(s))])), s=S)] else K:=[op(Flatten([op(P(Numbers))]))] fi;**** **

**else**** **

**if NumbersOrder="strict order" then **

**K:=[convert(Numbers[1],string)];**

**for i in Numbers[2..-1] do**

**K:=[seq(seq(cat(k, Substitute(Substitute(" j i","j",convert(j,string)),"i",convert(i,string))), k in K), j in Operators)]**

**od; else**** **

**S:=permute(Numbers); **

**for s in S do**

**L:=[convert(s[1],string)];**

**for i in s[2..-1] do**

**L:=[seq(seq(cat(k, Substitute(Substitute(" j i","j",convert(j,string)),"i",convert(i,string))), k in L), j in Operators)]**

**od; K[s]:=op(L) od; K:=convert(K,list) fi; **

**fi;**** **

**M:='M'; c:=0;**

**for i in K do**

**if parse(i)=Result then c:=c+1; if Parentheses=yes then M[i]:= convert(SubString(i,2..length(i)-1),symbol)=convert(Result,symbol) else M[i]:=convert(i,symbol)=convert(Result,symbol) fi; fi;**

**od;**** **

**if c=0 then M:=[]; return `No solutions` else M:=convert(M,list); op(M) fi;**** **

**end proc:**

Examples of use.

Example 1:

**NumbersGame(1/20, [$ 1..9]);**

1 * 2 - 3 + 4 / 5 / 6 * 7 / 8 * 9 = 1/20

Example 2. Numbers in the list **Numbers** may be repeated and permitted operations can be reduced:

**NumbersGame(15, [3,3,5,5,5], ["+","-"]);**

3 - 3 + 5 + 5 + 5 = 15

Example 3.

**NumbersGame(10, [1,2,3,4,5]);**

1 + 2 + 3 * 4 - 5 = 10

If the order of the number in **Numbers** is arbitrary, then the number of solutions is greatly increased (10 solutions displayed):

**NumbersGame(10, [1,2,3,4,5], "arbitrary order"):**

**nops(M);**

**for i to 10 do**

**M[1+50*(i-1)] od;**

If you use the parentheses, the number of solutions will increase significantly more (10 solutions displayed):

**NumbersGame(10, [1,2,3,4,5], "arbitrary order", yes):**

**nops(M);**

**for i to 10 do**

**M[1+600*(i-1)] od;**

Game.mws