24 game/Solve: Difference between revisions

m
No edit summary
m (→‎{{header|Wren}}: Minor tidy)
 
(46 intermediate revisions by 20 users not shown)
Line 10:
*   [[Arithmetic Evaluator]]
<br><br>
=={{header|11l}}==
{{trans|Nim}}
 
<syntaxhighlight lang="11l">[Char = ((Float, Float) -> Float)] op
op[Char(‘+’)] = (x, y) -> x + y
op[Char(‘-’)] = (x, y) -> x - y
op[Char(‘*’)] = (x, y) -> x * y
op[Char(‘/’)] = (x, y) -> I y != 0 {x / y} E 9999999
 
F almost_equal(a, b)
R abs(a - b) <= 1e-5
 
F solve(nums)
V syms = ‘+-*/’
V sorted_nums = sorted(nums).map(Float)
L(x, y, z) cart_product(syms, syms, syms)
V n = copy(sorted_nums)
L
V (a, b, c, d) = (n[0], n[1], n[2], n[3])
I almost_equal(:op[x](:op[y](a, b), :op[z](c, d)), 24.0)
R ‘(’a‘ ’y‘ ’b‘) ’x‘ (’c‘ ’z‘ ’d‘)’
I almost_equal(:op[x](a, :op[y](b, :op[z](c, d))), 24.0)
R a‘ ’x‘ (’b‘ ’y‘ (’c‘ ’z‘ ’d‘))’
I almost_equal(:op[x](:op[y](:op[z](c, d), b), a), 24.0)
R ‘((’c‘ ’z‘ ’d‘) ’y‘ ’b‘) ’x‘ ’a
I almost_equal(:op[x](:op[y](b, :op[z](c, d)), a), 24.0)
R ‘(’b‘ ’y‘ (’c‘ ’z‘ ’d‘)) ’x‘’a
I !n.next_permutation()
L.break
R ‘not found’
 
L(nums) [[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]]
print(‘solve(’nums‘) -> ’solve(nums))</syntaxhighlight>
 
{{out}}
<pre>
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 * (4 - 1))
solve([2, 3, 7, 3]) -> ((2 + 7) * 3) - 3
solve([8, 7, 9, 7]) -> not found
solve([1, 6, 2, 6]) -> 6 + (6 * (1 + 2))
solve([7, 9, 4, 1]) -> (1 - 9) * (4 - 7)
solve([6, 4, 2, 2]) -> (2 - 2) + (4 * 6)
solve([5, 7, 9, 7]) -> (5 + 7) * (9 - 7)
solve([3, 3, 8, 8]) -> 8 / (3 - (8 / 3))
</pre>
 
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits}}
<syntaxhighlight lang="aarch64 assembly">
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program game24Solvex64.s */
 
/*******************************************/
/* Constantes file */
/*******************************************/
/* for this file see task include a file in language AArch64 assembly*/
.include "../includeConstantesARM64.inc"
 
.equ NBDIGITS, 4 // digits number
.equ TOTAL, 24
.equ BUFFERSIZE, 80
 
/*********************************/
/* Initialized data */
/*********************************/
.data
szMessRules: .ascii "24 Game\n"
.ascii "The program will display four randomly-generated \n"
.asciz "single-digit numbers and search a solution for a total to 24\n\n"
 
szMessDigits: .asciz "The four digits are @ @ @ @ and the score is 24. \n"
szMessOK: .asciz "Solution : \n"
szMessNotOK: .asciz "No solution for this problem !! \n"
szMessNewGame: .asciz "New game (y/n) ? \n"
szMessErrOper: .asciz "Error opérator in display result !!!"
szCarriageReturn: .asciz "\n"
.align 4
qGraine: .quad 123456
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
.align 4
sZoneConv: .skip 24
sBuffer: .skip BUFFERSIZE
qTabDigit: .skip 8 * NBDIGITS // digits table
qTabOperand1: .skip 8 * NBDIGITS // operand 1 table
qTabOperand2: .skip 8 * NBDIGITS // operand 2 table
qTabOperation: .skip 8 * NBDIGITS // operator table
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: // entry of program
ldr x0,qAdrszMessRules // display rules
bl affichageMess
1:
mov x3,#0
ldr x12,qAdrqTabDigit
ldr x5,qAdrszMessDigits
2: // loop generate random digits
mov x0,#8
bl genereraleas
add x0,x0,#1
str x0,[x12,x3,lsl 3] // store in table
ldr x1,qAdrsZoneConv
bl conversion10 // call decimal conversion
mov x0,x5
ldr x1,qAdrsZoneConv // insert conversion in message
bl strInsertAtCharInc
mov x5,x0
add x3,x3,#1
cmp x3,#NBDIGITS // end ?
blt 2b // no -> loop
mov x0,x5
bl affichageMess
mov x0,#0 // start leval
mov x1,x12 // address digits table
bl searchSoluce
cmp x0,#-1 // solution ?
bne 3f // no
ldr x0,qAdrszMessOK
bl affichageMess
bl writeSoluce // yes -> write solution in buffer
ldr x0,qAdrsBuffer // and display buffer
bl affichageMess
b 10f
3: // display message no solution
ldr x0,qAdrszMessNotOK
bl affichageMess
 
 
10: // display new game ?
ldr x0,qAdrszCarriageReturn
bl affichageMess
ldr x0,qAdrszMessNewGame
bl affichageMess
bl saisie
cmp x0,#'y'
beq 1b
cmp x0,#'Y'
beq 1b
100: // standard end of the program
mov x0,0 // return code
mov x8,EXIT // request to exit program
svc 0 // perform the system call
qAdrszCarriageReturn: .quad szCarriageReturn
qAdrszMessRules: .quad szMessRules
qAdrszMessDigits: .quad szMessDigits
qAdrszMessNotOK: .quad szMessNotOK
qAdrszMessOK: .quad szMessOK
qAdrszMessNewGame: .quad szMessNewGame
qAdrsZoneConv: .quad sZoneConv
qAdrqTabDigit: .quad qTabDigit
/******************************************************************/
/* recherche solution */
/******************************************************************/
/* x0 level */
/* x1 table value address */
/* x0 return -1 if ok */
searchSoluce:
stp x1,lr,[sp,-16]! // save registres
stp x2,x3,[sp,-16]! // save registres
stp x4,x5,[sp,-16]! // save registres
stp x6,x7,[sp,-16]! // save registres
stp x8,x9,[sp,-16]! // save registres
stp x10,x11,[sp,-16]! // save registres
stp x12,fp,[sp,-16]! // save registres
sub sp,sp,#8* NBDIGITS // reserve size new digits table
mov fp,sp // frame pointer = address stack
mov x10,x1 // save table
add x9,x0,#1 // new level
mov x13,#NBDIGITS
sub x3,x13,x9 // last element digits table
ldr x4,[x1,x3,lsl 3] // load last element
cmp x4,#TOTAL // equal to total to search ?
bne 0f // no
cmp x9,#NBDIGITS // all digits are used ?
bne 0f // no
mov x0,#-1 // yes -> it is ok -> end
b 100f
0:
mov x5,#0 // indice loop 1
1: // begin loop 1
cmp x5,x3
bge 9f
ldr x4,[x10,x5,lsl 3] // load first operand
ldr x8,qAdrqTabOperand1
str x4,[x8,x9,lsl 3] // and store in operand1 table
add x6,x5,#1 // indice loop 2
2: // begin loop 2
cmp x6,x3
bgt 8f
ldr x12,[x10,x6,lsl 3] // load second operand
ldr x8,qAdrqTabOperand2
str x12,[x8,x9,lsl 3] // and store in operand2 table
mov x7,#0 // k
mov x8,#0 // n
3:
cmp x7,x5
beq 4f
cmp x7,x6
beq 4f
ldr x0,[x10,x7,lsl 3] // copy other digits in new table on stack
str x0,[fp,x8,lsl 3]
add x8,x8,#1
4:
add x7,x7,#1
cmp x7,x3
ble 3b
 
add x7,x4,x12 // addition test
str x7,[fp,x8,lsl 3] // store result of addition
mov x7,#'+'
ldr x0,qAdrqTabOperation
str x7,[x0,x9,lsl 3] // store operator
mov x0,x9 // pass new level
mov x1,fp // pass new table address on stack
bl searchSoluce
cmp x0,#0
blt 100f
// soustraction test
sub x13,x4,x12
sub x14,x12,x4
cmp x4,x12
csel x7,x13,x14,gt
str x7,[fp,x8,lsl 3]
mov x7,#'-'
ldr x0,qAdrqTabOperation
str x7,[x0,x9,lsl 3]
mov x0,x9
mov x1,fp
bl searchSoluce
cmp x0,#0
blt 100f
mul x7,x4,x12 // multiplication test
str x7,[fp,x8,lsl 3]
mov x7,#'*'
ldr x0,qAdrqTabOperation
str x7,[x0,x9,lsl 3]
mov x0,x9
mov x1,fp
bl searchSoluce
cmp x0,#0
blt 100f
5: // division test
udiv x13,x4,x12
msub x14,x13,x12,x4
cmp x14,#0
bne 6f
str x13,[fp,x8,lsl 3]
mov x7,#'/'
ldr x0,qAdrqTabOperation
str x7,[x0,x9,lsl 3]
mov x0,x9
mov x1,fp
bl searchSoluce
b 7f
6:
udiv x13,x12,x4
msub x14,x13,x4,x12
cmp x14,#0
bne 7f
str x13,[fp,x8,lsl 3]
mov x7,#'/'
ldr x0,qAdrqTabOperation
str x7,[x0,x9,lsl 3]
mov x0,x9
mov x1,fp
bl searchSoluce
7:
cmp x0,#0
blt 100f
add x6,x6,#1 // increment indice loop 2
b 2b
 
8:
add x5,x5,#1 // increment indice loop 1
b 1b
9:
100:
add sp,sp,8* NBDIGITS // stack alignement
ldp x12,fp,[sp],16 // restaur des 2 registres
ldp x10,x11,[sp],16 // restaur des 2 registres
ldp x8,x9,[sp],16 // restaur des 2 registres
ldp x6,x7,[sp],16 // restaur des 2 registres
ldp x4,x5,[sp],16 // restaur des 2 registres
ldp x2,x3,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
qAdrqTabOperand1: .quad qTabOperand1
qAdrqTabOperand2: .quad qTabOperand2
qAdrqTabOperation: .quad qTabOperation
/******************************************************************/
/* write solution */
/******************************************************************/
writeSoluce:
stp x1,lr,[sp,-16]! // save registres
stp x2,x3,[sp,-16]! // save registres
stp x4,x5,[sp,-16]! // save registres
stp x6,x7,[sp,-16]! // save registres
stp x8,x9,[sp,-16]! // save registres
stp x10,x11,[sp,-16]! // save registres
stp x12,fp,[sp,-16]! // save registres
ldr x6,qAdrqTabOperand1
ldr x7,qAdrqTabOperand2
ldr x8,qAdrqTabOperation
ldr x10,qAdrsBuffer
mov x4,#0 // buffer indice
mov x9,#1
1:
ldr x13,[x6,x9,lsl 3] // operand 1
ldr x11,[x7,x9,lsl 3] // operand 2
ldr x12,[x8,x9,lsl 3] // operator
cmp x12,#'-'
beq 2f
cmp x12,#'/'
beq 2f
b 3f
2: // if division or soustraction
cmp x13,x11 // reverse operand if operand 1 is < operand 2
bge 3f
mov x2,x13
mov x13,x11
mov x11,x2
3: // conversion operand 1 = x13
mov x1,#10
udiv x2,x13,x1
msub x3,x1,x2,x13
cmp x2,#0
beq 31f
add x2,x2,#0x30
strb w2,[x10,x4]
add x4,x4,#1
31:
add x3,x3,#0x30
strb w3,[x10,x4]
add x4,x4,#1
ldr x2,[x7,x9,lsl 3]
 
strb w12,[x10,x4] // operator
add x4,x4,#1
mov x1,#10 // conversion operand 2 = x11
udiv x2,x11,x1
msub x3,x2,x1,x11
cmp x2,#0
beq 32f
add x2,x2,#0x30
strb w2,[x10,x4]
add x4,x4,#1
32:
add x3,x3,#0x30
strb w3,[x10,x4]
add x4,x4,#1
mov x0,#'='
strb w0,[x10,x4] // compute sous total
add x4,x4,#1
cmp x12,'+' // addition
bne 33f
add x0,x13,x11
b 37f
33:
cmp x12,'-' // soustraction
bne 34f
sub x0,x13,x11
b 37f
34:
cmp x12,'*' // multiplication
bne 35f
mul x0,x13,x11
b 37f
35:
cmp x12,'/' // division
bne 36f
udiv x0,x13,x11
b 37f
36: // error
ldr x0,qAdrszMessErrOper
bl affichageMess
b 100f
37: // and conversion ascii
mov x1,#10
udiv x2,x0,x1
msub x3,x2,x1,x0
cmp x2,#0
beq 36f
add x2,x2,#0x30
strb w2,[x10,x4]
add x4,x4,#1
36:
add x3,x3,#0x30
strb w3,[x10,x4]
add x4,x4,#1
mov x0,#'\n'
strb w0,[x10,x4]
add x4,x4,#1
add x9,x9,1
cmp x9,#NBDIGITS
blt 1b
mov x1,#0
strb w1,[x10,x4] // store 0 final
100:
ldp x12,fp,[sp],16 // restaur des 2 registres
ldp x10,x11,[sp],16 // restaur des 2 registres
ldp x8,x9,[sp],16 // restaur des 2 registres
ldp x6,x7,[sp],16 // restaur des 2 registres
ldp x4,x5,[sp],16 // restaur des 2 registres
ldp x2,x3,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
qAdrsBuffer: .quad sBuffer
qAdrszMessErrOper: .quad szMessErrOper
/******************************************************************/
/* string entry */
/******************************************************************/
/* x0 return the first character of human entry */
saisie:
stp x1,lr,[sp,-16]! // save registres
stp x2,x8,[sp,-16]! // save registres
mov x0,#STDIN // Linux input console
ldr x1,qAdrsBuffer // buffer address
mov x2,#BUFFERSIZE // buffer size
mov x8,#READ // request to read datas
svc 0 // call system
ldr x1,qAdrsBuffer // buffer address
ldrb w0,[x1] // load first character
100:
ldp x2,x8,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
/***************************************************/
/* Generation random number */
/***************************************************/
/* x0 contains limit */
genereraleas:
stp x1,lr,[sp,-16]! // save registres
stp x2,x3,[sp,-16]! // save registres
stp x4,x5,[sp,-16]! // save registres
ldr x4,qAdrqGraine
ldr x2,[x4]
ldr x3,qNbDep1
mul x2,x3,x2
ldr x3,qNbDep2
add x2,x2,x3
str x2,[x4] // maj de la graine pour l appel suivant
cmp x0,#0
beq 100f
add x1,x0,#1 // divisor
mov x0,x2 // dividende
udiv x3,x2,x1
msub x0,x3,x1,x0 // résult = remainder
100: // end function
 
ldp x4,x5,[sp],16 // restaur des 2 registres
ldp x2,x3,[sp],16 // restaur des 2 registres
ldp x1,lr,[sp],16 // restaur des 2 registres
ret
/*****************************************************/
qAdrqGraine: .quad qGraine
qNbDep1: .quad 0x0019660d
qNbDep2: .quad 0x3c6ef35f
/********************************************************/
/* File Include fonctions */
/********************************************************/
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
{{Output}}
<pre>
The four digits are 6 8 3 1 and the score is 24.
Solution :
6*8=48
3-1=2
48/2=24
 
New game (y/n) ?
y
The four digits are 8 6 6 5 and the score is 24.
Solution :
8-5=3
6*3=18
6+18=24
 
New game (y/n) ?
</pre>
 
=={{header|ABAP}}==
Line 15 ⟶ 526:
 
Note: the permute function was locally from [[Permutations#ABAP|here]]
<langsyntaxhighlight ABAPlang="abap">data: lv_flag type c,
lv_number type i,
lt_numbers type table of i.
Line 212 ⟶ 723:
modify iv_set index lv_perm from lv_temp_2.
modify iv_set index lv_len from lv_temp.
endform.</langsyntaxhighlight>
 
Sample Runs:
Line 505 ⟶ 1,016:
=={{header|Argile}}==
{{works with|Argile|1.0.0}}
<langsyntaxhighlight Argilelang="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 \
Line 602 ⟶ 1,113:
(roperators[(rrop[rpn][2])]) (rdigits[3]);
return buffer as text
nil</langsyntaxhighlight>
Examples:
<pre>$ arc 24_game_solve.arg -o 24_game_solve.c
Line 614 ⟶ 1,125:
$ ./24_game_solve 1127
(1+2)*(1+7)</pre>
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi}}
<syntaxhighlight lang="arm assembly">
/* ARM assembly Raspberry PI */
/* program game24Solver.s */
 
/* REMARK 1 : this program use routines in a include file
see task Include a file language arm assembly
for the routine affichageMess conversion10
see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes */
/************************************/
.include "../constantes.inc"
.equ STDIN, 0 @ Linux input console
.equ READ, 3 @ Linux syscall
.equ NBDIGITS, 4 @ digits number
.equ TOTAL, 24
.equ BUFFERSIZE, 80
 
/*********************************/
/* Initialized data */
/*********************************/
.data
szMessRules: .ascii "24 Game\n"
.ascii "The program will display four randomly-generated \n"
.asciz "single-digit numbers and search a solution for a total to 24\n\n"
 
szMessDigits: .asciz "The four digits are @ @ @ @ and the score is 24. \n"
szMessOK: .asciz "Solution : \n"
szMessNotOK: .asciz "No solution for this problem !! \n"
szMessNewGame: .asciz "New game (y/n) ? \n"
szCarriageReturn: .asciz "\n"
.align 4
iGraine: .int 123456
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
.align 4
sZoneConv: .skip 24
sBuffer: .skip BUFFERSIZE
iTabDigit: .skip 4 * NBDIGITS @ digits table
iTabOperand1: .skip 4 * NBDIGITS @ operand 1 table
iTabOperand2: .skip 4 * NBDIGITS @ operand 2 table
iTabOperation: .skip 4 * NBDIGITS @ operator table
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: @ entry of program
ldr r0,iAdrszMessRules @ display rules
bl affichageMess
1:
mov r3,#0
ldr r12,iAdriTabDigit
ldr r5,iAdrszMessDigits
2: @ loop generate random digits
mov r0,#8
bl genereraleas
add r0,r0,#1
str r0,[r12,r3,lsl #2] @ store in table
ldr r1,iAdrsZoneConv
bl conversion10 @ call decimal conversion
mov r2,#0
strb r2,[r1,r0] @ reduce size display area with zéro final
mov r0,r5
ldr r1,iAdrsZoneConv @ insert conversion in message
bl strInsertAtCharInc
mov r5,r0
add r3,r3,#1
cmp r3,#NBDIGITS @ end ?
blt 2b @ no -> loop
mov r0,r5
bl affichageMess
mov r0,#0 @ start leval
mov r1,r12 @ address digits table
bl searchSoluce
cmp r0,#-1 @ solution ?
bne 3f @ no
ldr r0,iAdrszMessOK
bl affichageMess
bl writeSoluce @ yes -> write solution in buffer
ldr r0,iAdrsBuffer @ and display buffer
bl affichageMess
b 10f
3: @ display message no solution
ldr r0,iAdrszMessNotOK
bl affichageMess
 
 
10: @ display new game ?
ldr r0,iAdrszCarriageReturn
bl affichageMess
ldr r0,iAdrszMessNewGame
bl affichageMess
bl saisie
cmp r0,#'y'
beq 1b
cmp r0,#'Y'
beq 1b
100: @ standard end of the program
mov r0, #0 @ return code
mov r7, #EXIT @ request to exit program
svc #0 @ perform the system call
iAdrszCarriageReturn: .int szCarriageReturn
iAdrszMessRules: .int szMessRules
iAdrszMessDigits: .int szMessDigits
iAdrszMessNotOK: .int szMessNotOK
iAdrszMessOK: .int szMessOK
iAdrszMessNewGame: .int szMessNewGame
iAdrsZoneConv: .int sZoneConv
iAdriTabDigit: .int iTabDigit
/******************************************************************/
/* recherche solution */
/******************************************************************/
/* r0 level */
/* r1 table value address */
/* r0 return -1 if ok */
searchSoluce:
push {r1-r12,lr} @ save registers
sub sp,#4* NBDIGITS @ reserve size new digits table
mov fp,sp @ frame pointer = address stack
mov r10,r1 @ save table
add r9,r0,#1 @ new level
rsb r3,r9,#NBDIGITS @ last element digits table
ldr r4,[r1,r3,lsl #2] @ load last element
cmp r4,#TOTAL @ equal to total to search ?
bne 0f @ no
cmp r9,#NBDIGITS @ all digits are used ?
bne 0f @ no
mov r0,#-1 @ yes -> it is ok -> end
b 100f
0:
mov r5,#0 @ indice loop 1
1: @ begin loop 1
cmp r5,r3
bge 9f
ldr r4,[r10,r5,lsl #2] @ load first operand
ldr r8,iAdriTabOperand1
str r4,[r8,r9,lsl #2] @ and store in operand1 table
add r6,r5,#1 @ indice loop 2
2: @ begin loop 2
cmp r6,r3
bgt 8f
ldr r12,[r10,r6,lsl #2] @ load second operand
ldr r8,iAdriTabOperand2
str r12,[r8,r9,lsl #2] @ and store in operand2 table
mov r7,#0 @ k
mov r8,#0 @ n
3:
cmp r7,r5
beq 4f
cmp r7,r6
beq 4f
ldr r0,[r10,r7,lsl #2] @ copy other digits in new table on stack
str r0,[fp,r8,lsl #2]
add r8,r8,#1
4:
add r7,r7,#1
cmp r7,r3
ble 3b
 
add r7,r4,r12 @ addition test
str r7,[fp,r8,lsl #2] @ store result of addition
mov r7,#'+'
ldr r0,iAdriTabOperation
str r7,[r0,r9,lsl #2] @ store operator
mov r0,r9 @ pass new level
mov r1,fp @ pass new table address on stack
bl searchSoluce
cmp r0,#0
blt 100f
@ soustraction test
cmp r4,r12
subgt r7,r4,r12
suble r7,r12,r4
str r7,[fp,r8,lsl #2]
mov r7,#'-'
ldr r0,iAdriTabOperation
str r7,[r0,r9,lsl #2]
mov r0,r9
mov r1,fp
bl searchSoluce
cmp r0,#0
blt 100f
mul r7,r4,r12 @ multiplication test
str r7,[fp,r8,lsl #2]
mov r7,#'*'
//vidregtit mult
ldr r0,iAdriTabOperation
str r7,[r0,r9,lsl #2]
mov r0,r9
mov r1,fp
bl searchSoluce
cmp r0,#0
blt 100f
5: @ division test
push {r1-r3}
mov r0,r4
mov r1,r12
bl division
// mov r7,r9
cmp r3,#0
bne 6f
str r2,[fp,r8,lsl #2]
mov r7,#'/'
ldr r0,iAdriTabOperation
str r7,[r0,r9,lsl #2]
mov r0,r9
mov r1,fp
bl searchSoluce
b 7f
6:
mov r0,r12
mov r1,r4
bl division
cmp r3,#0
bne 7f
str r2,[fp,r8,lsl #2]
mov r7,#'/'
ldr r0,iAdriTabOperation
str r7,[r0,r9,lsl #2]
mov r0,r9
mov r1,fp
bl searchSoluce
7:
pop {r1-r3}
cmp r0,#0
blt 100f
add r6,r6,#1 @ increment indice loop 2
b 2b
 
8:
add r5,r5,#1 @ increment indice loop 1
b 1b
9:
100:
add sp,#4* NBDIGITS @ stack alignement
pop {r1-r12,lr}
bx lr @ return
iAdriTabOperand1: .int iTabOperand1
iAdriTabOperand2: .int iTabOperand2
iAdriTabOperation: .int iTabOperation
/******************************************************************/
/* write solution */
/******************************************************************/
writeSoluce:
push {r1-r12,lr} @ save registers
ldr r6,iAdriTabOperand1
ldr r7,iAdriTabOperand2
ldr r8,iAdriTabOperation
ldr r10,iAdrsBuffer
mov r4,#0 @ buffer indice
mov r9,#1
1:
ldr r5,[r6,r9,lsl #2] @ operand 1
ldr r11,[r7,r9,lsl #2] @ operand 2
ldr r12,[r8,r9,lsl #2] @ operator
cmp r12,#'-'
beq 2f
cmp r12,#'/'
beq 2f
b 3f
2: @ if division or soustraction
cmp r5,r11 @ reverse operand if operand 1 is < operand 2
movlt r2,r5
movlt r5,r11
movlt r11,r2
3: @ conversion operand 1 = r0
mov r0,r5
mov r1,#10
bl division
cmp r2,#0
addne r2,r2,#0x30
strneb r2,[r10,r4]
addne r4,r4,#1
add r3,r3,#0x30
strb r3,[r10,r4]
add r4,r4,#1
ldr r2,[r7,r9,lsl #2]
 
strb r12,[r10,r4] @ operator
add r4,r4,#1
mov r0,r11 @ conversion operand 2
mov r1,#10
bl division
cmp r2,#0
addne r2,r2,#0x30
strneb r2,[r10,r4]
addne r4,r4,#1
add r3,r3,#0x30
strb r3,[r10,r4]
add r4,r4,#1
mov r0,#'='
str r0,[r10,r4] @ conversion sous total
add r4,r4,#1
cmp r12,#'+'
addeq r0,r5,r11
cmp r12,#'-'
subeq r0,r5,r11
cmp r12,#'*'
muleq r0,r5,r11
cmp r12,#'/'
udiveq r0,r5,r11
 
mov r1,#10
bl division
cmp r2,#0
addne r2,r2,#0x30
strneb r2,[r10,r4]
addne r4,r4,#1
add r3,r3,#0x30
strb r3,[r10,r4]
add r4,r4,#1
mov r0,#'\n'
str r0,[r10,r4]
add r4,r4,#1
add r9,#1
cmp r9,#NBDIGITS
blt 1b
mov r1,#0
strb r1,[r10,r4] @ store 0 final
100:
pop {r1-r12,lr}
bx lr @ return
iAdrsBuffer: .int sBuffer
 
/******************************************************************/
/* string entry */
/******************************************************************/
/* r0 return the first character of human entry */
saisie:
push {r1-r7,lr} @ save registers
mov r0,#STDIN @ Linux input console
ldr r1,iAdrsBuffer @ buffer address
mov r2,#BUFFERSIZE @ buffer size
mov r7,#READ @ request to read datas
svc 0 @ call system
ldr r1,iAdrsBuffer @ buffer address
ldrb r0,[r1] @ load first character
100:
pop {r1-r7,lr}
bx lr @ return
/***************************************************/
/* Generation random number */
/***************************************************/
/* r0 contains limit */
genereraleas:
push {r1-r4,lr} @ save registers
ldr r4,iAdriGraine
ldr r2,[r4]
ldr r3,iNbDep1
mul r2,r3,r2
ldr r3,iNbDep2
add r2,r2,r3
str r2,[r4] @ maj de la graine pour l appel suivant
cmp r0,#0
beq 100f
add r1,r0,#1 @ divisor
mov r0,r2 @ dividende
bl division
mov r0,r3 @ résult = remainder
100: @ end function
pop {r1-r4,lr} @ restaur registers
bx lr @ return
/*****************************************************/
iAdriGraine: .int iGraine
iNbDep1: .int 0x343FD
iNbDep2: .int 0x269EC3
/***************************************************/
/* ROUTINES INCLUDE */
/***************************************************/
.include "../affichage.inc"
 
</syntaxhighlight>
{{output}}
<pre>
New game (y/n) ?
y
The four digits are 8 3 9 1 and the score is 24.
Solution :
8*9=72
3*1=3
72/3=24
 
New game (y/n) ?
y
The four digits are 7 7 9 4 and the score is 24.
No solution for this problem !!
 
New game (y/n) ?
y
The four digits are 3 5 8 9 and the score is 24.
Solution :
3*9=27
8-5=3
27-3=24
 
New game (y/n) ?
</pre>
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}}
Output is in RPN.
<langsyntaxhighlight AHKlang="ahk">#NoEnv
InputBox, NNNN ; user input 4 digits
NNNN := RegExReplace(NNNN, "(\d)(?=\d)", "$1,") ; separate with commas for the sort command
Line 725 ⟶ 1,650:
o := A_LoopField o
return o
}</langsyntaxhighlight>
{{out}}for 1127:
<pre>
Line 740 ⟶ 1,665:
 
=={{header|BBC BASIC}}==
<langsyntaxhighlight lang="bbcbasic">
PROCsolve24("1234")
PROCsolve24("6789")
Line 797 ⟶ 1,722:
IF I% > 4 PRINT "No solution found"
ENDPROC
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 807 ⟶ 1,732:
 
=={{header|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.
<lang C>#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
Tested with GCC 10.2.0, but should work with all versions supporting C99.<br>
#define n_cards 4
Provided code prints all solutions or nothing in case no solutions are found.<br>
#define solve_goal 24
It can be modified or extended to work with more than 4 numbers, goals other than 24 and additional operations.<br>
#define max_digit 9
Note: This a brute-force approach with time complexity <em>O(6<sup>n</sup>.n.(2n-3)!!)</em> and recursion depth <em>n</em>.<br>
 
<syntaxhighlight lang="c">#include <stdio.h>
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{int *exprval, op, left, right;} Node;
typedef struct expr_t {
op_type op;
expr left, right;
int value;
} expr_t;
 
Node nodes[10000];
void show_expr(expr e, op_type prec, int is_right)
int iNodes;
{
 
const char * op;
int b;
switch(e->op) {
float eval(Node x){
case C_NUM: printf("%d", e->value);
if (x.op != -1){
return;
casefloat C_ADD:l = eval(nodes[x.left]), opr = " + "; breakeval(nodes[x.right]);
case C_SUB: switch(x.op = " - "; break;){
case C_MUL: case 0: op = " x ";return breakl+r;
case C_DIV: case 1: op = " / ";return breakl-r;
case 2: return r-l;
case 3: return l*r;
case 4: return r?l/r:(b=1,0);
case 5: return l?r/l:(b=1,0);
}
}
 
else return x.val*1.;
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_exprshow(exprNode e, frac fx){
if (x.op != -1){
{
frac_t left, rightprintf("(");
if switch(e->x.op == C_NUM) {
case 0: show(nodes[x.left]); printf(" f->num+ ="); e->valueshow(nodes[x.right]); break;
case 1: show(nodes[x.left]); printf(" f->denom ="); 1show(nodes[x.right]); break;
case 2: show(nodes[x.right]); printf(" return- "); show(nodes[x.left]); break;
case 3: show(nodes[x.left]); printf(" * "); show(nodes[x.right]); break;
}
case 4: show(nodes[x.left]); printf(" / "); show(nodes[x.right]); break;
eval_expr(e->left, &left);
eval_expr case 5: show(e->nodes[x.right,]); &rightprintf(" / "); show(nodes[x.left]); break;
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;
}
printf(")");
}
else printf("%d", x.val);
}
int solve(expr ex_in[], int len)
{
int i, j;
expr_t node;
expr ex[n_cards];
frac_t final;
 
int float_fix(float x){ return x < 0.00001 && x > -0.00001; }
if (len == 1) {
 
eval_expr(ex_in[0], &final);
void solutions(int a[], int n, float t, int s){
if (final.num == final.denom * solve_goal && final.denom) {
if (s == n){
show_expr(ex_in[0], 0, 0);
b = return 10;
float e = eval(nodes[0]); }
return 0;
if (!b && float_fix(e-t)){
show(nodes[0]);
printf("\n");
}
}
else{
nodes[iNodes++] = (typeof(Node)){a[s],-1,-1,-1};
for (int op = 0; op < 6; op++){
int k = iNodes-1;
for (int i = 0; i < k; i++){
nodes[iNodes++] = nodes[i];
nodes[i] = (typeof(Node)){-1,op,iNodes-1,iNodes-2};
solutions(a, n, t, s+1);
nodes[i] = nodes[--iNodes];
}
}
iNodes--;
}
};
 
int main(){
for (i = 0; i < len - 1; i++) {
// define problem
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;
 
int a[4] = {8, 3, 8, 3};
node.left = ex_in[j];
float t = 24;
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;
 
// print all solutions
ex[j] = ex_in[j];
}
ex[i] = ex_in[i];
}
 
nodes[0] = (typeof(Node)){a[0],-1,-1,-1};
return 0;
iNodes = 1;
}
 
solutions(a, sizeof(a)/sizeof(int), t, 1);
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);
}
 
return 0;
int main()
}</syntaxhighlight>
{
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;
}</lang>
{{out}}
<pre> 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</pre>
For the heck of it, using seven numbers ranging from 0 to 99, trying to calculate 1:
<pre> 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</pre>
 
=={{header|C++}}==
Line 981 ⟶ 1,828:
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.
 
<langsyntaxhighlight lang="cpp">
#include <iostream>
#include <ratio>
Line 1,072 ⟶ 1,919:
return 0;
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,122 ⟶ 1,969:
(( 5 + 3 ) * 3 ) / 1
</pre>
 
=={{header|C sharp|C#}}==
Generate binary trees -> generate permutations -> create expression -> evaluate expression<br/>
This works with other targets and more numbers but it will of course become slower.<br/>
Redundant expressions are filtered out (based on https://www.4nums.com/theory/) but I'm not sure I caught them all.
{{works with|C sharp|8}}
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using static System.Linq.Enumerable;
 
public static class Solve24Game
{
public static void Main2() {
var testCases = new [] {
new [] { 1,1,2,7 },
new [] { 1,2,3,4 },
new [] { 1,2,4,5 },
new [] { 1,2,7,7 },
new [] { 1,4,5,6 },
new [] { 3,3,8,8 },
new [] { 4,4,5,9 },
new [] { 5,5,5,5 },
new [] { 5,6,7,8 },
new [] { 6,6,6,6 },
new [] { 6,7,8,9 },
};
foreach (var t in testCases) Test(24, t);
Test(100, 9,9,9,9,9,9);
 
static void Test(int target, params int[] numbers) {
foreach (var eq in GenerateEquations(target, numbers)) Console.WriteLine(eq);
Console.WriteLine();
}
}
 
static readonly char[] ops = { '*', '/', '+', '-' };
public static IEnumerable<string> GenerateEquations(int target, params int[] numbers) {
var operators = Repeat(ops, numbers.Length - 1).CartesianProduct().Select(e => e.ToArray()).ToList();
return (
from pattern in Patterns(numbers.Length)
let expression = CreateExpression(pattern)
from ops in operators
where expression.WithOperators(ops).HasPreferredTree()
from permutation in Permutations(numbers)
let expr = expression.WithValues(permutation)
where expr.Value == target && expr.HasPreferredValues()
select $"{expr.ToString()} = {target}")
.Distinct()
.DefaultIfEmpty($"Cannot make {target} with {string.Join(", ", numbers)}");
}
 
///<summary>Generates postfix expression trees where 1's represent operators and 0's represent numbers.</summary>
static IEnumerable<int> Patterns(int length) {
if (length == 1) yield return 0; //0
if (length == 2) yield return 1; //001
if (length < 3) yield break;
//Of each tree, the first 2 bits must always be 0 and the last bit must be 1. Generate the bits in between.
length -= 2;
int len = length * 2 + 3;
foreach (int permutation in BinaryPatterns(length, length * 2)) {
(int p, int l) = ((permutation << 1) + 1, len);
if (IsValidPattern(ref p, ref l)) yield return (permutation << 1) + 1;
}
}
 
///<summary>Generates all numbers with the given number of 1's and total length.</summary>
static IEnumerable<int> BinaryPatterns(int ones, int length) {
int initial = (1 << ones) - 1;
int blockMask = (1 << length) - 1;
for (int v = initial; v >= initial; ) {
yield return v;
int w = (v | (v - 1)) + 1;
w |= (((w & -w) / (v & -v)) >> 1) - 1;
v = w & blockMask;
}
}
 
static bool IsValidPattern(ref int pattern, ref int len) {
bool isNumber = (pattern & 1) == 0;
pattern >>= 1;
len--;
if (isNumber) return true;
IsValidPattern(ref pattern, ref len);
IsValidPattern(ref pattern, ref len);
return len == 0;
}
 
static Expr CreateExpression(int pattern) {
return Create();
 
Expr Create() {
bool isNumber = (pattern & 1) == 0;
pattern >>= 1;
if (isNumber) return new Const(0);
Expr right = Create();
Expr left = Create();
return new Binary('*', left, right);
}
}
 
static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) {
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from acc in accumulator
from item in sequence
select acc.Concat(new [] { item }));
}
 
private static List<int> helper = new List<int>();
public static IEnumerable<T[]> Permutations<T>(params T[] input) {
if (input == null || input.Length == 0) yield break;
helper.Clear();
for (int i = 0; i < input.Length; i++) helper.Add(i);
while (true) {
yield return input;
int cursor = helper.Count - 2;
while (cursor >= 0 && helper[cursor] > helper[cursor + 1]) cursor--;
if (cursor < 0) break;
int i = helper.Count - 1;
while (i > cursor && helper[i] < helper[cursor]) i--;
(helper[cursor], helper[i]) = (helper[i], helper[cursor]);
(input[cursor], input[i]) = (input[i], input[cursor]);
int firstIndex = cursor + 1;
for (int lastIndex = helper.Count - 1; lastIndex > firstIndex; ++firstIndex, --lastIndex) {
(helper[firstIndex], helper[lastIndex]) = (helper[lastIndex], helper[firstIndex]);
(input[firstIndex], input[lastIndex]) = (input[lastIndex], input[firstIndex]);
}
}
}
 
static Expr WithOperators(this Expr expr, char[] operators) {
int i = 0;
SetOperators(expr, operators, ref i);
return expr;
 
static void SetOperators(Expr expr, char[] operators, ref int i) {
if (expr is Binary b) {
b.Symbol = operators[i++];
SetOperators(b.Right, operators, ref i);
SetOperators(b.Left, operators, ref i);
}
}
}
 
static Expr WithValues(this Expr expr, int[] values) {
int i = 0;
SetValues(expr, values, ref i);
return expr;
 
static void SetValues(Expr expr, int[] values, ref int i) {
if (expr is Binary b) {
SetValues(b.Left, values, ref i);
SetValues(b.Right, values, ref i);
} else {
expr.Value = values[i++];
}
}
}
 
static bool HasPreferredTree(this Expr expr) => expr switch {
Const _ => true,
// a / b * c => a * c / b
((_, '/' ,_), '*', _) => false,
// c + a * b => a * b + c
(var l, '+', (_, '*' ,_) r) when l.Depth < r.Depth => false,
// c + a / b => a / b + c
(var l, '+', (_, '/' ,_) r) when l.Depth < r.Depth => false,
// a * (b + c) => (b + c) * a
(var l, '*', (_, '+' ,_) r) when l.Depth < r.Depth => false,
// a * (b - c) => (b - c) * a
(var l, '*', (_, '-' ,_) r) when l.Depth < r.Depth => false,
// (a +- b) + (c */ d) => ((c */ d) + a) +- b
((_, var p, _), '+', (_, var q, _)) when "+-".Contains(p) && "*/".Contains(q) => false,
// a + (b + c) => (a + b) + c
(var l, '+', (_, '+' ,_) r) => false,
// a + (b - c) => (a + b) - c
(var l, '+', (_, '-' ,_) r) => false,
// a - (b + c) => (a - b) + c
(_, '-', (_, '+', _)) => false,
// a * (b * c) => (a * b) * c
(var l, '*', (_, '*' ,_) r) => false,
// a * (b / c) => (a * b) / c
(var l, '*', (_, '/' ,_) r) => false,
// a / (b / c) => (a * c) / b
(var l, '/', (_, '/' ,_) r) => false,
// a - (b - c) * d => (c - b) * d + a
(_, '-', ((_, '-' ,_), '*', _)) => false,
// a - (b - c) / d => (c - b) / d + a
(_, '-', ((_, '-' ,_), '/', _)) => false,
// a - (b - c) => a + c - b
(_, '-', (_, '-', _)) => false,
// (a - b) + c => (a + c) - b
((_, '-', var b), '+', var c) => false,
 
(var l, _, var r) => l.HasPreferredTree() && r.HasPreferredTree()
};
 
static bool HasPreferredValues(this Expr expr) => expr switch {
Const _ => true,
 
// -a + b => b - a
(var l, '+', var r) when l.Value < 0 && r.Value >= 0 => false,
// b * a => a * b
(var l, '*', var r) when l.Depth == r.Depth && l.Value > r.Value => false,
// b + a => a + b
(var l, '+', var r) when l.Depth == r.Depth && l.Value > r.Value => false,
// (b o c) * (a o d) => (a o d) * (b o c)
((var a, _, _) l, '*', (var c, _, _) r) when l.Value == r.Value && l.Depth == r.Depth && a.Value < c.Value => false,
// (b o c) + (a o d) => (a o d) + (b o c)
((var a, var p, _) l, '+', (var c, var q, _) r) when l.Value == r.Value && l.Depth == r.Depth && a.Value < c.Value => false,
// (a * c) * b => (a * b) * c
((_, '*', var c), '*', var b) when b.Value < c.Value => false,
// (a + c) + b => (a + b) + c
((_, '+', var c), '+', var b) when b.Value < c.Value => false,
// (a - b) - c => (a - c) - b
((_, '-', var b), '-', var c) when b.Value < c.Value => false,
// a / 1 => a * 1
(_, '/', var b) when b.Value == 1 => false,
// a * b / b => a + b - b
((_, '*', var b), '/', var c) when b.Value == c.Value => false,
// a * 1 * 1 => a + 1 - 1
((_, '*', var b), '*', var c) when b.Value == 1 && c.Value == 1 => false,
 
(var l, _, var r) => l.HasPreferredValues() && r.HasPreferredValues()
};
 
private struct Fraction : IEquatable<Fraction>, IComparable<Fraction>
{
public readonly int Numerator, Denominator;
 
public Fraction(int numerator, int denominator)
=> (Numerator, Denominator) = (numerator, denominator) switch
{
(_, 0) => (Math.Sign(numerator), 0),
(0, _) => (0, 1),
(_, var d) when d < 0 => (-numerator, -denominator),
_ => (numerator, denominator)
};
 
public static implicit operator Fraction(int i) => new Fraction(i, 1);
public static Fraction operator +(Fraction a, Fraction b) =>
new Fraction(a.Numerator * b.Denominator + a.Denominator * b.Numerator, a.Denominator * b.Denominator);
public static Fraction operator -(Fraction a, Fraction b) =>
new Fraction(a.Numerator * b.Denominator + a.Denominator * -b.Numerator, a.Denominator * b.Denominator);
public static Fraction operator *(Fraction a, Fraction b) =>
new Fraction(a.Numerator * b.Numerator, a.Denominator * b.Denominator);
public static Fraction operator /(Fraction a, Fraction b) =>
new Fraction(a.Numerator * b.Denominator, a.Denominator * b.Numerator);
 
public static bool operator ==(Fraction a, Fraction b) => a.CompareTo(b) == 0;
public static bool operator !=(Fraction a, Fraction b) => a.CompareTo(b) != 0;
public static bool operator <(Fraction a, Fraction b) => a.CompareTo(b) < 0;
public static bool operator >(Fraction a, Fraction b) => a.CompareTo(b) > 0;
public static bool operator <=(Fraction a, Fraction b) => a.CompareTo(b) <= 0;
public static bool operator >=(Fraction a, Fraction b) => a.CompareTo(b) >= 0;
 
public bool Equals(Fraction other) => Numerator == other.Numerator && Denominator == other.Denominator;
public override string ToString() => Denominator == 1 ? Numerator.ToString() : $"[{Numerator}/{Denominator}]";
 
public int CompareTo(Fraction other) => (Numerator, Denominator, other.Numerator, other.Denominator) switch {
var ( n1, d1, n2, d2) when n1 == n2 && d1 == d2 => 0,
( 0, 0, _, _) => (-1),
( _, _, 0, 0) => 1,
var ( n1, d1, n2, d2) when d1 == d2 => n1.CompareTo(n2),
(var n1, 0, _, _) => Math.Sign(n1),
( _, _, var n2, 0) => Math.Sign(n2),
var ( n1, d1, n2, d2) => (n1 * d2).CompareTo(n2 * d1)
};
}
 
private abstract class Expr
{
protected Expr(char symbol) => Symbol = symbol;
public char Symbol { get; set; }
public abstract Fraction Value { get; set; }
public abstract int Depth { get; }
public abstract void Deconstruct(out Expr left, out char symbol, out Expr right);
}
 
private sealed class Const : Expr
{
public Const(Fraction value) : base('c') => Value = value;
public override Fraction Value { get; set; }
public override int Depth => 0;
public override void Deconstruct(out Expr left, out char symbol, out Expr right) => (left, symbol, right) = (this, Symbol, this);
public override string ToString() => Value.ToString();
}
 
private sealed class Binary : Expr
{
public Binary(char symbol, Expr left, Expr right) : base(symbol) => (Left, Right) = (left, right);
public Expr Left { get; }
public Expr Right { get; }
public override int Depth => Math.Max(Left.Depth, Right.Depth) + 1;
public override void Deconstruct(out Expr left, out char symbol, out Expr right) => (left, symbol, right) = (Left, Symbol, Right);
 
public override Fraction Value {
get => Symbol switch {
'*' => Left.Value * Right.Value,
'/' => Left.Value / Right.Value,
'+' => Left.Value + Right.Value,
'-' => Left.Value - Right.Value,
_ => throw new InvalidOperationException() };
set {}
}
 
public override string ToString() => Symbol switch {
'*' => ToString("+-".Contains(Left.Symbol), "+-".Contains(Right.Symbol)),
'/' => ToString("+-".Contains(Left.Symbol), "*/+-".Contains(Right.Symbol)),
'+' => ToString(false, false),
'-' => ToString(false, "+-".Contains(Right.Symbol)),
_ => $"[{Value}]"
};
 
private string ToString(bool wrapLeft, bool wrapRight) =>
$"{(wrapLeft ? $"({Left})" : $"{Left}")} {Symbol} {(wrapRight ? $"({Right})" : $"{Right}")}";
}
}</syntaxhighlight>
{{out}}
<pre>
(1 + 2) * (1 + 7) = 24
 
(1 + 3) * (2 + 4) = 24
1 * 2 * 3 * 4 = 24
(1 + 2 + 3) * 4 = 24
 
(5 - 1) * (2 + 4) = 24
(2 + 5 - 1) * 4 = 24
 
(7 * 7 - 1) / 2 = 24
 
4 / (1 - 5 / 6) = 24
6 / (5 / 4 - 1) = 24
 
8 / (3 - 8 / 3) = 24
 
Cannot make 24 with 4, 4, 5, 9
 
5 * 5 - 5 / 5 = 24
 
(8 - 6) * (5 + 7) = 24
6 * 8 / (7 - 5) = 24
(5 + 7 - 8) * 6 = 24
 
6 + 6 + 6 + 6 = 24
6 * 6 - 6 - 6 = 24
 
6 * 8 / (9 - 7) = 24
 
(9 / 9 + 9) * (9 / 9 + 9) = 100</pre>
 
=={{header|Ceylon}}==
Don't forget to import ceylon.random in your module.ceylon file.
<langsyntaxhighlight lang="ceylon">import ceylon.random {
DefaultRandom
}
Line 1,257 ⟶ 2,457:
expressions.each(print);
}
}</langsyntaxhighlight>
 
=={{header|Clojure}}==
<langsyntaxhighlight Clojurelang="clojure">(ns rosettacode.24game.solve
(:require [clojure.math.combinatorics :as c]
[clojure.walk :as w]))
Line 1,284 ⟶ 2,484:
(map println)
doall
count))</langsyntaxhighlight>
 
The function <code>play24</code> 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))).
Line 1,290 ⟶ 2,490:
 
=={{header|COBOL}}==
<langsyntaxhighlight lang="cobol"> >>SOURCE FORMAT FREE
*> This code is dedicated to the public domain
*> This is GNUCobol 2.0
Line 1,735 ⟶ 2,935:
end-perform
.
end program twentyfoursolve.</langsyntaxhighlight>
 
{{out}}
Line 1,765 ⟶ 2,965:
 
=={{header|CoffeeScript}}==
<langsyntaxhighlight lang="coffeescript">
# This program tries to find some way to turn four digits into an arithmetic
# expression that adds up to 24.
Line 1,853 ⟶ 3,053:
solution = solve_24_game a, b, c, d
console.log "Solution for #{[a,b,c,d]}: #{solution ? 'no solution'}"
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,876 ⟶ 3,076:
=={{header|Common Lisp}}==
 
<langsyntaxhighlight lang="lisp">(defconstant +ops+ '(* / + -))
 
(defun digits ()
Line 1,931 ⟶ 3,131:
digits which evaluates to 24. The first form found is returned, or
NIL if there is no solution."
(solvable-p digits))</langsyntaxhighlight>
 
{{out}}
Line 1,949 ⟶ 3,149:
This uses the Rational struct and permutations functions of two other Rosetta Code Tasks.
{{trans|Scala}}
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.range, std.conv, std.string,
std.concurrency, permutations2, arithmetic_rational;
 
Line 1,984 ⟶ 3,184:
foreach (const prob; [[6, 7, 9, 5], [3, 3, 8, 8], [1, 1, 1, 1]])
writeln(prob, ": ", solve(24, prob));
}</langsyntaxhighlight>
{{out}}
<pre>[6, 7, 9, 5]: (6+(9*(7-5)))
Line 1,993 ⟶ 3,193:
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.
 
<langsyntaxhighlight lang="scheme">
;; use task [[RPN_to_infix_conversion#EchoLisp]] to print results
(define (rpn->string rpn)
Line 2,105 ⟶ 3,305:
(writeln digits '→ target)
(try-rpn digits target))
</langsyntaxhighlight>
 
{{out}}
Line 2,152 ⟶ 3,352:
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule Game24 do
@expressions [ ["((", "", ")", "", ")", ""],
["(", "(", "", "", "))", ""],
Line 2,197 ⟶ 3,397:
IO.puts "found #{length(solutions)} solutions, including #{hd(solutions)}"
IO.inspect Enum.sort(solutions)
end</langsyntaxhighlight>
 
{{out}}
Line 2,218 ⟶ 3,418:
=={{header|ERRE}}==
ERRE hasn't an "EVAL" function so we must write an evaluation routine; this task is solved via "brute-force".
<syntaxhighlight lang="err">
<lang ERR>
PROGRAM 24SOLVE
 
Line 2,530 ⟶ 3,730:
 
END PROGRAM
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,553 ⟶ 3,753:
Via brute force.
 
<syntaxhighlight lang="euler math toolbox">
<lang Euler Math Toolbox>
>function try24 (v) ...
$n=cols(v);
Line 2,576 ⟶ 3,776:
$return 0;
$endfunction
</syntaxhighlight>
</lang>
 
<syntaxhighlight lang="euler math toolbox">
<lang Euler Math Toolbox>
>try24([1,2,3,4]);
Solved the problem
Line 2,599 ⟶ 3,799:
-1+5=4
3-4=-1
</syntaxhighlight>
</lang>
 
=={{header|F_Sharp|F#}}==
Line 2,605 ⟶ 3,805:
It eliminates all duplicate solutions which result from transposing equal digits.
The basic solution is an adaption of the OCaml program.
<langsyntaxhighlight lang="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)
Line 2,713 ⟶ 3,913:
|> Seq.groupBy id
|> Seq.iter (fun x -> printfn "%s" (fst x))
0</langsyntaxhighlight>
{{out}}
<pre>>solve24 3 3 3 4
Line 2,742 ⟶ 3,942:
=={{header|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 <code>call</code> each quotation and print out the ones that equal 24. The <code>recover</code> word is an exception handler that is used to intercept divide-by-zero errors and continue gracefully by removing those quotations from consideration.
<langsyntaxhighlight lang="factor">USING: continuations grouping io kernel math math.combinatorics
prettyprint quotations random sequences sequences.deep ;
IN: rosetta-code.24-game
Line 2,759 ⟶ 3,959:
print expressions [ [ 24= ] [ 2drop ] recover ] each ;
24-game</langsyntaxhighlight>
{{out}}
<pre>
Line 2,787 ⟶ 3,987:
 
=={{header|Fortran}}==
<langsyntaxhighlight Fortranlang="fortran">program solve_24
use helpers
implicit none
Line 2,855 ⟶ 4,055:
end function op
 
end program solve_24</langsyntaxhighlight>
 
<langsyntaxhighlight Fortranlang="fortran">module helpers
 
contains
Line 2,928 ⟶ 4,128:
end subroutine nextpermutation
 
end module helpers</langsyntaxhighlight>
{{out}} (using g95):
<pre> 3 6 7 9 : 3 *(( 6 - 7 )+ 9 )
Line 2,943 ⟶ 4,143:
2 4 6 8 : (( 2 / 4 )* 6 )* 8
</pre>
 
 
=={{header|FutureBasic}}==
This programme gives just the first-found (simplest) solution. To see the exhaustive list, we would remove the '''if k > 0 then exit fn''' statements.
<syntaxhighlight lang="futurebasic>
 
begin globals
Short k
end globals
 
void local fn eval( t as CFStringRef )
CFMutableStringRef s = fn MutableStringNew
ExpressionRef x = fn ExpressionWithFormat( t )
CFRange r = fn CFRangeMake(0, fn StringLength( t ) )
CFNumberRef n = fn ExpressionValueWithObject( x, Null, Null )
Float f = dblval( n )
if f = 24 // found, so clean up
MutableStringSetString( s, t ) // duplicate string and pretend it was integers all along
MutableStringReplaceOccurrencesOfString( s, @".000000", @"", Null, r )
print s; @" = 24" : k ++
end if
end fn
 
 
clear local fn work( t as CFStringRef )
Short a, b, c, d, e, f, g
CGFloat n(3)
CFStringRef s, os = @"*/+-", o(3)
print t, : k = 0
// Put digits (as floats) and operators (as strings) in arrays
for a = 0 to 3 : s = mid( t, a, 1 ) : n(a) = fn StringFloatValue( s ) : o(a) = mid( os, a, 1 ) : next
// Permutions for the digits ...
for d = 0 to 3 : for e = 0 to 3 : for f = 0 to 3 : for g = 0 to 3
if d != e and d != f and d != g and e != f and e != g and f != g // ... without duplications
// Combinations for the operators (3 from 4, with replacement)
for a = 0 to 3 : for b = 0 to 3 : for c = 0 to 3
fn eval( fn StringWithFormat( @"%f %@ %f %@ %f %@ %f", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"%f %@ ( %f %@ %f ) %@ %f", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"%f %@ %f %@ ( %f %@ %f )", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"%f %@ ( %f %@ %f %@ %f )", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"( %f %@ %f ) %@ %f %@ %f", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"( %f %@ %f %@ %f ) %@ %f", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"%f %@ ( %f %@ ( %f %@ %f ) )", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"( %f %@ %f ) %@ ( %f %@ %f )", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"( %f %@ ( %f %@ %f )) %@ %f", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"( ( %f %@ %f ) %@ %f ) %@ %f", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
fn eval( fn StringWithFormat( @"%f %@ ( ( %f %@ %f ) %@ %f )", n(d), o(a), n(e), o(b), n(f), o(c), n(g) ) ) : if k > 0 then exit fn
next : next : next
end if
next : next : next : next
end fn
 
 
window 1, @"24 Game", ( 0, 0, 250, 250 )
fn work(@"3388")
fn work(@"1346")
fn work(@"8752")
 
handleevents
 
</syntaxhighlight>
{{out}}
 
[[File:FB 24.jpg]]
 
=={{header|GAP}}==
<langsyntaxhighlight lang="gap"># Solution in '''RPN'''
check := function(x, y, z)
local r, c, s, i, j, k, a, b, p;
Line 3,028 ⟶ 4,292:
# A tricky one:
Player24([3,3,8,8]);
"8383/-/"</langsyntaxhighlight>
 
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 3,202 ⟶ 4,465:
}
}
}</langsyntaxhighlight>
{{out}}
<pre> 8 6 7 6: No solution
Line 3,217 ⟶ 4,480:
 
=={{header|Gosu}}==
<syntaxhighlight lang="gosu">
<lang Gosu>
uses java.lang.Integer
uses java.lang.Double
Line 3,328 ⟶ 4,591:
print( "No solution!" )
}
</syntaxhighlight>
</lang>
 
=={{header|Haskell}}==
 
<langsyntaxhighlight lang="haskell">import Data.List
import Data.Ratio
import Control.Monad
Line 3,381 ⟶ 4,644:
nub $ permutations $ map Constant r4
 
main = getArgs >>= mapM_ print . solve 24 . map (toEnum . read)</langsyntaxhighlight>
 
Example use:
Line 3,399 ⟶ 4,662:
(8 / (2 / (9 - 3)))</pre>
===Alternative version===
<langsyntaxhighlight lang="haskell">import Control.Applicative
import Data.List
import Text.PrettyPrint
Line 3,440 ⟶ 4,703:
 
main = mapM_ (putStrLn . render . toDoc) $ solve 24 [2,3,8,9]</langsyntaxhighlight>
{{out}}
<pre>((8 / 2) * (9 - 3))
Line 3,456 ⟶ 4,719:
(((9 - 3) * 8) / 2)</pre>
 
== {{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.
 
<langsyntaxhighlight Iconlang="icon">invocable all
link strings # for csort, deletec, permutes
 
Line 3,534 ⟶ 4,797:
suspend 2(="(", E(), =")") | # parenthesized subexpression, or ...
tab(any(&digits)) # just a value
end</langsyntaxhighlight>
 
 
Line 3,541 ⟶ 4,804:
 
=={{header|J}}==
<langsyntaxhighlight Jlang="j">perm=: (A.&i.~ !) 4
ops=: ' ',.'+-*%' {~ >,{i.each 4 4 4
cmask=: 1 + 0j1 * i.@{:@$@[ e. ]
Line 3,549 ⟶ 4,812:
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</langsyntaxhighlight>
 
This implementation tests all 7680 candidate sentences.
Line 3,563 ⟶ 4,826:
 
The answer will be either a suitable J sentence or blank if none can be found. "J sentence" means that, for example, the sentence <code>8*7-4*1</code> is equivalent to the sentence <code>8*(7-(4*1))</code>. [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.]
 
Here is an alternative version that supports multi-digit numbers. It prefers expressions without parens, but searches for ones with if needed.
 
<syntaxhighlight lang="j">ops=: > , { 3#<'+-*%'
perms=: [: ":"0 [: ~. i.@!@# A. ]
build=: 1 : '(#~ 24 = ".) @: u'
 
combp=: dyad define
'a b c d'=. y['f g h'=. x
('(',a,f,b,g,c,')',h,d),('(',a,f,b,')',g,c,h,d),(a,f,'(',b,g,c,')',h,d),:('((',a,f,b,')',g,c,')',h,d)
)
 
math24=: monad define
assert. 4 = # y NB. prefer expressions without parens & fallback if needed
es=. ([: ,/ ops ([: , (' ',[) ,. ])"1 2/ perms) build y
if. 0 = #es do. es =. ([: ,/ [: ,/ ops combp"1 2/ perms) build y end.
es -."1 ' '
)</syntaxhighlight>
 
{{out}}
<pre> math24 2 3 5 12
12%3-5%2
math24 2 3 8 9
8*9-2*3
8*9-3*2
8%2%9-3
math24 3 6 6 11
(6+6*11)%3
(6+11*6)%3
((6*11)+6)%3
((11*6)+6)%3
</pre>
 
=={{header|Java}}==
Line 3,569 ⟶ 4,864:
 
Note that this version does not extend to different digit ranges.
<langsyntaxhighlight lang="java">import java.util.*;
 
public class Game24Player {
Line 3,832 ⟶ 5,127:
res.add(Arrays.asList((i / npow), (i % npow) / n, i % n));
}
}</langsyntaxhighlight>
 
{{out}}
Line 3,876 ⟶ 5,171:
=={{header|JavaScript}}==
This is a translation of the C code.
<langsyntaxhighlight lang="javascript">var ar=[],order=[0,1,2],op=[],val=[];
var NOVAL=9999,oper="+-*/",out;
 
Line 3,979 ⟶ 5,274:
solve24("1234");
solve24("6789");
solve24("1127");</langsyntaxhighlight>
 
Examples:
Line 3,993 ⟶ 5,288:
 
'''Infrastructure:'''
<langsyntaxhighlight lang="jq"># Generate a stream of the permutations of the input array.
def permutations:
if length == 0 then []
Line 4,030 ⟶ 5,325:
| ($in[$i+1:] | triples) as $tail
| [$head, $in[$i], $tail]
end;</langsyntaxhighlight>
'''Evaluation and pretty-printing of allowed expressions'''
<langsyntaxhighlight lang="jq"># Evaluate the input, which must be a number or a triple: [x, op, y]
def eval:
if type == "array" then
Line 4,054 ⟶ 5,349:
 
def pp:
"\(.)" | explode | map([.] | implode | if . == "," then " " elif . == "\"" then "" else . end) | join("");</langsyntaxhighlight>
 
'''24 Game''':
<langsyntaxhighlight lang="jq">def OPERATORS: ["+", "-", "*", "/"];
 
# Input: an array of 4 digits
Line 4,077 ⟶ 5,372:
;
 
solve(24), "Please try again."</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="sh">$ jq -r -f Solve.jq
[1,2,3,4]
That was too easy. I found 242 answers, e.g. [4 * [1 + [2 + 3]]]
Line 4,094 ⟶ 5,389:
[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.</langsyntaxhighlight>
 
=={{header|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.
<langsyntaxhighlight lang="julia">function solve24(nums)
length(nums) != 4 && error("Input must be a 4-element Array")
syms = [+,-,*,/]
Line 4,117 ⟶ 5,412:
end
return "0"
end</langsyntaxhighlight>
{{out}}
<pre>julia> for i in 1:10
Line 4,136 ⟶ 5,431:
=={{header|Kotlin}}==
{{trans|C}}
<langsyntaxhighlight lang="scala">// version 1.1.3
 
import java.util.Random
Line 4,234 ⟶ 5,529:
println(if (solve24(n)) "" else "No solution")
}
}</langsyntaxhighlight>
 
Sample output:
Line 4,251 ⟶ 5,546:
 
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">dim d(4)
input "Enter 4 digits: "; a$
nD=0
Line 4,373 ⟶ 5,668:
exit function
[handler]
end function</langsyntaxhighlight>
 
=={{header|Lua}}==
Line 4,379 ⟶ 5,674:
Generic solver: pass card of any size with 1st argument and target number with second.
 
<langsyntaxhighlight lang="lua">
local SIZE = #arg[1]
local GOAL = tonumber(arg[2]) or 24
Line 4,454 ⟶ 5,749:
 
permgen(input, SIZE)
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,494 ⟶ 5,789:
=={{header|Mathematica}} / {{header|Wolfram Language}}==
The code:
<syntaxhighlight lang="mathematica">
<lang Mathematica>
treeR[n_] := Table[o[trees[a], trees[n - a]], {a, 1, n - 1}]
treeR[1] := n
Line 4,510 ⟶ 5,805:
Permutations[Array[v, 4]], 1]],
Quiet[(# /. v[q_] :> val[[q]]) == 24] &] /.
Table[v[q] -> val[[q]], {q, 4}])]</langsyntaxhighlight>
 
The <code>treeR</code> 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, <code>treeR[4]</code> is allotted 4 inputs, so it returns <code>{o[treeR[3],treeR[1]],o[treeR[2],treeR[2]],o[treeR[1],treeR[3]]}</code>, where <code>o</code> is the operator (generic at this point).
Line 4,544 ⟶ 5,839:
**For each result, turn the expression into a string (for easy manipulation), strip the "<code>HoldForm</code>" 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:
 
<langsyntaxhighlight Mathematicalang="mathematica">game24play[RandomInteger[{1, 9}, 4]]</langsyntaxhighlight>
 
{{out}}
Line 4,569 ⟶ 5,864:
An alternative solution operates on Mathematica expressions directly without using any inert intermediate form for the expression tree, but by using <code>Hold</code> to prevent Mathematica from evaluating the expression tree.
 
<langsyntaxhighlight Mathematicalang="mathematica">evaluate[HoldForm[op_[l_, r_]]] := op[evaluate[l], evaluate[r]];
evaluate[x_] := x;
combine[l_, r_ /; evaluate[r] != 0] := {HoldForm[Plus[l, r]],
Line 4,603 ⟶ 5,898:
solveMaintainOrder[1/5, Range[2, 5]]
solveCanPermute[1/5, Range[2, 5]]
solveSubsets[1/5, Range[2, 5]]</langsyntaxhighlight>
 
=={{header|Nim}}==
 
{{trans|Python Succinct}}
{{works with|Nim Compiler|0.19.4}}
 
<langsyntaxhighlight lang="nim">import algorithm, sequtils, strformat
 
type
Line 4,620 ⟶ 5,916:
const Ops = @[opAdd, opSub, opMul, opDiv]
 
procfunc opr(o: Operation, a, b: float): float =
case o
of opAdd: a + b
Line 4,627 ⟶ 5,923:
of opDiv: a / b
 
procfunc solve(nums: array[4, int]): string =
func `~=`(a, b: float): bool =
abs(a - b) <= 1e-5
Line 4,664 ⟶ 5,960:
echo fmt"solve({nums}) -> {solve(nums)}"
 
when isMainModule: main()</langsyntaxhighlight>
 
{{out}}
Line 4,683 ⟶ 5,979:
=={{header|OCaml}}==
 
<langsyntaxhighlight lang="ocaml">type expression =
| Const of float
| Sum of expression * expression (* e1 + e2 *)
Line 4,752 ⟶ 6,048:
| x::xs -> comp x xs
| [] -> assert false
) all</langsyntaxhighlight>
 
<pre>
Line 4,768 ⟶ 6,064:
 
Note: the <code>permute</code> function was taken from [http://faq.perl.org/perlfaq4.html#How_do_I_permute_N_e here]
<langsyntaxhighlight Perllang="perl"># Fischer-Krause ordered permutation generator
# http://faq.perl.org/perlfaq4.html#How_do_I_permute_N_e
sub permute :prototype(&@) {
my $code = shift;
my @idx = 0..$#_;
Line 4,821 ⟶ 6,117:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>E:\Temp>24solve.pl
Line 4,849 ⟶ 6,145:
E:\Temp></pre>
 
=={{header|Perl 6Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
 
<span style="color: #000080;font-style:italic;">-- demo\rosetta\24_game_solve.exw</span>
===With EVAL===
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
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.
<span style="color: #000080;font-style:italic;">-- The following 5 parse expressions are possible.
 
-- Obviously numbers 1234 represent 24 permutations from
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"<sup>&trade;</sup>
-- {1,2,3,4} to {4,3,2,1} of indexes to the real numbers.
 
-- Likewise "+-*" is like "123" representing 64 combinations
<lang perl6>use MONKEY-SEE-NO-EVAL;
-- from {1,1,1} to {4,4,4} of indexes to "+-*/".
 
-- Both will be replaced if/when the strings get printed.
my @digits;
-- Last hint is because of no precedence, just parenthesis.
my $amount = 4;
--</span>
 
<span style="color: #008080;">constant</span> <span style="color: #000000;">OPS</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"+-*/"</span>
# Get $amount digits from the user,
<span style="color: #008080;">constant</span> <span style="color: #000000;">expressions</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"1+(2-(3*4))"</span><span style="color: #0000FF;">,</span>
# ask for more if they don't supply enough
<span style="color: #008000;">"1+((2-3)*4)"</span><span style="color: #0000FF;">,</span>
while @digits.elems < $amount {
<span style="color: #008000;">"(1+2)-(3*4)"</span><span style="color: #0000FF;">,</span>
@digits.append: (prompt "Enter {$amount - @digits} digits from 1 to 9, "
<span style="color: #008000;">"(1+(2-3))*4"</span><span style="color: #0000FF;">,</span>
~ '(repeats allowed): ').comb(/<[1..9]>/);
<span style="color: #008000;">"((1+2)-3)*4"</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- (equivalent to "1+2-3*4")
}
# Throw away any extras
-- The above represented as three sequential operations (the result gets
@digits = @digits[^$amount];
-- left in &lt;(map)1&gt;, ie vars[perms[operations[i][3][1]]] aka vars[lhs]):</span>
 
<span style="color: #008080;">constant</span> <span style="color: #000000;">operations</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'*'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'+'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}},</span> <span style="color: #000080;font-style:italic;">--3*=4; 2-=3; 1+=2</span>
# Generate combinations of operators
<span style="color: #0000FF;">{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'*'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'+'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}},</span> <span style="color: #000080;font-style:italic;">--2-=3; 2*=4; 1+=2</span>
my @ops = [X,] <+ - * /> xx 3;
<span style="color: #0000FF;">{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'+'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'*'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">}},</span> <span style="color: #000080;font-style:italic;">--1+=2; 3*=4; 1-=3</span>
 
<span style="color: #0000FF;">{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'+'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'*'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}},</span> <span style="color: #000080;font-style:italic;">--2-=3; 1+=2; 1*=4</span>
# Enough sprintf formats to cover most precedence orderings
<span style="color: #0000FF;">{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'+'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'*'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}}}</span> <span style="color: #000080;font-style:italic;">--1+=2; 1-=3; 1*=4</span>
my @formats = (
'%d %s %d %s %d %s %d',
<span style="color: #008080;">function</span> <span style="color: #000000;">evalopset</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">opset</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">perms</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ops</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">)</span>
'(%d %s %d) %s %d %s %d',
<span style="color: #000080;font-style:italic;">-- invoked 5*24*64 = 7680 times, to try all possible expressions/vars/operators
'(%d %s %d %s %d) %s %d',
-- (btw, vars is copy-on-write, like all parameters not explicitly returned, so
'((%d %s %d) %s %d) %s %d',
-- we can safely re-use it without clobbering the callee version.)
'(%d %s %d) %s (%d %s %d)',
-- (update: with js made that illegal and reported it correctly and forced the
'%d %s (%d %s %d %s %d)',
-- addition of the deep_copy(), all exactly the way it should.)</span>
'%d %s (%d %s (%d %s %d))',
<span style="color: #004080;">integer</span> <span style="color: #000000;">lhs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rhs</span>
);
<span style="color: #000000;">vars</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vars</span><span style="color: #0000FF;">)</span>
 
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">opset</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
# Brute force test the different permutations
<span style="color: #0000FF;">{</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">opset</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
(unique @digits.permutations).race.map: -> @p {
<span style="color: #000000;">lhs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">perms</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">]</span>
for @ops -> @o {
<span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ops</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">OPS</span><span style="color: #0000FF;">)]</span>
for @formats -> $format {
<span style="color: #000000;">rhs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">perms</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">]</span>
my $string = sprintf $format, flat roundrobin(|@p; |@o);
<span style="color: #008080;">if</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'+'</span> <span style="color: #008080;">then</span>
my $result = EVAL($string);
<span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">]</span>
say "$string = 24" and last if $result and $result == 24;
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'-'</span> <span style="color: #008080;">then</span>
}
<span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">]</span>
}
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'*'</span> <span style="color: #008080;">then</span>
}
<span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">]</span>
 
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'/'</span> <span style="color: #008080;">then</span>
# Only return unique sub-arrays
<span style="color: #008080;">if</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">1e300</span><span style="color: #0000FF;">*</span><span style="color: #000000;">1e300</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
sub unique (@array) {
<span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">/=</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rhs</span><span style="color: #0000FF;">]</span>
my %h = map { $_.Str => $_ }, @array;
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
%h.values;
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
}</lang>
<span style="color: #008080;">return</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lhs</span><span style="color: #0000FF;">]</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">nSolutions</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">xSolutions</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">success</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">expr</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">perms</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ops</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">expr</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">expr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #008000;">'1'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #008000;">'9'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">expr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">perms</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">]]+</span><span style="color: #008000;">'0'</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #000000;">OPS</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">expr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ops</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">expr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">xSolutions</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- 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.</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"success: %s = %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">expr</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)})</span>
<span style="color: #000000;">nSolutions</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">xSolutions</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xSolutions</span><span style="color: #0000FF;">,</span><span style="color: #000000;">expr</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">tryperms</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">perms</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ops</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">operations</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">-- 5 parse expressions</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">evalopset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">operations</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">perms</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ops</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">round</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1e9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- fudge tricky 8/(3-(8/3)) case</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">24</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">success</span><span style="color: #0000FF;">(</span><span style="color: #000000;">expressions</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">perms</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ops</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">tryops</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">ops</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">-- 24 var permutations</span>
<span style="color: #000000;">tryperms</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}),</span><span style="color: #000000;">ops</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">procedure</span> <span style="color: #000000;">solve24</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">vars</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">nSolutions</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">xSolutions</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">op1</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">op2</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">op3</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">-- 64 operator combinations</span>
<span style="color: #000000;">tryops</span><span style="color: #0000FF;">({</span><span style="color: #000000;">OPS</span><span style="color: #0000FF;">[</span><span style="color: #000000;">op1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">OPS</span><span style="color: #0000FF;">[</span><span style="color: #000000;">op2</span><span style="color: #0000FF;">],</span><span style="color: #000000;">OPS</span><span style="color: #0000FF;">[</span><span style="color: #000000;">op3</span><span style="color: #0000FF;">]},</span><span style="color: #000000;">vars</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n%d solutions\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">nSolutions</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">solve24</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">})</span>
<span style="color: #000080;font-style:italic;">--solve24({6,4,6,1})
--solve24({3,3,8,8})
--solve24({6,9,7,4})</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
success: (1+2)*(7+1) = 24
Enter 4 digits from 1 to 9, (repeats allowed): 3711
success: (1 + 7) * 3 * (1+2) = 24
success: (1 + 72) * 3 / (1+7) = 24
success: (2+1 * 3) * (7+1 + 7) = 24
3success: (7+1)* (1 + 1 * 72) = 24
success: (3 * 2+1) * (1 + 7) = 24
3 *success: (1 / 1 + 7)*(2+1) = 24
success: (3 / 7+1) * (2+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
 
8 solutions
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
</pre>
 
=={{header|Picat}}==
===No EVAL===
<syntaxhighlight lang="picat">main =>
Alternately, a version that doesn't use EVAL. More general case. Able to handle 3 or 4 integers, able to select the goal value.
foreach (_ in 1..10)
Nums = [D : _ in 1..4, D = random() mod 9 + 1],
NumExps = [(D,D) : D in Nums],
println(Nums),
(solve(NumExps) -> true; println("No solution")),
nl
end.
 
solve([(Num,Exp)]), Num =:= 24 =>
<lang perl6>my %*SUB-MAIN-OPTS = :named-anywhere;
println(Exp).
solve(NumExps) =>
select((Num1,Exp1),NumExps,NumExps1),
select((Num2,Exp2),NumExps1,NumExps2),
member(Op, ['+','-','*','/']),
(Op == '/' -> Num2 =\= 0; true),
Num3 = apply(Op,Num1,Num2),
Exp3 =.. [Op,Exp1,Exp2],
solve([(Num3,Exp3)|NumExps2]).
</syntaxhighlight>
 
{{trans|Raku}}
sub MAIN (*@parameters, Int :$goal = 24) {
<syntaxhighlight lang="picat">import util.
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
}
 
main =>
sub solve (@numbers, $goal = 24) {
Target=24,
my @operators = < + - * / >;
Nums = [5,6,7,8],
my @ops = [X] @operators xx (@numbers - 1);
my @perms = @numbers.permutations.unique( :with(&[eqv]) );
All=findall(Expr, solve_num(Nums,Target,Expr)),
my @order = (^(@numbers - 1)).permutations;
foreach(Expr in All) println(Expr.flatten()) end,
my @sol;
println(len=All.length),
@sol[250]; # preallocate some stack space
nl.
 
% A string based approach, inspired by - among others - the Raku solution.
my $batch = ceiling +@perms/4;
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().
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}";
}
 
ignore(_E) => fail. % ignore zero_divisor errors
sub evaluate ( @digit, @ops, @orders ) {
my @result = @digit.map: { [ $_, $_ ] };
my @offset = 0 xx +@orders;
 
% Replace all occurrences in S with From -> To.
for ^@orders {
replace_all(S,From,To) = Res =>
my $this = @orders[$_];
R = S,
my $order = $this - @offset[$this];
foreach({F,T} in zip(From,To))
my $op = @ops[$this];
R := replace(R, F,T.to_string())
my $result = op( $op, @result[$order;0], @result[$order+1;0] );
end,
return [ NaN, Str ] unless defined $result;
Res = R.</syntaxhighlight>
my $string = "({@result[$order;1]} $op {@result[$order+1;1]})";
@result.splice: $order, 2, [ $[ $result, $string ] ];
@offset[$_]++ if $order < $_ for ^@offset;
}
@result[0];
}
 
{{out}}
multi op ( '+', $m, $n ) { $m + $n }
<pre>
multi op ( '-', $m, $n ) { $m - $n }
Picat> main
multi op ( '/', $m, $n ) { $n == 0 ?? fail() !! $m / $n }
multi op ( '*', $m, $n ) { $m * $n }
 
(5 + 7 - 8) * 6
my $txt = "\e[0;96m";
((5 + 7) - 8) * 6
my $cmd = "\e[0;92m> {$*EXECUTABLE-NAME} {$*PROGRAM-NAME}";
(5 + 7) * (8 - 6)
sub USAGE {
(5 - 8 + say7) qq:to* 6
((5 - 8) + 7) * 6
'========================================================================'
6 * (5 + 7 - 8)
{$txt}Supply 3 or 4 integers on the command line, and optionally a value
6 * (5 + to(7 equate- to.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</pre>
 
Another approach:
Integers may be all one group: {$cmd} 2233{$txt}
Or, separated by spaces: {$cmd} 2 4 6 7{$txt}
 
<syntaxhighlight lang="picat">import util.
If you wish to supply multi-digit or negative numbers, you must
separate them with spaces: {$cmd} -2 6 12{$txt}
 
main =>
If you wish to use a different equate value,
Target=24,
supply a new --goal parameter: {$cmd} --goal=17 2 -3 1 9{$txt}
Nums = [5,6,7,8],
_ = findall(Expr, solve_num2(Nums,Target)),
nl.
 
solve_num2(Nums, Target) =>
If you don't supply any parameters, will use 24 as the goal, will run a
Syms = [+,-,*,/],
demo and will show this message.\e[0m
Perms = permutations([I.to_string() : I in Nums]),
========================================================================
Seen = new_map(), % weed out duplicates
}</lang>
foreach(X in Syms,Y in Syms, Z in Syms)
{{out}}
foreach(P in Perms)
When supplied 1399 on the command line:
[A,B,C,D] = P,
<pre>(((9 - 1) / 3) * 9)
if catch(check(A,X,B,Y,C,Z,D,Target,Expr),E,ignore(E)),
((9 - 1) / (3 / 9))
not Seen.has_key(Expr) then
((9 / 3) * (9 - 1))
println(Expr.flatten()=Expr.eval().round()),
(9 / (3 / (9 - 1)))
Seen.put(Expr,1)
((9 * (9 - 1)) / 3)
(9 * ((9 - 1) / 3)) end
(((9 - 1) * 9) / 3)end
end.
((9 - 1) * (9 / 3))
8 equations evaluate to 24 using: 1 3 9 9</pre>
 
to_string2(Expr) = [E.to_string() : E in Expr].flatten().
=={{header|Phix}}==
<lang 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...
 
ignore(_E) => fail. % ignore zero_divisor errors
-- 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".
 
check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
function evalopset(sequence opset, sequence perms, sequence ops, sequence vars)
Expr = ["(",A,Y,B,")",X,"(",C,Z,D,")"].to_string2(),
-- invoked 5*24*64 = 7680 times, to try all possible expressions/vars/operators
Target =:= Expr.eval().
-- (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
 
check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
integer nSolutions
Expr = [A,X,"(",B,Y,"(",C,Z,D,")",")"].to_string2(),
sequence xSolutions
Target =:= Expr.eval().
 
check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
procedure success(string expr, sequence perms, sequence ops, sequence vars, atom r)
Expr = ["(","(",C,Z,D,")",Y,B,")",X,A].to_string2(),
integer ch
Target for i=1:= to lengthExpr.eval(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
 
check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
procedure tryperms(sequence perms, sequence ops, sequence vars)
Expr = ["(",B,Y,"(",C,Z,D,")",")",X,A].to_string2(),
atom r
Target =:= Expr.eval().
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
 
check(A,X,B,Y,C,Z,D,Target,Expr) =>
include builtins/factorial.e
Expr = [A,X,"(","(",B,Y,C,")", Z,D,")"].to_string2(),
include builtins/permute.e
Target =:= Expr.eval().</syntaxhighlight>
 
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</lang>
{{out}}
<pre>> main
success: 6*(15+2)*(7+1-8)) = 24
success: 6*(17+7(5-8)*(1+2) = 24
success: (15+27)*(1+78-6) = 24
success: (27+15)*(7+18-6) = 24
success: 6*((7+1-8)*(1+25) = 24
success: (2+1)6*(1(5-8)+7) = 24
success: (1(5+7)-8)*(2+1)6 = 24
success: ((7+15)-8)*(2+1)6 = 24
(8-6)*(5+7) = 24
 
(8-6)*(7+5) = 24
8 solutions
6*(7-(8-5)) = 24
</pre>
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</pre>
 
=={{header|PicoLisp}}==
We use Pilog (PicoLisp Prolog) to solve this task
<langsyntaxhighlight PicoLisplang="picolisp">(be play24 (@Lst @Expr) # Define Pilog rule
(permute @Lst (@A @B @C @D))
(member @Op1 (+ - * /))
Line 5,208 ⟶ 6,464:
(println @X) ) )
 
(play24 5 6 7 8) # Call 'play24' function</langsyntaxhighlight>
{{out}}
<pre>(* (+ 5 7) (- 8 6))
Line 5,227 ⟶ 6,483:
Note
This example uses the math module:
<langsyntaxhighlight ProDOSlang="prodos">editvar /modify -random- = <10
:a
editvar /newvar /withothervar /value=-random- /title=1
Line 5,261 ⟶ 6,517:
printline you could have done it by doing -c-
stoptask
goto :b</langsyntaxhighlight>
 
{{out}}
Line 5,282 ⟶ 6,538:
rdiv/2 is use instead of //2 to enable the program to solve difficult cases as [3 3 8 8].
 
<langsyntaxhighlight Prologlang="prolog">play24(Len, Range, Goal) :-
game(Len, Range, Goal, L, S),
maplist(my_write, L),
Line 5,372 ⟶ 6,628:
 
my_write(V) :-
format('~w ', [V]).</langsyntaxhighlight>
{{out}}
<pre>?- play24(4,9, 24).
Line 5,429 ⟶ 6,685:
</pre>
===Minimal version===
{{incorrect|Prolog|NoDoes matternot howfollow I24 parsegame it,rules Ifor candivision: see<quote>Division howshould 3*8-2//9use evaluatesfloating point or rational arithmetic, etc, to 24preserve remainders.</quote>}}
{{Works with|GNU Prolog|1.4.4}}
Little efforts to remove dublicatesduplicates (e.g. output for [4,6,9,9]).
<langsyntaxhighlight lang="prolog">:- initialization(main).
 
solve(N,Xs,Ast) :-
Line 5,453 ⟶ 6,709:
 
test(T) :- solve(24, [2,3,8,9], T).
main :- forall(test(T), (write(T), nl)), halt.</langsyntaxhighlight>
{{Output}}
<pre>(9-3)*8//2
Line 5,473 ⟶ 6,729:
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.
<syntaxhighlight lang="python">'''
<lang Python>'''
The 24 Game Player
Line 5,631 ⟶ 6,887:
print ("Thank you and goodbye")
main()</langsyntaxhighlight>
 
{{out}}
Line 5,656 ⟶ 6,912:
Thank you and goodbye</pre>
 
====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.
Line 5,685 ⟶ 6,941:
==={{header|Python}} Succinct===
Based on the Julia example above.
<langsyntaxhighlight lang="python"># -*- coding: utf-8 -*-
import operator
from itertools import product, permutations
Line 5,723 ⟶ 6,979:
[3,3,8,8], # Difficult case requiring precise division
]:
print(f"solve24({nums}) -> {solve24(nums)}")</langsyntaxhighlight>
 
{{out}}
Line 5,740 ⟶ 6,996:
==={{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.
<langsyntaxhighlight lang="python"># -*- coding: utf-8 -*-
# Python 3
from operator import mul, sub, add
Line 5,784 ⟶ 7,040:
except StopIteration:
print("No solution found")
</syntaxhighlight>
</lang>
 
{{out}}
Line 5,799 ⟶ 7,055:
[9, 4, 4, 5] : No solution found</pre>
 
===Python: using tkinter===
 
<syntaxhighlight lang="python">
''' Python 3.6.5 code using Tkinter graphical user interface.
Combination of '24 game' and '24 game/Solve'
allowing user or random selection of 4-digit number
and user or computer solution.
Note that all computer solutions are displayed'''
 
from tkinter import *
from tkinter import messagebox
from tkinter.scrolledtext import ScrolledText
# 'from tkinter import scrolledtext' in later versions?
import random
import itertools
 
# ************************************************
 
class Game:
def __init__(self, gw):
self.window = gw
self.digits = '0000'
 
a1 = "(Enter '4 Digits' & click 'My Digits'"
a2 = "or click 'Random Digits')"
self.msga = a1 + '\n' + a2
 
b1 = "(Enter 'Solution' & click 'Check Solution'"
b2 = "or click 'Show Solutions')"
self.msgb = b1 + '\n' + b2
 
# top frame:
self.top_fr = Frame(gw,
width=600,
height=100,
bg='dodger blue')
self.top_fr.pack(fill=X)
 
self.hdg = Label(self.top_fr,
text=' 24 Game ',
font='arial 22 bold',
fg='navy',
bg='lemon chiffon')
self.hdg.place(relx=0.5, rely=0.5,
anchor=CENTER)
 
self.close_btn = Button(self.top_fr,
text='Quit',
bd=5,
bg='navy',
fg='lemon chiffon',
font='arial 12 bold',
command=self.close_window)
self.close_btn.place(relx=0.07, rely=0.5,
anchor=W)
 
self.clear_btn = Button(self.top_fr,
text='Clear',
bd=5,
bg='navy',
fg='lemon chiffon',
font='arial 12 bold',
command=self.clear_screen)
self.clear_btn.place(relx=0.92, rely=0.5,
anchor=E)
 
# bottom frame:
self.btm_fr = Frame(gw,
width=600,
height=500,
bg='lemon chiffon')
self.btm_fr.pack(fill=X)
self.msg = Label(self.btm_fr,
text=self.msga,
font='arial 16 bold',
fg='navy',
bg='lemon chiffon')
self.msg.place(relx=0.5, rely=0.1,
anchor=CENTER)
 
self.user_dgt_btn = Button(self.btm_fr,
text='My Digits',
width=12,
bd=5,
bg='navy',
fg='lemon chiffon',
font='arial 12 bold',
command=self.get_digits)
self.user_dgt_btn.place(relx=0.07, rely=0.2,
anchor=W)
 
self.rdm_dgt_btn = Button(self.btm_fr,
text='Random Digits',
width=12,
bd=5,
bg='navy',
fg='lemon chiffon',
font='arial 12 bold',
command=self.gen_digits)
self.rdm_dgt_btn.place(relx=0.92, rely=0.2,
anchor=E)
 
self.dgt_fr = LabelFrame(self.btm_fr,
text=' 4 Digits ',
bg='dodger blue',
fg='navy',
bd=4,
relief=RIDGE,
font='arial 12 bold')
self.dgt_fr.place(relx=0.5, rely=0.27,
anchor=CENTER)
 
self.digit_ent = Entry(self.dgt_fr,
justify='center',
font='arial 16 bold',
fg='navy',
disabledforeground='navy',
bg='lemon chiffon',
disabledbackground='lemon chiffon',
bd=4,
width=6)
self.digit_ent.grid(row=0, column=0,
padx=(8,8),
pady=(8,8))
self.chk_soln_btn = Button(self.btm_fr,
text='Check Solution',
state='disabled',
width=14,
bd=5,
bg='navy',
fg='lemon chiffon',
font='arial 12 bold',
command=self.check_soln)
self.chk_soln_btn.place(relx=0.07, rely=.42,
anchor=W)
 
self.show_soln_btn = Button(self.btm_fr,
text='Show Solutions',
state='disabled',
width=14,
bd=5,
bg='navy',
fg='lemon chiffon',
font='arial 12 bold',
command=self.show_soln)
self.show_soln_btn.place(relx=0.92, rely=.42,
anchor=E)
 
self.soln_fr = LabelFrame(self.btm_fr,
text=' Solution ',
bg='dodger blue',
fg='navy',
bd=4,
relief=RIDGE,
font='arial 12 bold')
self.soln_fr.place(relx=0.07, rely=0.58,
anchor=W)
 
self.soln_ent = Entry(self.soln_fr,
justify='center',
font='arial 16 bold',
fg='navy',
disabledforeground='navy',
bg='lemon chiffon',
disabledbackground='lemon chiffon',
state='disabled',
bd=4,
width=15)
self.soln_ent.grid(row=0, column=0,
padx=(8,8), pady=(8,8))
 
self.solns_fr = LabelFrame(self.btm_fr,
text=' Solutions ',
bg='dodger blue',
fg='navy',
bd=4,
relief=RIDGE,
font='arial 12 bold')
self.solns_fr.place(relx=0.92, rely=0.5,
anchor='ne')
 
self.solns_all = ScrolledText(self.solns_fr,
font='courier 14 bold',
state='disabled',
fg='navy',
bg='lemon chiffon',
height=8,
width=14)
self.solns_all.grid(row=0, column=0,
padx=(8,8), pady=(8,8))
 
# validate '4 Digits' entry.
# save if valid and switch screen to solution mode.
def get_digits(self):
txt = self.digit_ent.get()
if not(len(txt) == 4 and txt.isdigit()):
self.err_msg('Please enter 4 digits (eg 1357)')
return
self.digits = txt # save
self.reset_one() # to solution mode
return
 
# generate 4 random digits, display them,
# save them, and switch screen to solution mode.
def gen_digits(self):
self.digit_ent.delete(0, 'end')
self.digits = ''.join([random.choice('123456789')
for i in range(4)])
self.digit_ent.insert(0, self.digits) # display
self.reset_one() # to solution mode
return
 
# switch screen from get digits to solution mode:
def reset_one(self):
self.digit_ent.config(state='disabled')
self.user_dgt_btn.config(state='disabled')
self.rdm_dgt_btn.config(state='disabled')
self.msg.config(text=self.msgb)
self.chk_soln_btn.config(state='normal')
self.show_soln_btn.config(state='normal')
self.soln_ent.config(state='normal')
return
 
# edit user's solution:
def check_soln(self):
txt = self.soln_ent.get() # user's expression
d = '' # save digits in expression
dgt_op = 'd' # expecting d:digit or o:operation
for t in txt:
if t not in '123456789+-*/() ':
self.err_msg('Invalid character found: ' + t)
return
if t.isdigit():
if dgt_op == 'd':
d += t
dgt_op = 'o'
else:
self.err_msg('Need operator between digits')
return
if t in '+-*/':
if dgt_op == 'o':
dgt_op = 'd'
else:
self.err_msg('Need digit befor operator')
return
if sorted(d) != sorted(self.digits):
self.err_msg("Use each digit in '4 Digits' once")
return
try:
# round covers up Python's
# representation of floats
if round(eval(txt),5) == 24:
messagebox.showinfo(
'Success',
'YOUR SOLUTION IS VADLID!')
self.show_soln() # show all solutions
return
except:
self.err_msg('Invalid arithmetic expression')
return
messagebox.showinfo(
'Failure',
'Your expression does not yield 24')
return
 
# show all solutions:
def show_soln(self):
# get all sets of 3 operands: ('+', '+', '*'), ...)
ops = ['+-*/', '+-*/', '+-*/']
combs = [p for p in itertools.product(*ops)]
# get unique permutations for requested 4 digits:
d = self.digits
perms = set([''.join(p) for p in itertools.permutations(d)])
 
# list of all (hopefully) expressions for
# 4 operands and 3 operations:
formats = ['Aop1Bop2Cop3D',
'(Aop1Bop2C)op3D',
'((Aop1B)op2C)op3D',
'(Aop1(Bop2C))op3D',
'Aop1Bop2(Cop3D)',
'Aop1(Bop2C)op3D',
'(Aop1B)op2Cop3D',
'(Aop1B)op2(Cop3D)',
'Aop1(Bop2Cop3D)',
'Aop1((Bop2C)op3D)',
'Aop1(Bop2(Cop3D))']
 
lox = [] # list of valid expressions
for fm in formats: # pick a format
for c in combs: # plug in 3 ops
f = fm.replace('op1', c[0])
f = f.replace('op2', c[1])
f = f.replace('op3', c[2])
for A, B, C, D in perms: # plug in 4 digits
x = f.replace('A', A)
x = x.replace('B', B)
x = x.replace('C', C)
x = x.replace('D', D)
try: # evaluate expression
# round covers up Python's
# representation of floats
if round(eval(x),5) == 24:
lox.append(' ' + x)
except ZeroDivisionError: # can ignore these
continue
if lox:
txt = '\n'.join(x for x in lox)
else:
txt =' No Solution'
self.solns_all.config(state='normal')
self.solns_all.insert('end', txt) # show solutions
self.solns_all.config(state='disabled')
 
self.chk_soln_btn.config(state='disabled')
self.show_soln_btn.config(state='disabled')
self.soln_ent.config(state='disabled')
return
 
def err_msg(self, msg):
messagebox.showerror('Error Message', msg)
return
 
# restore screen to it's 'initial' state:
def clear_screen(self):
self.digits = ''
self.digit_ent.config(state='normal')
self.user_dgt_btn.config(state='normal')
self.rdm_dgt_btn.config(state='normal')
self.digit_ent.delete(0, 'end')
self.chk_soln_btn.config(state='disabled')
self.show_soln_btn.config(state='disabled')
self.soln_ent.config(state='normal')
self.soln_ent.delete(0, 'end')
self.soln_ent.config(state='disabled')
self.msg.config(text=self.msga)
self.clear_solns_all()
return
 
# clear the 'Solutions' frame.
# note: state must be 'normal' to change data
def clear_solns_all(self):
self.solns_all.config(state='normal')
self.solns_all.delete(1.0, 'end')
self.solns_all.config(state='disabled')
return
def close_window(self):
self.window.destroy()
 
# ************************************************
 
root = Tk()
root.title('24 Game')
root.geometry('600x600+100+50')
root.resizable(False, False)
g = Game(root)
root.mainloop()
</syntaxhighlight>
 
=={{header|Quackery}}==
 
<code>permutations</code> is defined at [[Permutations#Quackery]] and <code>uniquewith</code> is defined at [[Remove duplicate elements#Quackery]].
 
<syntaxhighlight lang="quackery"> [ ' [ 0 1 2 3 ]
permutations ] constant is numorders ( --> [ )
 
[ []
4 3 ** times
[ [] i^
3 times
[ 4 /mod 4 +
rot join swap ]
drop
nested join ] ] constant is oporders ( --> [ )
 
[ [] numorders witheach
[ oporders witheach
[ dip dup join nested
rot swap join swap ]
drop ] ] constant is allorders ( --> [ )
 
[ [] unrot witheach
[ dip dup peek
swap dip [ nested join ] ]
drop ] is reorder ( [ [ --> [ )
 
[ ' [ [ 0 1 4 2 5 3 6 ]
[ 0 1 4 2 3 5 6 ]
[ 0 1 2 4 3 5 6 ] ]
witheach
[ dip dup reorder swap ]
4 pack ] is orderings ( [ --> [ )
 
[ witheach
[ dup number? iff n->v done
dup ' + = iff
[ drop v+ ] done
dup ' - = iff
[ drop v- ] done
' * = iff v* done
v/ ]
24 n->v v- v0= ] is 24= ( [ --> b )
 
[ 4 pack sort
[] swap
' [ + - * / ] join
allorders witheach
[ dip dup reorder orderings
witheach
[ dup 24= iff
[ rot swap
nested join swap ]
else drop ] ]
drop
uniquewith
[ dip unbuild unbuild $> ]
dup size
dup 0 = iff
[ 2drop say "No solutions." ]
done
dup 1 = iff
[ drop say "1 solution." ]
else
[ echo say " solutions." ]
unbuild
2 split nip
-2 split drop nest$ 90 wrap$ ] is solve ( n n n n --> )</syntaxhighlight>
 
{{out}}
 
As a dialogue in the Quackery shell.
 
<pre>/O> 8 8 3 3 solve
...
1 solution.
[ 8 3 8 3 / - / ]
Stack empty.
 
/O> 7 7 9 4 solve
...
No solutions.
Stack empty.
 
/O> 8 7 6 5 solve
...
22 solutions.
[ 5 7 + 8 6 - * ] [ 5 7 + 8 - 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 8 5 - - * ] [ 6 7 8 - 5 + * ] [ 6 8 7 5 - / * ] [ 6 8 * 7 5 - / ] [ 7 5 + 8 6 - * ]
[ 7 5 + 8 - 6 * ] [ 7 8 - 5 + 6 * ] [ 8 6 7 5 - / * ] [ 8 6 - 5 7 + * ] [ 8 6 - 7 5 + * ]
[ 8 6 * 7 5 - / ] [ 8 7 5 - 6 / / ]
Stack empty.
</pre>
 
=={{header|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.
<syntaxhighlight lang="r">
<lang r>
library(gtools)
 
Line 5,837 ⟶ 7,551:
return(NA)
}
</syntaxhighlight>
</lang>
{{out}}
<syntaxhighlight lang="r">
<lang r>
> solve24()
8 * (4 - 2 + 1)
Line 5,852 ⟶ 7,566:
> solve24(ops=c('-', '/')) #restricted set of operators
(8 - 2)/(1/4)
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
The sequence of all possible variants of expressions with given numbers ''n1, n2, n3, n4'' and operations ''o1, o2, o3''.
<langsyntaxhighlight lang="racket">
(define (in-variants n1 o1 n2 o2 n3 o3 n4)
(let ([o1n (object-name o1)]
Line 5,873 ⟶ 7,587:
`(,n1 ,o1n ((,n2 ,o3n ,n3) ,o2n ,n4))
`(,n1 ,o1n (,n2 ,o2n (,n3 ,o3n ,n4))))))))
</syntaxhighlight>
</lang>
 
Search for all solutions using brute force:
<langsyntaxhighlight lang="racket">
(define (find-solutions numbers (goal 24))
(define in-operations (list + - * /))
Line 5,892 ⟶ 7,606:
 
(define (remove-from numbers . n) (foldr remq numbers n))
</syntaxhighlight>
</lang>
 
Examples:
Line 5,914 ⟶ 7,628:
 
In order to find just one solution effectively one needs to change <tt>for*/list</tt> to <tt>for*/first</tt> in the function <tt>find-solutions</tt>.
 
=={{header|Raku}}==
(formerly 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 Raku 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"<sup>&trade;</sup>
 
<syntaxhighlight lang="raku" line>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
@digits.permutations».join.unique».comb.race.map: -> @p {
for @ops -> @o {
for @formats -> $format {
my $result = .EVAL given my $string = sprintf $format, roundrobin(@p, @o, :slip);
say "$string = 24" and last if $result and $result == 24;
}
}
}</syntaxhighlight>
{{out}}
<pre>
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
</pre>
 
===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.
 
<syntaxhighlight lang="raku" line>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
========================================================================
}</syntaxhighlight>
{{out}}
When supplied 1399 on the command line:
<pre>(((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</pre>
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program helps the user find solutions to the game of 24. */
/* start-of-help
┌───────────────────────────────────────────────────────────────────────┐
Line 6,131 ⟶ 8,042:
x.e= 1 /*mark this expression as being used. */
end
interpret 'x=(' e ") / 1" /*have REXX do the heavy lifting here. */
if x\==?? then do /*Not correct? Then try again. */
numeric digits 9; x= x / 1 /*re-do evaluation.*/
numeric digits 12 /*re-instate digits*/
if x\==?? then iterate /*Not correct? Then try again. */
end
finds= finds + 1 /*bump number of found solutions. */
if \show | negatory then return finds
Line 6,178 ⟶ 8,089:
ger: say= '***error*** for argument:' y; say arg(1); errCode= 1; return 0
p: return word( arg(1), 1)
s: if arg(1)==1 then return arg(3); return word( arg(2) 's', 1)</langsyntaxhighlight>
Some older REXXes don't have a &nbsp; '''changestr''' &nbsp; BIF, so one is included here ──► &nbsp; &nbsp; [[CHANGESTR.REX]].
<br><br>
Line 6,291 ⟶ 8,202:
{{trans|Tcl}}
{{works with|Ruby|2.1}}
<langsyntaxhighlight lang="ruby">class TwentyFourGame
EXPRESSIONS = [
'((%dr %s %dr) %s %dr) %s %dr',
Line 6,331 ⟶ 8,242:
puts "found #{solutions.size} solutions, including #{solutions.first}"
puts solutions.sort
end</langsyntaxhighlight>
 
{{out}}
Line 6,365 ⟶ 8,276:
=={{header|Rust}}==
{{works with|Rust|1.17}}
<langsyntaxhighlight lang="rust">#[derive(Clone, Copy, Debug)]
enum Operator {
Sub,
Line 6,530 ⟶ 8,441:
[numbers[order[0]], numbers[order[1]], numbers[order[2]], numbers[order[3]]]
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 6,544 ⟶ 8,455:
A non-interactive player.
 
<langsyntaxhighlight lang="scala">def permute(l: List[Double]): List[List[Double]] = l match {
case Nil => List(Nil)
case x :: xs =>
Line 6,568 ⟶ 8,479:
}
 
def hasSolution(l: List[Double]) = permute(l) flatMap computeAllOperations filter (_._1 == 24) map (_._2)</langsyntaxhighlight>
 
Example:
Line 6,602 ⟶ 8,513:
This version outputs an S-expression that will '''eval''' to 24 (rather than converting to infix notation).
 
<langsyntaxhighlight lang="scheme">
#!r6rs
 
Line 6,649 ⟶ 8,560:
(filter evaluates-to-24
(map* tree (iota 6) ops ops ops perms))))
</syntaxhighlight>
</lang>
 
Example output:
<langsyntaxhighlight lang="scheme">
> (solve 1 3 5 7)
((* (+ 1 5) (- 7 3))
Line 6,666 ⟶ 8,577:
> (solve 3 4 9 10)
()
</syntaxhighlight>
</lang>
 
=={{header|Sidef}}==
Line 6,672 ⟶ 8,583:
'''With eval():'''
 
<langsyntaxhighlight lang="ruby">var formats = [
'((%d %s %d) %s %d) %s %d',
'(%d %s (%d %s %d)) %s %d',
Line 6,704 ⟶ 8,615:
}
}
}</langsyntaxhighlight>
 
'''Without eval():'''
<langsyntaxhighlight lang="ruby">var formats = [
{|a,b,c|
Hash(
Line 6,764 ⟶ 8,675:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 6,781 ⟶ 8,692:
 
=={{header|Simula}}==
<langsyntaxhighlight lang="simula">BEGIN
 
 
Line 7,078 ⟶ 8,989:
OUTIMAGE;
END.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 7,097 ⟶ 9,008:
=={{header|Swift}}==
 
<langsyntaxhighlight lang="swift">
import Darwin
import Foundation
Line 7,269 ⟶ 9,180:
} else {
println("Congratulations, you found a solution!")
}</langsyntaxhighlight>
 
{{out}}The program in action:
Line 7,316 ⟶ 9,227:
This is a complete Tcl script, intended to be invoked from the command line.
{{tcllib|struct::list}}
<langsyntaxhighlight lang="tcl">package require struct::list
# Encoding the various expression trees that are possible
set patterns {
Line 7,377 ⟶ 9,288:
}
}
print24GameSolutionFor $argv</langsyntaxhighlight>
{{out}}
Demonstrating it in use:
Line 7,398 ⟶ 9,309:
non-terminal nodes of a tree in every possible way. The <code>value</code> function evaluates a tree and the
<code>format</code> function displays it in a readable form.
<langsyntaxhighlight Ursalalang="ursala">#import std
#import nat
#import rat
Line 7,408 ⟶ 9,319:
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"</langsyntaxhighlight>
test program:
<langsyntaxhighlight Ursalalang="ursala">#show+
 
test_games = mat` * pad` *K7 pad0 game24* <<2,3,8,9>,<5,7,4,1>,<5,6,7,8>></langsyntaxhighlight>
output:
<pre>
Line 7,443 ⟶ 9,354:
((7-8)+5)*6
((5-8)+7)*6
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-dynamic}}
<syntaxhighlight lang="wren">import "random" for Random
import "./dynamic" for Tuple, Enum, Struct
 
var N_CARDS = 4
var SOLVE_GOAL = 24
var MAX_DIGIT = 9
 
var Frac = Tuple.create("Frac", ["num", "den"])
 
var OpType = Enum.create("OpType", ["NUM", "ADD", "SUB", "MUL", "DIV"])
 
var Expr = Struct.create("Expr", ["op", "left", "right", "value"])
 
var showExpr // recursive function
showExpr = Fn.new { |e, prec, isRight|
if (!e) return
if (e.op == OpType.NUM) {
System.write(e.value)
return
}
var op = (e.op == OpType.ADD) ? " + " :
(e.op == OpType.SUB) ? " - " :
(e.op == OpType.MUL) ? " x " :
(e.op == OpType.DIV) ? " / " : e.op
if ((e.op == prec && isRight) || e.op < prec) System.write("(")
showExpr.call(e.left, e.op, false)
System.write(op)
showExpr.call(e.right, e.op, true)
if ((e.op == prec && isRight) || e.op < prec) System.write(")")
}
 
var evalExpr // recursive function
evalExpr = Fn.new { |e|
if (!e) return Frac.new(0, 1)
if (e.op == OpType.NUM) return Frac.new(e.value, 1)
var l = evalExpr.call(e.left)
var r = evalExpr.call(e.right)
var res = (e.op == OpType.ADD) ? Frac.new(l.num * r.den + l.den * r.num, l.den * r.den) :
(e.op == OpType.SUB) ? Frac.new(l.num * r.den - l.den * r.num, l.den * r.den) :
(e.op == OpType.MUL) ? Frac.new(l.num * r.num, l.den * r.den) :
(e.op == OpType.DIV) ? Frac.new(l.num * r.den, l.den * r.num) :
Fiber.abort("Unknown op: %(e.op)")
return res
}
 
var solve // recursive function
solve = Fn.new { |ea, len|
if (len == 1) {
var final = evalExpr.call(ea[0])
if (final.num == final.den * SOLVE_GOAL && final.den != 0) {
showExpr.call(ea[0], OpType.NUM, false)
return true
}
}
var ex = List.filled(N_CARDS, null)
for (i in 0...len - 1) {
for (j in i + 1...len) ex[j - 1] = ea[j]
var node = Expr.new(OpType.NUM, null, null, 0)
ex[i] = node
for (j in i + 1...len) {
node.left = ea[i]
node.right = ea[j]
for (k in OpType.startsFrom+1...OpType.members.count) {
node.op = k
if (solve.call(ex, len - 1)) return true
}
node.left = ea[j]
node.right = ea[i]
node.op = OpType.SUB
if (solve.call(ex, len - 1)) return true
node.op = OpType.DIV
if (solve.call(ex, len - 1)) return true
ex[j] = ea[j]
}
ex[i] = ea[i]
}
return false
}
 
var solve24 = Fn.new { |n|
var l = List.filled(N_CARDS, null)
for (i in 0...N_CARDS) l[i] = Expr.new(OpType.NUM, null, null, n[i])
return solve.call(l, N_CARDS)
}
 
var r = Random.new()
var n = List.filled(N_CARDS, 0)
for (j in 0..9) {
for (i in 0...N_CARDS) {
n[i] = 1 + r.int(MAX_DIGIT)
System.write(" %(n[i])")
}
System.write(": ")
System.print(solve24.call(n) ? "" : "No solution")
}</syntaxhighlight>
 
{{out}}
Sample run:
<pre>
5 4 2 6: (5 + 4) x 2 + 6
5 3 2 9: (5 - 2) x 9 - 3
4 8 4 3: ((4 + 8) - 4) x 3
3 8 4 7: 8 - (3 - 7) x 4
7 9 9 2: No solution
1 6 5 5: (1 + 5) x 5 - 6
3 2 7 8: (8 - (3 - 7)) x 2
2 2 8 8: (2 + 2) x 8 - 8
6 4 2 5: (6 - 2) x 5 + 4
9 2 1 6: 9 x 2 x 1 + 6
</pre>
 
=={{header|Yabasic}}==
<langsyntaxhighlight Yabasiclang="yabasic">operators$ = "*+-/"
space$ = " "
 
Line 7,624 ⟶ 9,649:
next n
return true
end sub</langsyntaxhighlight>
 
=={{header|zkl}}==
Line 7,630 ⟶ 9,655:
 
File solve24.zkl:
<langsyntaxhighlight lang="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());
Line 7,655 ⟶ 9,680:
catch(MathError){ False } };
{ f2s(digits4,ops3,f) }]];
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">solutions:=u(game24Solver(ask(0,"digits: ")));
println(solutions.len()," solutions:");
solutions.apply2(Console.println);</langsyntaxhighlight>
One trick used is to look at the solving functions name and use the digit in it to index into the formats list.
{{out}}
Line 7,683 ⟶ 9,708:
...
</pre>
 
[[Category:Puzzles]]
 
{{omit from|GUISS}}
{{omit from|ML/I}}
 
[[Category:Puzzles]]
9,476

edits