24 game: Difference between revisions
→{{header|FutureBasic}}
(36 intermediate revisions by 17 users not shown) | |||
Line 36:
{{trans|C++}}
<
String message
F (message)
Line 47:
F op(f)
I .stk.len < 2
X.throw Error(‘Improperly written expression’)
V b = .stk.pop()
V a = .stk.pop()
Line 62:
E I c == ‘/’ {.op((a, b) -> a / b)}
E I c != ‘ ’
X.throw Error(‘Wrong char: ’c)
F get_result()
I .stk.len != 1
X.throw Error(‘Improperly written expression’)
R .stk.last
Line 94:
X.catch Error error
print(‘Error: ’error.message)</
{{out}}
Line 101:
=={{header|8th}}==
This is a fully-worked sample of the game in 8th, showing error-detection and user-restriction techniques:
<
\ Generate four random digits and display to the user
\ then get an expression from the user using +, -, / and * and the digits
Line 211:
start
</syntaxhighlight>
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits}}
<
/* ARM assembly AARCH64 Raspberry PI 3B */
/* program game24_64.s */
Line 701:
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
=={{header|ABAP}}==
See [[24 game/ABAP]]
Line 707:
=={{header|Ada}}==
game24.adb:
<
with Ada.Text_IO;
with Ada.Numerics.Discrete_Random;
Line 878:
end if;
end;
end Game_24;</
{{out}}
Line 897:
You won!
Enter N for a new game, or try another solution.</pre>
=={{header|ALGOL 68}}==
Uses infix expressions.
<syntaxhighlight lang="algol68">
BEGIN # play the 24 game - present the user with 4 digits and invite them to #
# enter an expression using the digits that evaluates to 24 #
[ 0 : 9 ]INT expression digits; # the digits entered by the user #
[ 0 : 9 ]INT puzzle digits; # the digits for the puzzle #
PROC eval = ( STRING expr )REAL: # parses and evaluates expr #
BEGIN
# syntax: expression = term ( ( "+" | "-" ) term )* #
# term = factor ( ( "*" | "/" ) factor ) * #
# factor = "0" | "1" | "2" | ... | "9" #
# | "(" expression ")" #
INT x pos := LWB expr - 1;
INT x end := UPB expr;
BOOL ok := TRUE;
PROC error = ( STRING msg )VOID:
IF ok THEN # this is the firstt error #
ok := FALSE;
print( ( msg, newline ) );
x pos := x end + 1
FI # error # ;
PROC curr ch = CHAR: IF x pos > x end THEN REPR 0 ELSE expr[ x pos ] FI;
PROC next ch = VOID: WHILE x pos +:= 1; curr ch = " " DO SKIP OD;
PROC factor = REAL:
IF curr ch >= "0" AND curr ch <= "9" THEN
INT digit = ABS curr ch - ABS "0";
REAL result = digit;
expression digits[ digit ] +:= 1;
next ch;
result
ELIF curr ch = "(" THEN
next ch;
REAL result = expression;
IF curr ch = ")" THEN
next ch
ELSE
error( """)"" expected after sub-expression" )
FI;
result
ELSE
error( "Unexpected """ + curr ch + """" );
0
FI # factor # ;
PROC term = REAL:
BEGIN
REAL result := factor;
WHILE curr ch = "*" OR curr ch = "/" DO
CHAR op = curr ch;
next ch;
IF op = "*" THEN result *:= factor ELSE result /:= factor FI
OD;
result
END # term # ;
PROC expression = REAL:
BEGIN
REAL result := term;
WHILE curr ch = "+" OR curr ch = "-" DO
CHAR op = curr ch;
next ch;
IF op = "+" THEN result +:= term ELSE result -:= term FI
OD;
result
END # expression # ;
next ch;
IF curr ch = REPR 0 THEN
error( "Missing expression" );
0
ELSE
REAL result = expression;
IF curr ch /= REPR 0 THEN
error( "Unexpected text: """ + expr[ x pos : ] + """ after expression" )
FI;
result
FI
END # eval # ;
WHILE
FOR i FROM 0 TO 9 DO # initialise the digit counts #
expression digits[ i ] := 0;
puzzle digits[ i ] := 0
OD;
print( ( "Enter an expression using these digits:" ) );
FOR i TO 4 DO # pick 4 random digits #
INT digit := 1 + ENTIER ( next random * 9 );
IF digit > 9 THEN digit := 9 FI;
puzzle digits[ digit ] +:= 1;
print( ( whole( digit, - 2 ) ) )
OD;
print( ( " that evaluates to 24: " ) );
# get and check the expression #
STRING expr;
read( ( expr, newline ) );
REAL result = eval( expr );
BOOL same := TRUE;
FOR i FROM 0 TO 9 WHILE same := puzzle digits[ i ] = expression digits[ i ] DO SKIP OD;
IF NOT same THEN
print( ( "That expression didn't contain the puzzle digits", newline ) )
ELIF result = 24 THEN
print( ( "Yes! That expression evaluates to 24", newline ) )
ELSE
print( ( "No - that expression evaluates to ", fixed( result, -8, 4 ), newline ) )
FI;
print( ( newline, "Play again [y/n]? " ) );
STRING play again;
read( ( play again, newline ) );
play again = "y" OR play again = "Y" OR play again = ""
DO SKIP OD
END
</syntaxhighlight>
{{out}}
<pre>
Enter an expression using these digits: 2 5 3 5 that evaluates to 24: (3+5)*(5-2)
Yes! That expression evaluates to 24
Play again [y/n]?
Enter an expression using these digits: 8 8 6 6 that evaluates to 24: 8+6+8/6
No - that expression evaluates to 15.3333
Play again [y/n]?
Enter an expression using these digits: 2 1 5 1 that evaluates to 24: (1+1)*(7+5)
That expression didn't contain the puzzle digits
Play again [y/n]? n
</pre>
=={{header|APL}}==
{{works with|Dyalog APL}}
<
⎕←d←?⍵⍴9
i←⍞
Line 907 ⟶ 1,036:
24≠⍎i:'nope'
'Yeah!'
}</
{{out}}
<pre> tfgame 4
Line 919 ⟶ 1,048:
nope
</pre>
=={{header|Applesoft BASIC}}==
This was taken from both the [[#Commodore_BASIC|Commodore BASIC]] and [[#ZX_Spectrum_Basic|ZX Spectrum Basic]] solutions.
<syntaxhighlight lang=ApplesoftBasic> 0 BH = PEEK (104):BL = PEEK (103)
1 GOSUB 1200: CALL - 868
10 LET N$ = ""
20 R = RND ( - ( PEEK (78) + PEEK (79) * 256)): REM RANDOMIZE
30 FOR I = 1 TO 4
40 LET N$ = N$ + STR$ ( INT ( RND (1) * 9) + 1)
50 NEXT I
60 PRINT " PRESS A KEY TO CONTINUE. ";: GET A$
65 LET I$ = "": LET F$ = "": LET P$ = ""
70 HOME
80 PRINT M$M$ SPC( 16)"24 GAME"
90 PRINT M$"ALLOWED CHARACTERS:"M$
100 LET I$ = N$ + "+-*/()"
110 HTAB 20
120 FOR I = 1 TO 10
130 PRINT MID$ (I$,I,1)" ";
140 NEXT I
150 PRINT M$ TAB( 7)"0 TO END"M$
160 INPUT "ENTER THE FORMULA: ";F$
170 IF F$ = "0" THEN END : GOTO 65
180 PRINT M$ TAB( 7)F$" = ";
190 FOR I = 1 TO LEN (F$)
200 LET C$ = MID$ (F$,I,1)
210 IF C$ = " " THEN LET F$ = MID$ (F$,1,I - 1) + MID$ (F$,I + 1): GOTO 250
220 IF C$ = "+" OR C$ = "-" OR C$ = "*" OR C$ = "/" THEN LET P$ = P$ + "O": GOTO 250
230 IF C$ = "(" OR C$ = ")" THEN LET P$ = P$ + C$: GOTO 250
240 LET P$ = P$ + "N"
250 NEXT I
260 RESTORE
270 FOR I = 1 TO 11
280 READ T$
290 IF T$ = P$ THEN LET I = 11
300 NEXT I
310 IF T$ < > P$ THEN INVERSE : PRINT "BAD CONSTRUCTION!"G$M$: NORMAL : GOTO 60
320 FOR I = 1 TO LEN (F$)
330 FOR J = 1 TO 10
340 IF ( MID$ (F$,I,1) = MID$ (I$,J,1)) AND MID$ (F$,I,1) > "0" AND MID$ (F$,I,1) < = "9" THEN LET I$ = MID$ (I$,1,J - 1) + " " + MID$ (I$,J + 1, LEN (I$))
350 NEXT J,I
370 IF MID$ (I$,1,4) < > " " THEN INVERSE : PRINT "INVALID ARGUMENTS!"G$M$: NORMAL : GOTO 60
380 GOSUB 600: REM LET R = VAL(F$)
390 PRINT R" ";
400 IF R < > 24 THEN INVERSE : PRINT "WRONG!"G$M$: NORMAL : GOTO 60
410 INVERSE : PRINT "CORRECT!"M$: NORMAL : GOTO 10
420 DATA"NONONON"
430 DATA"(NON)ONON"
440 DATA"NONO(NON)"
450 DATA"NO(NO(NON))"
460 DATA"((NON)ON)ON"
470 DATA"NO(NON)ON"
480 DATA"(NON)O(NON)"
485 DATA"NO((NON)ON)"
490 DATA"(NONON)ON"
495 DATA"(NO(NON))ON"
500 DATA"NO(NONON)"
600 REMGET BASIC TO EVALUATE OUR EXPRESSION
605 A$ = "R=" + F$: GOSUB 1440
610 FOR I = 1 TO LEN (A$)
615 REMSIMPLE TOKEN TRANSLATION
620 B = ASC ( MID$ (A$,I,1))
625 IF (B > 41 AND B < 48) OR B = 61 OR B = 94 THEN B = T(B)
630 POKE (AD + I - 1),B
635 NEXT
640 GOSUB 2000
645 REM GOSUB 1440:REM UNCOMMENT TO CLEAR EVALUATION LINE AFTER USE
650 RETURN
1200 M$ = CHR$ (13)
1210 G$ = CHR$ (7)
1220 HOME
1230 PRINT SPC( 16)"24 GAME"
1240 PRINT M$" THE GOAL OF THIS GAME IS TO FORMULATE"
1250 PRINT M$" AN ARITHMETIC EXPRESSION THAT"
1260 PRINT M$" EVALUATES TO A VALUE OF 24, HOWEVER"
1270 PRINT M$" YOU MAY USE ONLY THE FOUR NUMBERS"
1280 PRINT M$" GIVEN AT RANDOM BY THE COMPUTER AND"
1290 PRINT M$" THE STANDARD ARITHMETIC OPERATIONS OF"
1300 PRINT M$" ADD, SUBTRACT, MULTIPLY, AND DIVIDE."
1310 PRINT M$" EACH DIGIT MUST BE USED BY ITSELF. "
1320 PRINT M$" (E.G. IF GIVEN 1, 2, 3, 4, YOU CANNOT"
1330 PRINT M$" COMBINE 1 AND 2 TO MAKE 12.)"
1340 PRINT M$
1350 PRINT "INITIALIZING...";
1360 HTAB 1
1400 DIM T(94)
1401 T( ASC ("+")) = 200: REM $C8
1402 T( ASC ("-")) = 201: REM $C9
1403 T( ASC ("*")) = 202: REM $CA
1404 T( ASC ("/")) = 203: REM $CB
1405 T( ASC ("=")) = 208: REM $D0
1406 T( ASC ("^")) = 204: REM $CC
1409 REMLOCATE LINE 2005 IN RAM
1410 LH = BH:LL = BL:NH = 0:NL = 0
1415 AD = LH * 256 + LL
1420 LH = PEEK (AD + 1):LL = PEEK (AD)
1425 NL = PEEK (AD + 2):NH = PEEK (AD + 3):N = NH * 256 + NL
1430 IF N < > 2005 THEN GOTO 1415
1435 AD = AD + 4: RETURN
1440 FOR J = AD TO AD + 12: POKE J, ASC (":"): NEXT
1445 RETURN
2000 REMPUT 13 COLONS ON THE NEXT LINE
2005 :::::::::::::
2010 RETURN
</syntaxhighlight>
=={{header|Argile}}==
{{works with|Argile|1.0.0}}
<
do
Line 1,032 ⟶ 1,268:
error "unclosed parenthesis"
return x
</syntaxhighlight>
compile with:
arc 24_game.arg -o 24_game.c && gcc 24_game.c -o 24_game /usr/lib/libargrt.a
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi}}
<
/* ARM assembly Raspberry PI */
/* program game24.s */
Line 1,491 ⟶ 1,727:
/***************************************************/
.include "../affichage.inc"
</syntaxhighlight>
<pre>
24 Game
Line 1,514 ⟶ 1,750:
=={{header|Arturo}}==
<
print " Welcome to 24 Game"
print "-----------------------------"
Line 1,554 ⟶ 1,790:
]
print "Well done!"</
{{out}}
Line 1,584 ⟶ 1,820:
=={{header|AutoHotkey}}==
<
Title := "24 Game"
Gui, -MinimizeBox
Line 1,691 ⟶ 1,927:
FileDelete, %File%
Return, Result
}</
=={{header|AutoIt}}==
<
;AutoIt Script Example
;by Daniel Barnes
Line 1,769 ⟶ 2,005:
endif
EndFunc
</syntaxhighlight>
=={{header|BBC BASIC}}==
<
DIM digits%(4), check%(4)
FOR choice% = 1 TO 4
Line 1,837 ⟶ 2,073:
INPUT '"Play again", answer$
IF LEFT$(answer$,1) = "y" OR LEFT$(answer$,1) = "Y" THEN CLS : RUN
QUIT</
=={{header|Befunge}}==
<
2 2 1234
4 ^1?3^4
Line 1,865 ⟶ 2,101:
| -*84gg01g00<p00*84<v <
>00g:1+00p66*`#^_ "niW">:#,_@
</syntaxhighlight>
The code functions by placing the 4 randomly generated numbers into the points labelled 1,2,3,4. In order to play, press the corresponding label to draw that number onto the stack, then press the corresponding operation (+,-,*,/) to perform it on the stack elements postfix-wise according to the rules of befunge (i.e. pop the values operate and push the answer back to the stack). When you wish to check your answer enter "=" and it will perform the checks to ensure that you haven't performed any illegal operations, that you have used all four numbers and that your final value is 24.
Line 1,882 ⟶ 2,118:
=={{header|Bracmat}}==
<
= m-w m-z 4numbers answer expr numbers
, seed get-random convertBinaryMinusToUnary
Line 1,959 ⟶ 2,195:
)
& 24-game$(13.14)
& ;</
<pre>Enter an expression that evaluates to 24 by combining the following numbers.
You may only use the operators + - * /
Line 2,006 ⟶ 2,242:
=={{header|C}}==
Simple recursive descent parser. It doesn't have a real lexer, because all tokens are single character (digits, operators and parens). Code is a little too long.
<
#include <ctype.h>
#include <stdlib.h>
Line 2,286 ⟶ 2,522:
}
return 0;
}</
{{out}}
<pre>Available digits are: 5 2 3 9. Type an expression and I'll check it for you, or make new numbers.
Line 2,316 ⟶ 2,552:
This uses the C++11 standard to simplify several parts of the code. Input is given in RPN format.
<
#include <iostream>
#include <stack>
Line 2,413 ⟶ 2,649:
}
return 0;
}</
{{out}}
Line 2,430 ⟶ 2,666:
=={{header|Ceylon}}==
Be sure to import ceylon.random in you ceylon.module file.
<
DefaultRandom
}
Line 2,666 ⟶ 2,902:
}
}
}</
=={{header|Clojure}}==
<
(ns rosettacode.24game)
Line 2,697 ⟶ 2,933:
; * checks prefix form, then checks to see that the numbers used
; and the numbers generated by the game are the same.
</syntaxhighlight>
=={{header|COBOL}}==
<
*> This code is dedicated to the public domain
*> This is GNUCobol 2.0
Line 3,543 ⟶ 3,779:
.
end program twentyfour.
</syntaxhighlight>
=={{header|CoffeeScript}}==
{{works with|node.js}}
<
tty.setRawMode true
Line 3,600 ⟶ 3,836:
# begin taking input
process.stdin.resume()
</syntaxhighlight>
=={{header|Commodore BASIC}}==
This solution was taken from the ZX Spectrum example further down, however, BASIC on the Spectrum features slightly different string handling functions. Most importantly, while the <code>val()</code> function on the Spectrum is able to parse complete mathematical expressions within
To get around this, this program utilizes BASIC's ability to parse expressions containing simple math operators, and is in fact technically a self-modifying program. Line 2005 is a line padded with colons which simply allow BASIC to join multiple statements on a single line, otherwise perform no operation. This reserves sufficient space in memory for inserting the user's expression—by overwriting the first several bytes of colons—which can then be evaluated in the normal course of the program's execution. The subroutine at 1400 initializes a simple translation table for exchanging the operators into their proper BASIC tokens. Parenthesis, numerals, and variable names do not need to be translated.
Line 3,614 ⟶ 3,850:
Since Commodore BASIC v2 was the initial target for this program, all other versions of Commodore BASIC are compatible as long as the base memory address for BASIC programs is adjusted. (BASIC tokens maintain compatibility across all versions.) Simply use the appropriate values for <code>bh</code> and <code>bl</code> in lines 11-15.
<
2 rem for rosetta code
10 rem use appropriate basic base address
Line 3,635 ⟶ 3,871:
72 print:print " an arithmetic expression that"
73 print:print " evaluates to a value of 24, however"
74 print:print " you may use only
75 print:print " given at random by the computer and
76 print:print " the standard arithmetic operations of
77 print:print " add, subtract, multiply, and divide.
78 print:print " Each digit must be used by itself.
79 print:print " (e.g. if given 1, 2, 3, 4, you cannot
80 print:print " combine 1 and 2 to make 12.)"
89 gosub 1000
Line 3,749 ⟶ 3,985:
2005 ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
2010 return
</syntaxhighlight>
{{out}}
Line 3,808 ⟶ 4,044:
=={{header|Common Lisp}}==
<
(define-condition bad-equation (error) ())
Line 3,843 ⟶ 4,079:
(if (= 24 (eval (check (prompt)))) (win) (lose))
(error () (format t "Bad equation, try again.~%"))
(choose-digits () (choose)))))))</
'''Verbose Implementation'''
{{works with|clisp|2.47}}
<
(defconstant +ops+ '(* / + -))
Line 3,952 ⟶ 4,188:
(emit "Sorry, the form you entered did not ~
compute.~%~%")))))
initially (prompt initial-digits)))</
Example Usage:
Line 3,983 ⟶ 4,219:
=={{header|D}}==
<
std.typetuple;
Line 4,019 ⟶ 4,255:
writeln("Result: ", stack[0]);
writeln(abs(stack[0] - 24) < 0.001 ? "Good job!" : "Try again.");
}</
Example:
<pre>Make 24 with the digits: [1, 8, 9, 8]
Line 4,025 ⟶ 4,261:
Result: 24
Good job!</pre>
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
Program includes full recursive descent, expression evaluator that can handle any expression the user might eneter.
<syntaxhighlight lang="Delphi">
var ErrorFlag: boolean;
var ErrorStr: string;
function EvaluateExpression(Express: string): double;
{ Recursive descent expression evaluator }
var Atom: char;
var ExpressStr: string;
var ExpressInx: integer;
const Tab_Char = #$09; SP_char = #$20;
procedure HandleError(S: string);
begin
ErrorStr:=S;
ErrorFlag:=True;
Abort;
end;
procedure GetChar;
begin
if ExpressInx > Length(ExpressStr) then
begin
Atom:= ')';
end
else begin
Atom:= ExpressStr[ExpressInx];
Inc(ExpressInx);
end;
end;
procedure SkipWhiteSpace;
{ Skip Tabs And Spaces In Expression }
begin
while (Atom=TAB_Char) or (Atom=SP_char) do GetChar;
end;
procedure SkipSpaces;
{ Get Next Character, Ignoring Any Space Characters }
begin
repeat GetChar until Atom <> SP_CHAR;
end;
function GetDecimal: integer;
{ Read In A Decimal String And Return Its Value }
var S: string;
begin
Result:=0;
S:='';
while True do
begin
if not (Atom in ['0'..'9']) then break;
S:=S+Atom;
GetChar;
end;
if S='' then HandleError('Number Expected')
else Result:=StrToInt(S);
if Result>9 then HandleError('Only Numbers 0..9 allowed')
end;
function Expression: double;
{ Returns The Value Of An Expression }
function Factor: double;
{ Returns The Value Of A Factor }
var NEG: boolean;
begin
Result:=0;
while Atom='+' do SkipSpaces; { Ignore Unary "+" }
NEG:= False;
while Atom ='-' do { Unary "-" }
begin
SkipSpaces;
NEG:= not NEG;
end;
if (Atom>='0') and (Atom<='9') then Result:= GetDecimal { Unsigned Integer }
else case Atom of
'(': begin { Subexpression }
SkipSpaces;
Result:= Expression;
if Atom<>')' then HandleError('Mismatched Parenthesis');
SkipSpaces;
end;
else HandleError('Syntax Error');
end;
{ Numbers May Terminate With A Space Or Tab }
SkipWhiteSpace;
if NEG then Result:=-Result;
end; { Factor }
function Term: double;
{ Returns Factor * Factor, Etc. }
var R: double;
begin
Result:= Factor;
while True do
case Atom of
'*': begin
SkipSpaces;
Result:= Result * Factor;
end;
'/': begin
SkipSpaces;
R:=Factor;
if R=0 then HandleError('Divide By Zero');
Result:= Result / R;
end;
else break;
end;
end;
{ Term }
function AlgebraicExpression: double;
{ Returns Term + Term, Etc. }
begin
Result:= Term;
while True do
case Atom of
'+': begin SkipSpaces; Result:= Result + Term; end;
'-': begin SkipSpaces; Result:= Result - Term; end
else break;
end;
end; { Algexp }
begin { Expression }
SkipWhiteSpace;
Result:= AlgebraicExpression;
end; { Expression }
begin { EvaluateExpression }
ErrorFlag:=False;
ErrorStr:='';
ExpressStr:=Express;
ExpressInx:=1;
try
GetChar;
Result:= Expression;
except end;
end;
function WaitForString(Memo: TMemo; Prompt: string): string;
{Wait for key stroke on TMemo component}
var MW: TMemoWaiter;
var C: char;
var Y: integer;
begin
{Use custom object to wait and capture key strokes}
MW:=TMemoWaiter.Create(Memo);
try
Memo.Lines.Add(Prompt);
Memo.SelStart:=Memo.SelStart-1;
Memo.SetFocus;
Result:=MW.WaitForLine;
finally MW.Free; end;
end;
procedure Play24Game(Memo: TMemo);
{Play the 24 game}
var R: double;
var Nums: array [0..4-1] of char;
var I: integer;
var Express,RS: string;
var RB: boolean;
procedure GenerateNumbers;
{Generate and display four random number 1..9}
var S: string;
var I: integer;
begin
{Generate random numbers}
for I:=0 to High(Nums) do
Nums[I]:=char(Random(9)+$31);
{Display them}
S:='';
for I:=0 to High(Nums) do
S:=S+' '+Nums[I];
Memo.Lines.Add('Your Digits: '+S);
end;
function TestMatchingNums: boolean;
{Make sure numbers entered by user match the target numbers}
var SL1,SL2: TStringList;
var I: integer;
begin
Result:=False;
SL1:=TStringList.Create;
SL2:=TStringList.Create;
try
{Load target numbers into string list}
for I:=0 to High(Nums) do SL1.Add(Nums[I]);
{Load users expression number int string list}
for I:=1 to Length(Express) do
if Express[I] in ['0'..'9'] then SL2.Add(Express[I]);
{There should be the same number }
if SL1.Count<>SL2.Count then exit;
{Sort them to facilitate testing}
SL1.Sort; SL2.Sort;
{Are number identical, if not exit}
for I:=0 to SL1.Count-1 do
if SL1[I]<>SL2[I] then exit;
{Users numbers passed all tests}
Result:=True;
finally
SL2.Free;
SL1.Free;
end;
end;
function TestUserExpression(var S: string): boolean;
{Test expression user entered }
begin
Result:=False;
if not TestMatchingNums then
begin
S:='Numbers Do not Match';
exit;
end;
R:=EvaluateExpression(Express);
S:='Expression Value = '+FloatToStrF(R,ffFixed,18,0)+CRLF;
if ErrorFlag then
begin
S:=S+'Expression Problem: '+ErrorStr;
exit;
end;
if R<>24 then
begin
S:=S+'Expression is incorrect value';
exit;
end;
S:=S+'!!!!!! Winner !!!!!!!';
Result:=True;
end;
begin
Randomize;
Memo.Lines.Add('=========== 24 Game ===========');
GenerateNumbers;
while true do
begin
if Application.Terminated then exit;
Express:=WaitForString(Memo,'Enter expression, Q = quit, N = New numbers: '+CRLF);
if Pos('N',UpperCase(Express))>0 then
begin
GenerateNumbers;
Continue;
end;
if Pos('Q',UpperCase(Express))>0 then exit;
RB:=TestUserExpression(RS);
Memo.Lines.Add(RS);
if not RB then continue;
RS:=WaitForString(Memo,'Play again Y=Yes, N=No'+CRLF);
if Pos('N',UpperCase(RS))>0 then exit;
GenerateNumbers;
end;
end;
</syntaxhighlight>
{{out}}
<pre>
=========== 24 Game ===========
Your Digits: 8 2 5 5
Enter expression, Q = quit, N = New numbers:
n
Your Digits: 3 1 9 3
Enter expression, Q = quit, N = New numbers:
3 * 9 -3
Numbers Do not Match
Enter expression, Q = quit, N = New numbers:
3 * 9 - 3 * 1
Expression Value = 24
!!!!!! Winner !!!!!!!
Play again Y=Yes, N=No
</pre>
=={{header|EchoLisp}}==
<
(string-delimiter "")
;; check that nums are in expr, and only once
Line 4,059 ⟶ 4,614:
(writeln "24-game - Can you combine" nums "to get 24 ❓ (q to exit)")
(input-expr check-24 (string-append (string nums) " -> 24 ❓")))
</syntaxhighlight>
{{out}}
<pre>
Line 4,084 ⟶ 4,639:
=={{header|Elena}}==
ELENA
<
import system'collections;
import system'dynamic;
Line 4,094 ⟶ 4,649:
class ExpressionTree
{
object
constructor(s)
Line 4,100 ⟶ 4,655:
auto level := new Integer(0);
s.forEach::(ch)
{
var node := new DynamicStruct();
ch =>
$43 { node.Level := level + 1; node.Operation :=
$45 { node.Level := level + 1; node.Operation :=
$42 { node.Level := level + 2; node.Operation :=
$47 { node.Level := level + 2; node.Operation :=
$40 { level.append(10); ^ self } // (
$41 { level.reduce(10); ^ self } // )
node.Leaf := ch.toString().toReal();
node.Level := level + 3
};
if (nil ==
{
}
else
{
if (
{
node.Left :=
node.Right :=
}
else
{
}
}
Line 4,146 ⟶ 4,701:
eval(node)
{
if (node.containsProperty(
{
^ node.Leaf
Line 4,162 ⟶ 4,717:
get Value()
<= eval(
readLeaves(list, node)
Line 4,169 ⟶ 4,724:
{ InvalidArgumentException.raise() };
if (node.containsProperty(
{
list.append(node.Leaf)
Line 4,181 ⟶ 4,736:
readLeaves(list)
<= readLeaves(list,
}
Line 4,199 ⟶ 4,754:
theNumbers := new object[]
{
1 + randomGenerator.
1 + randomGenerator.
1 + randomGenerator.
1 + randomGenerator.
}
}
Line 4,209 ⟶ 4,764:
{
console
.printLine
.printLine
.printLine
.printLine
.printLine
.printLine
.printLine
.printLine
.writeLine()
.printLine
.printLine
}
prompt()
{
theNumbers.forEach::(n){ console.print(n," ") };
console.print
}
Line 4,234 ⟶ 4,789:
var leaves := new ArrayList();
tree.readLeaves
ifnot (leaves.ascendant().sequenceEqual(theNumbers.ascendant()))
{ console.printLine
var result := tree.Value;
Line 4,265 ⟶ 4,820:
if (expr == "")
{
console.printLine
}
else
Line 4,275 ⟶ 4,830:
catch(Exception e)
{
console.printLine
//console.printLine:"An error occurred. Check your input and try again."
}
};
Line 4,283 ⟶ 4,839:
}
}
// --- program ---
public program()
Line 4,289 ⟶ 4,847:
while (game.prompt().playRound(console.readLine())) {}
}</
{{out}}
<pre>
Line 4,315 ⟶ 4,873:
=={{header|Elixir}}==
{{trans|Erlang}}
<
def main do
IO.puts "24 Game"
Line 4,353 ⟶ 4,911:
end
Game24.main</
{{out}}
Line 4,368 ⟶ 4,926:
=={{header|Erlang}}==
<
-export([main/0]).
Line 4,433 ⟶ 4,991:
eval([X|Rest], 0) when X >= $1, X =< $9 ->
eval(Rest, X-$0).
</syntaxhighlight>
The evaluator uses a simple infix scheme that doesn't care about operator precedence, but does support brackets and parentheses alike. Thus, <code>((9+1)*2)+2+2</code> is evaluated as:
Line 4,465 ⟶ 5,023:
=={{header|F_Sharp|F#}}==
<
open System.Text.RegularExpressions
Line 4,570 ⟶ 5,128:
loop()
gameLoop()</
{{out}}
<pre>Compute 24 from the following 4 numbers: 3 3 3 5
Line 4,589 ⟶ 5,147:
=={{header|Factor}}==
<
combinators.short-circuit
continuations
Line 4,631 ⟶ 5,189:
[ '[ _ step ] loop ]
bi ;
</syntaxhighlight>
Sample:
<
IN: scratchpad main
Your numbers are { 4, 1, 8, 2 }, make an expression
8 4 + 2 * 1 /
You got it!
</syntaxhighlight>
=={{header|Falcon}}==
<
function genRandomNumbers( amount )
Line 4,711 ⟶ 5,269:
end
end
end</
=={{header|Fortran}}==
Line 4,717 ⟶ 5,275:
Indicate operator precedence by parentheses; e.g. (3+(5*6))-9. No whitespace is admissible.
The program uses [[Insertion_sort#Fortran|Insertion_sort in Fortran]].
<
implicit none
real :: vector(4), reals(11), result, a, b, c, d
Line 4,828 ⟶ 5,386:
end program game_24
</syntaxhighlight>
===As a more general recursive descent parser:===
Permits spaces and arbitrary parentheses.
<
! implement a recursive descent parser
module evaluate_algebraic_expression
Line 5,044 ⟶ 5,602:
end subroutine deal
end program g24
</syntaxhighlight>
Compilation and too many examples. Which would you cut?
Line 5,149 ⟶ 5,707:
=={{header|FreeBASIC}}==
Solución en '''RPN''':
<
' The 24 game en FreeBASIC
Line 5,258 ⟶ 5,816:
End
'--------------------------
</syntaxhighlight>
{{out}}
<pre>
Line 5,278 ⟶ 5,836:
</pre>
=={{header|FutureBasic}}==
24 Game
May 13, 2024
Rich Love
Modified to include 96 blocks of numbers for random selection.
Thanks to Ken and Bernie
<syntaxhighlight lang="futurebasic">
#build CompilerOptions @"-Wno-unused-variable"
_mEdit = 2
editmenu _mEdit
void local fn EraseErrorText
CGRect r
r = fn CGRectMake(10, 200, 400, 15)
rect fill r,fn ColorBlack
end fn
local fn ArcRandom( a as long, b as long ) as long
long i
cln i = (arc4random()%(b-a+1))+a;
end fn = fn floor(i)
local fn GetRandomNumbers as CFStringRef
CFArrayRef combos = @[¬
@"1 3 2 6", @"1 7 2 1", @"1 5 2 2", @"1 9 2 1", @"3 7 6 2",¬
@"1 2 3 9", @"1 6 3 1", @"1 4 3 3", @"1 4 5 6", @"1 3 4 4",¬
@"1 1 5 4", @"1 9 3 1", @"2 2 3 2", @"2 6 3 1", @"6 4 9 8",¬
@"2 8 2 1", @"3 2 5 2", @"6 5 4 4", @"2 6 2 1", @"2 4 3 1",¬
@"2 8 1 1", @"2 9 1 1", @"3 9 6 2", @"3 5 2 1", @"3 3 2 2",¬
@"3 7 1 1", @"3 2 4 1", @"2 5 7 8", @"3 8 1 6", @"4 2 9 1",¬
@"4 4 2 1", @"4 8 1 1", @"8 8 9 6", @"4 6 1 1", @"5 3 2 1",¬
@"5 7 1 1", @"5 1 2 2", @"1 5 1 4", @"5 2 2 2", @"5 4 1 1",¬
@"5 8 1 1", @"3 4 3 3", @"6 6 2 1", @"6 2 2 1", @"6 1 4 1",¬
@"9 6 2 3", @"9 5 5 9", @"7 1 3 1", @"7 5 1 1", @"8 1 8 6",¬
@"7 1 2 2", @"7 2 1 1", @"7 4 1 1", @"8 3 1 1", @"8 4 2 1",¬
@"8 1 3 1", @"8 2 1 1", @"9 3 2 1", @"2 3 5 3", @"9 1 2 1",¬
@"9 1 8 3", @"9 2 4 3", @"9 4 1 3", @"4 7 8 2", @"1 8 6 2",¬
@"6 1 6 1", @"1 6 2 2", @"1 8 3 1", @"5 7 1 3", @"6 2 3 4",¬
@"5 5 6 1", @"2 6 1 2", @"8 1 2 4", @"4 9 6 1", @"6 4 1 2",¬
@"4 7 3 2", @"5 5 4 9", @"7 3 6 2", @"6 1 2 2", @"6 2 1 2",¬
@"9 2 3 7", @"1 2 5 2", @"5 3 4 7", @"1 3 8 1", @"1 4 5 2",¬
@"1 4 7 1", @"1 5 6 2", @"1 5 8 1", @"2 6 7 1", @"2 3 4 2",¬
@"2 3 6 1", @"2 4 5 1", @"3 4 5 9", @"4 1 2 9", @"2 1 3 5",¬
@"2 2 3 4"]
long i = fn ArcRandom( 0, len(combos) - 1 )
end fn = combos[i]
local fn EvaluateMath( equation as CFStringRef ) as CFStringRef
equation = fn StringByReplacingOccurrencesOfString( lcase(equation), @"x", @"*" )
CFStringRef result = NULL
RegularExpressionRef regex = fn RegularExpressionWithPattern( @"[0-9.]+", NSRegularExpressionCaseInsensitive, NULL )
CFArrayRef matches = fn RegularExpressionMatches( regex, equation, 0, fn CFRangeMake( 0, len(equation) ) )
NSInteger intConversions = 0
TextCheckingResultRef match
CFRange originalRange
CFRange adjustedRange
CFStringRef value
for match in matches
originalRange = fn TextCheckingResultRange( match )
adjustedRange = fn CFRangeMake( ( originalRange.location + ( intConversions * len( @".0") ) ), originalRange.length )
value = fn StringSubstringWithRange( equation, adjustedRange )
if fn StringContainsString( value, @"." )
continue
else
equation = fn StringByReplacingCharactersInRange( equation, adjustedRange, fn StringWithFormat( @"%@.0", value ) )
intConversions++
end if
next
ExceptionRef e
try
ExpressionRef expression = fn ExpressionWithFormat( equation )
CFNumberRef number = fn ExpressionValueWithObject( expression, NULL, NULL )
result = fn StringWithFormat( @"%.3f", dblval( number ) )
end try
catch (e)
result = fn StringWithFormat( @"%@", e ) : exit fn
end catch
// Test if result is an integer and, if so, return result as an integer
if( fn StringDoubleValue( result ) == fn floorf( fn StringDoubleValue( result ) ) )
result = fn ArrayFirstObject( fn StringComponentsSeparatedByString( result, @"." ) )
end if
end fn = result
local fn QuitOrPlayAlert(GameResult as CFStringRef)
alert -2,,GameResult,@"You won!",@"Quit;Play Again"
AlertButtonSetKeyEquivalent( 2, 2, @"\e" )
short result
result = alert 2
if ( result != NSAlertSecondButtonReturn ) then appterminate
end fn
local fn BuildWindow
CGRect r = fn CGRectMake( 0, 0, 580, 250)
window 1, @"24 Game", r
windowcenter(1)
WindowSetBackgroundColor(1,fn ColorBlack)
end fn
///////// Start //////////
fn BuildWindow
short d(4), i
CFStringRef CheckForDuplicates(97)
for i = 1 to 96
CheckForDuplicates(i) = @""
next i
short DuplicatesCounter
DuplicatesCounter = 0
"Main"
cls
text ,,fn colorWhite
print
print %(10,15),"Given four numbers and using just the +, -, *, and / operators; and the"
print %(10,30),"possible use of parenthesis (), enter an expression that equates to 24."
print %(10,45),"You must use all your numbers and only those numbers."
print %(10,60),"Examples: 9618 Solution 9 + 6 + 1 + 8 or 3173 Solution ((3 * 1) * 7) + 3"
print
print %(10,85),"Enter Q to quit or S to skip to the next number."
"GetFourNumbers"
CFArrayRef randomNumbers : randomNumbers= fn StringComponentsSeparatedByString( fn GetRandomNumbers, @" " )
CFStringRef RandomNumberblock : RandomNumberblock = @""
CFStringRef RandomNumberblockAdd : RandomNumberblockAdd = @""
for i = 0 to 3
// create a string from the 4 numbers
RandomNumberblockAdd = randomNumbers[i]
RandomNumberblock = fn StringByAppendingString(RandomNumberblock,RandomNumberblockAdd)
RandomNumberblock = fn StringByAppendingString(RandomNumberblock,@" ")
next i
if DuplicatesCounter = > 96
// reset counter when last number is retrieved and start from the first number block
DuplicatesCounter = 0
for i = 1 to 96
CheckForDuplicates(i) = @""
next i
end if
for i = 1 to 96
// check the current numbers with the numbers already used
if fn StringIsEqual(RandomNumberblock,CheckForDuplicates(i))
RandomNumberblock = fn StringWithString(CheckForDuplicates(DuplicatesCounter))
goto "GetFourNumbers"
end if
next i
DuplicatesCounter ++
CheckForDuplicates(DuplicatesCounter) = fn StringWithString(RandomNumberblock)
d(1) = fn StringIntegerValue( randomNumbers[0] )
d(2) = fn StringIntegerValue( randomNumbers[1] )
d(3) = fn StringIntegerValue( randomNumbers[2] )
d(4) = fn StringIntegerValue( randomNumbers[3] )
//d(1) = 9:d(2) = 6:d(3) = 1:d(4) = 8 // Uncomment to test with 9618 numbers. Solution 9 + 6 + 1 + 8
//d(1) = 6:d(2) = 5:d(3) = 3:d(4) = 8 // Uncomment to test with 6538 numbers. Solution 6 / ( 5 - 3 ) * 8
//d(1) = 3:d(2) = 1:d(3) = 7:d(4) = 3 // Uncomment to test with 3773 numbers. Solution ((3 * 1) * 7) + 3
//d(1) = 4:d(2) = 2:d(3) = 7:d(4) = 1 // Uncomment to test with 4271 numbers. Solution (4 * ( 7 - 2 + 1 )
print
text ,,fn colorGreen
print %(10,110),"These are your numbers: "
print %(10,125)
text ,18,fn colorGreen
for i = 1 to 4
print d(i); " ";
next
print
text ,12,fn colorWhite
printf @"\n\n\n"
CFStringRef expr
bool TryAgain : TryAgain = _false
CFStringRef MessageText
CFStringRef UserInput = NULL
"InputExpression"
if TryAgain
MessageText = fn StringWithFormat( @"Enter math expression: [ '%@' was incorrect ]", expr )
UserInput = input %(10, 190), MessageText, @"123456789+-*/()qs", YES,, 0
else
UserInput = input %(10, 190), @"Enter math expression:", @"123456789+-*/()qs", YES,, 0
end if
if ( UserInput == NULL ) then "InputExpression"
expr = UserInput
if expr = @"" then "InputExpression"
if fn StringIsEqual(ucase(expr) , @"Q") then appterminate
if fn StringIsEqual(ucase(expr) , @"S") then "Main"
//check expr for validity
short j
bool GotAllNumbers : GotAllNumbers = _false
short ThisNumberPosition : ThisNumberPosition = 0
short GotaNumber : GotaNumber = 0
short TotalNumbers : TotalNumbers = 0
for i = 1 to 4
GotaNumber = 0
for j = 0 to len(expr) -1
ThisNumberPosition = instr( j, expr, right(str( d(i)),1 ))
ThisNumberPosition ++
if ThisNumberPosition then GotaNumber = _true
next j
if GotaNumber then TotalNumbers ++
next i
if TotalNumbers => 4 then GotAllNumbers = _true
if GotAllNumbers = _false
fn EraseErrorText
text ,,fn colorRed
TryAgain = _true
print %(10,200);"ERROR! Must use all your numbers and only those numbers." : goto "InputExpression"
text ,,fn colorWhite
end if
fn EraseErrorText
if fn EvaluateMath( expr ) = _false
text ,,fn colorRed
TryAgain = _true
Print %(10,200);"Error! Incorrect math sequence."
goto "InputExpression"
text ,,fn colorWhite
end if
CFStringRef GameResult
if fn StringIntegerValue( fn EvaluateMath( expr ) ) == 24 then GameResult = @"Correct" else GameResult = @"Incorrect"
if GameResult = @"Incorrect"
TryAgain = _true
goto "InputExpression"
end if
fn QuitOrPlayAlert(GameResult)
goto "Main"
handleevents
</syntaxhighlight>
=={{header|GAP}}==
Solution in '''RPN''':
<
local input, digits, line, c, chars, stack, stackptr, cur, p, q, ok, a, b, run;
input := InputTextUser();
Line 5,371 ⟶ 6,200:
[ 5, 9, 2, 7 ]
end
gap></
=={{header|Go}}==
RPN solution.
<
import (
Line 5,442 ⟶ 6,271:
fmt.Println("correct.")
}
}</
Example game:
<pre>
Line 5,451 ⟶ 6,280:
=={{header|Gosu}}==
<
uses java.lang.Double
uses java.lang.Integer
Line 5,557 ⟶ 6,386:
print( "You lose!" )
}
</syntaxhighlight>
=={{header|Groovy}}==
{{trans|Ruby}}
This solution breaks strict adherence to the rules in only one way: any line that starts with the letter "q" causes the game to quit.
<
final input = new Scanner(System.in)
Line 5,628 ⟶ 6,457:
println 'One more try, then?'
}
}</
Sample Run:
Line 5,651 ⟶ 6,480:
=={{header|Haskell}}==
<
import Data.Char (isDigit)
import Data.Maybe (fromJust)
Line 5,703 ⟶ 6,532:
isOp v = elem v $ fmap fst ops
ops = [("+", (+)), ("-", (-)), ("*", (*)), ("/", (/))]</
=={{header|HicEst}}==
<
CHARACTER expression*100, prompt*100, answers='Wrong,Correct,', protocol='24 game.txt'
Line 5,740 ⟶ 6,569:
DLG(TItle=prompt, Button='>2:Try again', B='>1:New game', B='Quit')
END</
<
4 + 8 + 7 + a: Instead 4 digits you used 3
4 + 8 + 7 + a + 4: a is an illegal character
4 + 8 + 7a + 4: a is an illegal character
4 + 8 + 7 + 4:; answer=Wrong; result=23;
4 * 7 - 8 + 4:; answer=Correct; result=24;</
=={{header|Huginn}}==
<
exec huginn --no-argv -E "${0}"
#! huginn
Line 5,802 ⟶ 6,631:
}
return ( 0 );
}</
=={{header|Icon}} and {{header|Unicon}}==
This plays the game of 24 using a simplified version of the code from the [[Arithmetic_evaluation#Icon_and_Unicon|Arithmetic evaluation]] task.
<
link strings # for csort, deletec
Line 5,863 ⟶ 6,692:
"Combining (concatenating) digits is not allowed.\n",
"Enter 'help', 'quit', or an expression.\n")
end</
{{libheader|Icon Programming Library}}
Line 5,891 ⟶ 6,720:
=={{header|J}}==
<
deal=: 1 + ? bind 9 9 9 9
rules=: smoutput bind 'see http://en.wikipedia.org/wiki/24_Game'
Line 5,901 ⟶ 6,730:
respond=: (;:'no yes') {::~ wellformed * is24
game24=: (respond input)@deal@rules</
Example use:
Line 5,916 ⟶ 6,745:
=={{header|Java}}==
{{works with|Java|7}}
<
public class Game24 {
Line 5,977 ⟶ 6,806:
return result;
}
}</
{{out}}
Line 5,986 ⟶ 6,815:
=={{header|JavaScript}}==
<
function twentyfour(numbers, input) {
var invalidChars = /[^\d\+\*\/\s-\(\)]/;
Line 6,038 ⟶ 6,867:
alert(twentyfour(numbers, input));
}
</syntaxhighlight>
=={{header|Julia}}==
This implementation, because it is based on the Julia parser and evaluator, allows the user to enter arbitrary infix expressions, including parentheses. (These expressions are checked to ensure that they only include the allowed operations on integer literals.)
<
validexpr(ex::Int) = true
validexpr(ex::Any) = false
Line 6,069 ⟶ 6,898:
end
end
end</
{{out}}
<pre>
Line 6,081 ⟶ 6,910:
enter expression using [2,5,8,9] => (8 + 9) + (5 + 2)
you won!</pre>
=={{header|Koka}}==
<syntaxhighlight lang=koka>
import std/num/random
import std/os/readline
type expr
Num(i: int)
Add(e1: expr, e2: expr)
Sub(e1: expr, e2: expr)
Mul(e1: expr, e2: expr)
Div(e1: expr, e2: expr)
fun genNum()
random-int() % 9 + 1
fun parseFact(s: string): <div,exn> (expr, string)
match s.head
"(" ->
val (e, rest) = s.tail.parseExpr()
match rest.head
")" -> (e, rest.tail)
_ -> throw("expected ')'")
x | x.head-char.default('_').is-digit -> (Num(x.parse-int.unjust), s.tail)
_ -> throw("No factor")
fun parseTerm(s): <div,exn> (expr, string)
val (e', n) = s.parseFact()
match n.head
"*" ->
val (e'', n') = n.tail.parseTerm()
(Mul(e', e''), n')
"/" ->
val (e'', n') = n.tail.parseTerm()
(Div(e', e''), n')
_ -> (e', n)
fun parseExpr(s): <div,exn> (expr, string)
val (e', n) = s.parseTerm()
match n.head
"+" ->
val (e'', n') = n.tail.parseExpr()
(Add(e', e''), n')
"-" ->
val (e'', n') = n.tail.parseExpr()
(Sub(e', e''), n')
_ -> (e', n)
fun numbers(e: expr): div list<int>
match e
Num(i) -> [i]
Add(e1, e2) -> numbers(e1) ++ numbers(e2)
Sub(e1, e2) -> numbers(e1) ++ numbers(e2)
Mul(e1, e2) -> numbers(e1) ++ numbers(e2)
Div(e1, e2) -> numbers(e1) ++ numbers(e2)
fun check(e: expr, l: list<int>): <div,exn> ()
val ns = numbers(e)
if (ns.length == 4) then
if l.all(fn(n) ns.any(fn(x) x == n)) then
()
else
throw("wrong numbers")
else
throw("wrong number of numbers")
fun evaluate(e: expr): float64
match e
Num(i) -> i.float64
Add(e1, e2) -> evaluate(e1) + evaluate(e2)
Sub(e1, e2) -> evaluate(e1) - evaluate(e2)
Mul(e1, e2) -> evaluate(e1) * evaluate(e2)
Div(e1, e2) -> evaluate(e1) / evaluate(e2)
fun main()
println("\nGoal: ")
println("- Create an expression that evaluates to 24")
println("- Using the four given numbers each number once")
println("- Using the operators (+-/*) with no spaces")
println("Example 2 3 4 1: (2+3)*4*1\n")
println("Here are your numbers!")
var l: list<int> := Nil
repeat(4) fn()
val n = genNum()
l := Cons(n, l)
(n.show ++ " ").print
println("")
var found := False
while { !found } fn()
val (expr, r) = readline().parseExpr()
if r.count > 0 then
println("Expected EOF but got: " ++ r ++ " please try again")
return ()
expr.check(l)
val result = expr.evaluate()
if result == 24.0 then
println("You got it!")
found := True
else
println("Try again, your expression evaluated to: " ++ result.show)
</syntaxhighlight>
=={{header|Kotlin}}==
<
import java.util.Scanner
import java.util.Stack
Line 6,134 ⟶ 7,064:
}
fun main(args: Array<String>) = Game24.run()</
=={{header|Lasso}}==
Line 6,142 ⟶ 7,072:
If a valid expression it is evaluated, and the result and success state shown to the user.
<
if(sys_listunboundmethods !>> 'randoms') => {
define randoms()::array => {
Line 6,211 ⟶ 7,141:
[if(#exprsafe)]
<p>Result: <b>[#exprresult]</b> [#exprcorrect ? 'is CORRECT!' | 'is incorrect']</p>
[/if]</
=={{header|Liberty BASIC}}==
<
dim chk(4)
print "The 24 Game"
Line 6,300 ⟶ 7,230:
exit function
[handler]
end function</
=={{header|LiveCode}}==
Line 6,313 ⟶ 7,243:
4. label button "StartButton"
5. Add the following to the code of "StartButton"<
put empty into fld "EvalField"
put empty into fld "AnswerField"
put random(9) & comma & random(9) & comma & random(9) & comma & random(9) into fld "YourNumbersField"
end mouseUp</
6. Add the following to the code of field "EvalField"<
on keyDown k
local ops, nums, allowedKeys, numsCopy, expr
Line 6,348 ⟶ 7,278:
exit keyDown
end if
end keyDown</
=={{header|Locomotive Basic}}==
<
20 PRINT "The 24 Game"
30 PRINT "===========":PRINT
Line 6,405 ⟶ 7,335:
520 ' syntax error, e.g. non-matching parentheses
530 PRINT "Error in expression, please try again."
540 RESUME 150</
Note: The program needs a writable disk in the active disk drive.
Line 6,411 ⟶ 7,341:
=={{header|Logo}}==
{{works with|UCB_Logo|5.5}}
<
make "false 1=0
make "true 1=1
Line 6,484 ⟶ 7,414:
]]]
]
bye</
{{out}}
<pre>
Line 6,503 ⟶ 7,433:
=={{header|Lua}}==
<
local function help()
print [[
Line 6,602 ⟶ 7,532:
end
end
game24()</
Alternately, using the <code>lpeg.re</code> module:
<
print [[
The 24 Game
Line 6,647 ⟶ 7,577:
end
end
twentyfour()</
=={{header|Maple}}==
Click [http://maplecloud.maplesoft.com/application.jsp?appId=5764927761416192 here] to try this game online.
<
export ModuleApply;
local cheating;
Line 6,734 ⟶ 7,664:
end module:
play24();</
{{out}}
<pre>
Line 6,755 ⟶ 7,685:
Most of the job is already done by Mathematica (the expression conversion); in fact, it is ''too'' good—it automatically converts ex. 3/4 to Times[3, Power[4, -1]], which we have to specifically test for so that real powers don't get through.
<
Quiet[Check[
With[{h = ToExpression[x, StandardForm, HoldForm]},
Line 6,769 ⟶ 7,699:
"Sorry, that is invalid.", 24, "Congrats! That's 24!", _,
"Sorry, that makes " <> ToString[ToExpression@x, InputForm] <>
", not 24."]]}}]</
=={{header|MATLAB}} / {{header|Octave}}==
<
N = 4;
n = ceil(rand(1,N)*9);
Line 6,799 ⟶ 7,729:
else
fprintf('expression "%s" does not result in 24 but %i.\n',s,val);
end; </
=={{header|MiniScript}}==
We use a simple recursive descent parser, with a bit of extra code to make sure that only available digits are used, and all of them are used.
<
result = evalMultDiv
while true
Line 6,858 ⟶ 7,788:
result = null
while result != 24
availableDigits = choices[
print "Using only the digits " + availableDigits + ","
tokens = input("enter an expression that comes to 24: ").replace(" ","").values
Line 6,868 ⟶ 7,798:
if result != null then print "That equals " + result + "."
end while
print "Great job!"</
{{out}}
Line 6,886 ⟶ 7,816:
=={{header|mIRC Scripting Language}}==
<
dialog -m 24-Game 24-Game
}
Line 6,918 ⟶ 7,848:
did -o 24-Game 1 1 Numbers: $rand(1,9) $rand(1,9) $rand(1,9) $rand(1,9)
}
}</
=={{header|Modula-2}}==
{{libheader|Ulm's Modula-2 Library}}
<
FROM InOut IMPORT WriteString, WriteLn, Write, ReadString, WriteInt;
Line 7,100 ⟶ 8,030:
END;(*of CASE*)
WriteLn;
END TwentyFour.</
=={{header|MUMPS}}==
<
k number, operator, bracket
; generate 4 random numbers each between 1 & 9
Line 7,183 ⟶ 8,113:
w x
q
</syntaxhighlight>
=={{header|Nanoquery}}==
<
import Nanoquery.Util
Line 7,269 ⟶ 8,199:
end
end
end</
{{out}}
<pre>Your digits are: [2, 5, 4, 6]
Line 7,286 ⟶ 8,216:
{{trans|D}}
{{works with|Nim Compiler|1.0.0}}
<
from strutils import Whitespace
from algorithm import sort
Line 7,323 ⟶ 8,253:
raise newException(ValueError, "Wrong expression.")
echo "Result: ", stack[0]
echo if abs(stack[0] - 24) < 0.001: "Good job!" else: "Try again."</
Example game:
<pre>Make 24 with the digits: @[8, 1, 3, 1]
Line 7,334 ⟶ 8,264:
Source: [https://github.com/nitlang/nit/blob/master/examples/rosettacode/24_game.nit the Nit’s official repository]
<
fun is_op: Bool do return "-+/*".has(self)
end
Line 7,482 ⟶ 8,412:
end
if random_numbers.has(24) then print "CONGRATULATIONS" else print "YOU LOSE"</
=={{header|Objeck}}==
{{trans|C++}}
<
use System.Matrix;
Line 7,587 ⟶ 8,517:
alias Func {
Calc : (IntHolder, IntHolder) ~ IntHolder
}</
=={{header|OCaml}}==
Line 7,594 ⟶ 8,524:
ocamlopt -pp camlp4o g24.ml -o g24.opt
<
| Const of float
| Sum of expression * expression (* e1 + e2 *)
Line 7,683 ⟶ 8,613:
else print_endline "Try again"
end
done</
=={{header|Oforth}}==
<
: game
Line 7,708 ⟶ 8,638:
#null? l conform? ifFalse: [ "Sorry, all numbers must be used..." . return ]
24 if=: [ "You won !" ] else: [ "You loose..." ] .
;</
=={{header|ooRexx}}==
Line 7,719 ⟶ 8,649:
=={{header|OpenEdge/Progress}}==
The dynamic query parser is used to evaluate the expression.
<
DEFINE VARIABLE p_deanswer AS DECIMAL NO-UNDO.
Line 7,786 ⟶ 8,716:
MESSAGE cmessage VIEW-AS ALERT-BOX.
</syntaxhighlight>
=={{header|PARI/GP}}==
{{untested}}
<
my(v=vecsort(vector(4,i,random(8)+1)));
print("Form 24 using */+-() and: "v);
Line 7,834 ⟶ 8,764:
1
)
};</
=={{header|Perl}}==
<
use warnings;
use strict;
Line 7,882 ⟶ 8,812:
elsif ($n == 24) { say "You win!"; last; }
else { say "Sorry, your expression is $n, not 24"; }
}</
=={{header|Phix}}==
<!--<
<span style="color: #000080;font-style:italic;">-- Note this uses simple/strict left association, so for example:
-- 1+2*1*8 is ((1+2)*1)*8 not 1+((2*1)*8) [or 1+(2*(1*8))], and
Line 8,061 ⟶ 8,991:
<span style="color: #000000;">play</span><span style="color: #0000FF;">()</span>
<!--</
=={{header|PHP}}==
{{trans|Perl}}
<
The 24 Game
Line 8,158 ⟶ 9,088:
return eval("return $expression;");
}
?></
=={{header|Picat}}==
<
main =>
Line 8,184 ⟶ 9,114:
catch(Term = parse_term(Exp), Exception, println(Exception)),
Res is Term,
(Res =:= 24 ->
println("Good work!")
;
Line 8,191 ⟶ 9,121:
),
play.
</syntaxhighlight>
=={{header|PicoLisp}}==
<
(load "@lib/frac.l")
Line 8,250 ⟶ 9,180:
(loopuntilquit)
</syntaxhighlight>
{{out}}
<pre>
Line 8,298 ⟶ 9,228:
=={{header|PL/I}}==
<
/* Plays the game of 24. */
Line 8,435 ⟶ 9,365:
end TWENTYFOUR;
</syntaxhighlight>
=={{header|Potion}}==
<
x = s ord(0)
if (x >= "0"ord && x <= "9"ord): true.
Line 8,477 ⟶ 9,407:
else:
(entry, " => ", expr string, " != 24") join("") say.
.</
=={{header|PowerShell}}==
Line 8,484 ⟶ 9,414:
todo: add a validation that all given digits were used. Right now the validation is that 4 digits should be used in the expression, but not exactly the ones given. (example: if you are given the digits 2, 2, 6, 9 this program accepts the following solution: 6 * '''4''' * 2 / 2)
<
CLS
Line 8,558 ⟶ 9,488:
}
While($EndResult -ne 24)
</syntaxhighlight>
=={{header|ProDOS}}==
This example uses the math module:
<
editvar /modify -random- = <10
printline These are your four digits: -random- -random- -random- -random-
Line 8,572 ⟶ 9,502:
:b
editvar /newvar /value=b /userinput=1 /title=Do you want to play again?
if -b- /hasvalue y goto :a else exitcurrentprogram</
=={{header|Prolog}}==
{{Works with|GNU Prolog}}
<
Line 8,605 ⟶ 9,535:
, ( X == 10 -> Xs = [] ; Xs = [X|Ys], get_line(Ys) )
.
main :- randomize, play, halt.</
Example "session":
<pre>Digits: [9,4,6,9]
Line 8,631 ⟶ 9,561:
=={{header|PureBasic}}==
<
Global Dim digits(#digitCount - 1) ;holds random digits
Line 8,790 ⟶ 9,720:
Print(#CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
EndIf</
{{out}}
<pre>The 24 Game
Line 8,811 ⟶ 9,741:
===Python: Original, with output===
Uses eval, the built-in expression evaluator of infix expressions.
<
The 24 Game
Line 8,878 ⟶ 9,808:
print ("Thank you and goodbye")
if __name__ == '__main__': main() </
{{out}}
Line 8,904 ⟶ 9,834:
===Python: Alternative===
<
chars = ["(",")","/","+","-","*"]
while True:
Line 8,936 ⟶ 9,866:
print "You cannot use anthing other than", charsandints
break
print "Thanks for playing"</
=={{header|Quackery}}==
Line 8,942 ⟶ 9,872:
<code>switch</code>, <code>case</code>, and <code>otherwise</code> are defined at [[Metaprogramming#Quackery]].
<
0 $ "*/+-" witheach [ bit | ]
Line 9,015 ⟶ 9,945:
24 n->v v- v0= iff
[ say ". :-)" ] else [ say ". :-(" ]
numbers release ] is game ( --> )</
{{out}}
Line 9,062 ⟶ 9,992:
This makes use of R's metaprogramming (parse, eval, etc.). It uses parse to obtain a parse tree, which is scanned for containing only permitted elements before evaluating.
<
selector=function() sample(1:9, 4, replace=TRUE),
arguments=selector(),
Line 9,115 ⟶ 10,045:
if (! isTRUE(all.equal(sort(numbers.used), sort(arguments))))
stop("Must use each number once.")
}</
Example Session
<
Make 24 out of the numbers 1, 6, 7, 5 and the operators +, -, *, /, ( .
Line 9,146 ⟶ 10,076:
> q
Goodbye!
</syntaxhighlight>
=={{header|Racket}}==
Line 9,154 ⟶ 10,084:
invalid cases.
<
#lang racket
Line 9,190 ⟶ 10,120:
result
(error "You didn`t use all numbers!")))
</syntaxhighlight>
Testing the interpreter:
Line 9,214 ⟶ 10,144:
The program which uses the interpreter to play the game:
<
;; starting the program
(define (start)
Line 9,251 ⟶ 10,181:
(define (read-the-answer)
(read (open-input-string (format "(~a)" (read-line)))))
</syntaxhighlight>
=={{header|Raku}}==
Line 9,257 ⟶ 10,187:
{{works with|Rakudo|2015.12}}
<syntaxhighlight lang="raku"
say "Here are your digits: ",
Line 9,283 ⟶ 10,213:
}
}
</syntaxhighlight>
The <code>MONKEY-SEE-NO-EVAL</code> pragma enables the dangerous <code>EVAL</code> function, which will compile and execute even user input. In this example, the grammar used to parse the input should ensure that only safe expressions are evaluated.
Line 9,289 ⟶ 10,219:
=={{header|Red}}==
<
Red []
print "Evaluation from left to right with no precedence, unless you use parenthesis." print ""
Line 9,325 ⟶ 10,255:
print "You got it right!"
</syntaxhighlight>
Output:
<pre>
Line 9,342 ⟶ 10,272:
===Red: Alternative===
<
Red [
Title: "24 Game"
Line 9,376 ⟶ 10,306:
forever [main]
</syntaxhighlight>
=={{header|REXX}}==
Line 9,384 ⟶ 10,314:
This REXX version uses an in─line documentation (for help).
<
╔═════════════════════════════════════════════════════════════════════════════╗
Line 9,631 ⟶ 10,561:
when _v\==0 then call ger 'illegal character:' substr(y, _v, 1)
otherwise nop
end /*select*/</
Some older REXXes don't have a '''changestr''' BIF, so one is included here ──► [[CHANGESTR.REX]].
Line 9,648 ⟶ 10,578:
=={{header|Ring}}==
<
# Project : 24 game
Line 9,709 ⟶ 10,639:
ok
end
</syntaxhighlight>
Output:
<pre>
Line 9,726 ⟶ 10,656:
sorry, you used the illegal digit 9
</pre>
=={{header|RPL}}==
{{works with|RPL|HP49-C #2.15}}
« '''IF''' DUP TYPE 9. ≠ '''THEN''' { } + <span style="color:grey">@ ''stack contains a number''</span>
'''ELSE'''
'''CASE''' OBJ→ SWAP 2. ≠ '''THEN''' DROP 0 '''END''' <span style="color:grey">@ ''stack contains a monadic operator''</span>
"+-*/" SWAP →STR POS NOT '''THEN''' DROP 0 '''END''' <span style="color:grey">@ ''stack contains a forbidden dyadic operator''</span>
'''END'''
<span style="color:blue">GET4</span> SWAP <span style="color:blue">GET4</span> +
'''END'''
» '<span style="color:blue">GET4</span>' STO <span style="color:grey">@ ''( 'expression' → { numbers } )''</span>
« 1 CF
« RAND 9 * CEIL R→I » 'x' 1 4 1 SEQ SORT <span style="color:grey">@ generate 4 numbers</span>
'''WHILE''' 1 FC? '''REPEAT'''
"Make 24 with" OVER →STR 2 OVER SIZE 2 - SUB +
{ "'" ALG V } INPUT <span style="color:grey">@ asks for an evaluable string</span>
CLLCD DUP TAIL 1 DISP
STR→ DUP <span style="color:blue">GET4</span>
'''CASE''' DUP 0 POS '''THEN''' DROP2 "Forbidden operator" '''END'''
SORT 3 PICK ≠ '''THEN''' DROP "Bad number" '''END'''
EVAL DUP →NUM 3 DISP 24 == '''THEN''' 1 SF "You won!" '''END'''
"Failed to get 24"
'''END'''
2 DISP 2 WAIT
'''END''' DROP
» '<span style="color:blue">GAM24</span>' STO
=={{header|Ruby}}==
<
def self.play
nums = Array.new(4){rand(1..9)}
Line 9,767 ⟶ 10,724:
end
Guess.play</
=={{header|Rust}}==
Line 9,775 ⟶ 10,732:
So if there is someone better than me please feel free to improve.
{{libheader|rand}}
<
extern crate rand;
use rand::Rng;
Line 9,876 ⟶ 10,833:
}
}</
=={{header|Scala}}==
Line 9,884 ⟶ 10,841:
Only problems with solution are shown to the user.
<div style='width: full; overflow: scroll'><
def main(args: Array[String]) {
import Parser.TwentyFourParser
Line 10,037 ⟶ 10,994:
}
}
}</
{{out}}
Line 10,073 ⟶ 11,030:
This uses read to read in a scheme expression, and eval to evaluate it, so in that sense it's not ideal (eval is evil etc.) but any expression that is valid should be safe and terminate in a timely manner.
<
(require srfi/27 srfi/1) ;; random-integer, every
Line 10,136 ⟶ 11,093:
(provide play)
</syntaxhighlight>
{{out}}
Line 10,169 ⟶ 11,126:
=={{header|Sidef}}==
<
const grammar = Regex(
'^ (?&exp) \z
Line 10,204 ⟶ 11,161:
default { say "Sorry, your expression is #{n}, not 24" }
}
}</
{{out}}
<pre>
Line 10,217 ⟶ 11,174:
=={{header|Simula}}==
<
CLASS EXPR;
Line 10,513 ⟶ 11,470:
END.
</syntaxhighlight>
{{out}}
<pre>
Line 10,537 ⟶ 11,494:
=={{header|Swift}}==
<
import Foundation
Line 10,611 ⟶ 11,568:
println("Congratulations, you found a solution!")
}
</syntaxhighlight>
=={{header|Tcl}}==
{{trans|Python}}
This version also terminates cleanly on end-of-file.
<
proc choose4 {} {
set digits {}
Line 10,690 ⟶ 11,647:
puts "Thank you and goodbye"
}
main</
=={{header|TorqueScript}}==
Includes an equation parser to avoid using eval.
To use, type startTwentyFourGame(); in the console.
<
{
if($numbers !$= "")
Line 10,861 ⟶ 11,818:
}
return %equ;
}</
=={{header|TUSCRIPT}}==
<
$$ MODE TUSCRIPT
BUILD X_TABLE blanks = ":': :"
Line 10,938 ⟶ 11,895:
ENDSECTION
DO game
</syntaxhighlight>
{{out}}
<pre style='height:30ex;overflow:scroll'>
Line 10,968 ⟶ 11,925:
=={{header|UNIX Shell}}==
Tried to be POSIX. Not sure about corner-cases.
<
awk 'BEGIN { srand()
for(i = 1; i <= 4; i++) print 1 + int(9 * rand())
Line 10,997 ⟶ 11,954:
echo $message
done</
=={{header|VBA}}==
<syntaxhighlight lang=vb>
Sub Rosetta_24game()
Line 11,124 ⟶ 12,081:
End Sub
</syntaxhighlight>
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">import os
import rand
import rand.seed
import math
fn main() {
rand.seed(seed.time_seed_array(2))
mut n := []int{len: 4}
for i in 0.. n.len {
n[i] = rand.intn(9) or {0}
}
println("Your numbers: $n")
expr := os.input("Enter RPN: ")
if expr.len != 7 {
println("invalid. expression length must be 7." +
" (4 numbers, 3 operators, no spaces)")
return
}
mut stack := []f64{len: 0, cap:4}
for r in expr.split('') {
if r >= '0' && r <= '9' {
if n.len == 0 {
println("too many numbers.")
return
}
mut i := 0
for n[i] != r.int() {
i++
if i == n.len {
println("wrong numbers.")
return
}
}
n.delete(n.index(r.int()))
stack << f64(r[0]-'0'[0])
continue
}
if stack.len < 2 {
println("invalid expression syntax.")
return
}
match r {
'+' {
stack[stack.len-2] += stack[stack.len-1]
}
'-' {
stack[stack.len-2] -= stack[stack.len-1]
}
'*' {
stack[stack.len-2] *= stack[stack.len-1]
}
'/' {
stack[stack.len-2] /= stack[stack.len-1]
}
else {
println("$r invalid.")
return
}
}
stack = stack[..stack.len-1]
}
if math.abs(stack[0]-24) > 1e-6 {
println("incorrect. ${stack[0]} != 24")
} else {
println("correct.")
}
}</syntaxhighlight>
{{out}}
Sample game:
<pre>
Make 24 using these digits: [2, 3, 5, 1]
> 23*51-*
Correct!
</pre>
=={{header|Wren}}==
Line 11,130 ⟶ 12,165:
{{libheader|Wren-ioutil}}
{{libheader|Wren-seq}}
<
import "./ioutil" for Input
import "./seq" for Stack
var R = Random.new()
Line 11,176 ⟶ 12,211:
}
Game24.run()</
{{out}}
Line 11,183 ⟶ 12,218:
Make 24 using these digits: [2, 3, 5, 1]
> 23*51-*
Correct!
</pre>
=={{header|XPL0}}==
<syntaxhighlight lang "XPL0">real Stack(10), A, B;
int SP, I, Char, Digit, Digits(10);
proc Push(X);
real X;
[Stack(SP):= X; SP:= SP+1];
func real Pop;
[SP:= SP-1; return Stack(SP)];
[SP:= 0;
for I:= 0 to 9 do Digits(I):= 0;
Text(0, "Enter an RPN expression that equals 24 using all these digits:");
for I:= 0 to 3 do
[Digit:= Ran(9)+1;
ChOut(0, ^ ); ChOut(0, Digit+^0);
Digits(Digit):= Digits(Digit)+1;
];
Text(0, "^m^j> ");
loop [Char:= ChIn(1);
ChOut(0, Char);
if Char >= ^1 and Char <=^9 then
[Digit:= Char - ^0;
Push(float(Digit));
Digits(Digit):= Digits(Digit) - 1;
]
else [if SP >= 2 then [A:= Pop; B:= Pop] else quit;
case Char of
^+: Push(B+A);
^-: Push(B-A);
^*: Push(B*A);
^/: Push(B/A)
other quit;
];
];
CrLf(0);
for I:= 0 to 9 do
if Digits(I) # 0 then
[Text(0, "Must use each of the given digits.^m^j"); exit];
Text(0, if abs(Pop-24.0) < 0.001 then "Correct!" else "Wrong.");
CrLf(0);
]</syntaxhighlight>
{{out}}
<pre>
Enter an RPN expression that equals 24 using all these digits: 1 4 4 9
> 44*9+1-
Correct!
</pre>
Line 11,188 ⟶ 12,273:
=={{header|Yabasic}}==
With reverse polish notation
<
espacios$ = " "
Line 11,305 ⟶ 12,390:
until(testigo = false)
return cadena$
end sub</
{{trans|ZX Spectrum Basic}}
<
clear screen
n$=""
Line 11,389 ⟶ 12,474:
return execute(mid$(c$,5,8))
end sub
</syntaxhighlight>
=={{header|zkl}}==
<
digits := [1..4].pump(String,(0).random.fpM("11-",1,9));
exp := ask("Enter an expression using the digits ",digits,
Line 11,410 ⟶ 12,495:
else println("That evaled to ",r,", not 24");
}
}</
{{out}}
<pre>
Line 11,426 ⟶ 12,511:
=={{header|ZX Spectrum Basic}}==
<
20 RANDOMIZE
30 FOR i=1 TO 4
Line 11,477 ⟶ 12,562:
490 DATA "(nonon)on"
495 DATA "(no(non))on"
500 DATA "no(nonon)"</
|