The 24 Game tests one's mental arithmetic.



Task
Write a program that randomly chooses and displays four digits, each from 1 ──► 9 (inclusive) with repetitions allowed.

The program should prompt for the player to enter an arithmetic expression using just those, and all of those four digits, used exactly once each. The program should check then evaluate the expression.

The goal is for the player to enter an expression that (numerically) evaluates to 24.

 Only the following operators/functions are allowed: multiplication, division, addition, subtraction
 Division should use floating point or rational arithmetic, etc, to preserve remainders.
 Brackets are allowed, if using an infix expression evaluator.
 Forming multiple digit numbers from the supplied digits is disallowed. (So an answer of 12+12 when given 1, 2, 2, and 1 is wrong).
 The order of the digits when given does not have to be preserved.


Notes
 The type of expression evaluator used is not mandated. An RPN evaluator is equally acceptable for example.
 The task is not for the program to generate the expression, or test whether an expression is even possible.


Related tasks
 24 game/Solve


Reference
 The 24 Game on h2g2.


operadores$ = "*/+-"
espacios$ = "                                                                                "
 
clear screen
print "24 Game"
print "============\n"
print "The player is provided with 4 numbers with which to perform operations"
print "of addition (+), subtraction (-), multiplication (*) or division (/) to attempt"
print "to get 24 as result."
print "Use reverse Polish notation (first the operands and then the operators)."
print "For example: instead of 2 + 4, type 2 4 +\n\n"
 
repeat
	print at(0,9) espacios$, espacios$, espacios$, espacios$, espacios$, espacios$
	print at(0,9);
	serie$ = ordenaCadena$(genSerie$())
	validos$ = serie$+operadores$
	line input "Enter your formula in reverse Polish notation: " entrada$
	entrada$ = quitaEspacios$(entrada$)
	entradaOrd$ = ordenaCadena$(entrada$)
	if (right$(entradaOrd$,4) <> serie$) or (len(entradaOrd$)<>7) then
		print "Error in the entered series"
	else
		resultado = evaluaEntrada(entrada$)
		print "The result is = ",resultado," "
		if resultado = 24 then
			print "Correct!"
		else
			print "Error!"
		end if
	end if
	print "Want to try again? (press N to exit, or another key to continue)"
until(upper$(left$(inkey$(),1)) = "N")
 
sub genSerie$()
	local i, c$, s$
 
	print "The numbers to be used are: ";
	i = ran()
	for i = 1 to 4
		c$ = str$(int(ran(9))+1)
		print c$," ";
		s$ = s$ + c$
	next i
	print
	return s$
end sub
 
 
sub evaluaEntrada(entr$)
	local d1, d2, c$, n(4), i
 
	while(entr$<>"")
		c$ = left$(entr$,1)
		entr$ = mid$(entr$,2)		
		if instr(serie$,c$) then
			i = i + 1
			n(i) = val(c$)
		elseif instr(operadores$,c$) then
			d2 = n(i)
			n(i) = 0
			i = i - 1
			d1 = n(i)
			n(i) = evaluador(d1, d2, c$)
		else
			print "Invalid sign"
			return
		end if
	wend
 
	return n(i)
 
end sub
 
 
sub evaluador(d1, d2, op$)
	local t
 
	switch op$
		case "+": t = d1 + d2 : break
		case "-": t = d1 - d2 : break
		case "*": t = d1 * d2 : break
		case "/": t = d1 / d2 : break
	end switch
 
	return t
end sub
 
 
sub quitaEspacios$(entr$)
	local n, i, s$, t$(1)
 
	n = token(entr$,t$()," ")
 
	for i=1 to n
		s$ = s$ + t$(i)
	next i
	return s$
end sub
 
 
sub ordenaCadena$(cadena$)
	local testigo, n, fin, c$
 
	fin = len(cadena$)-1
	repeat
		testigo = false
		for n = 1 to fin
			if mid$(cadena$,n,1) > mid$(cadena$,n+1,1) then
				testigo = true
				c$ = mid$(cadena$,n,1)
				mid$(cadena$,n,1) = mid$(cadena$,n+1,1)
				mid$(cadena$,n+1,1) = c$
			end if
		next n
	until(testigo = false)
	return cadena$
end sub