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.


 
\ Generate four random digits and display to the user
\ then get an expression from the user using +, -, / and * and the digits
\ the result must equal 24
\ http://8th-dev.com/24game.html
 
\ Only the words in namespace 'game' are available to the player:
ns: game
 
: + n:+ ;
: - n:- ;
: * n:* ;
: / n:/ ;
 
ns: G
 
var random-digits
var user-input
 
: one-digit \ a -- a
	rand n:abs 9 n:mod n:1+ a:push ;
 
: gen-digits \ - a
	[] clone nip \ the clone nip is not needed in versions past 1.0.2...
	' one-digit 4 times
	' n:cmp a:sort
	random-digits !  ;
 
: prompt-user 
	cr "The digits are: " .  random-digits @ . cr ;
 
: goodbye
	cr "Thanks for playing!\n" . cr 0 die ;
 
: get-input
	70 null con:accept dup user-input !
	null? if drop goodbye then ;
 
: compare-digits
	true swap
	(
		\ inputed-array index
		dup >r
		a:@ 
		random-digits @ r> a:@ nip
		n:= not if
			break
			swap drop false swap
		then
	) 0 3 loop drop ;
 
/^\D*(\d)\D+(\d)\D+(\d)\D+(\d)\D*$/  var, digits-regex
 
: all-digits? 
	user-input @ digits-regex @ r:match 
	null? if drop false else
		5 = not if
			false
		else
			\ convert the captured digits in the regex into a sorted array:
			digits-regex @ 
			( r:@ >n swap ) 1 4 loop drop
			4 a:close ' n:cmp a:sort
			compare-digits
		then
	then ;
 
: does-eval?
	0 user-input @ eval 24 n:= 
	dup not if
		cr "Sorry, that expression is wrong" . cr
	then ;
 
: check-input
	reset
	all-digits?  if 
		does-eval? if
			cr "Excellent!  Your expression: \"" .
			user-input @ .
			"\" worked!" . cr
		then
	else
		cr "You did not use the digits properly, try again." . cr
	then ;
 
: intro quote |
 
Welcome to the '24 game'!
 
You will be shown four digits each time.  Using only the + - * and / operators
and all the digits (and only the digits), produce the number '24'
 
Enter your result in 8th syntax, e.g.:  4 4 + 2 1 + *
 
To quit the game, just hit enter by itself. Enjoy!
 
	| . ;
 
: start
	\ don't allow anything but the desired words
	ns:game only
	intro
	repeat
		gen-digits
		prompt-user
		get-input
		check-input
	again ;
 
start
 