24 game: Difference between revisions

31,075 bytes added ,  22 days ago
fix syntax highlighting
m (Minor grammatical edit.)
(fix syntax highlighting)
 
(38 intermediate revisions by 12 users not shown)
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 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}}==
Line 4,132 ⟶ 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}}==
Line 4,191 ⟶ 4,639:
 
=={{header|Elena}}==
ELENA 56.0 :
<syntaxhighlight lang=elena>import system'routines;
import system'collections;
Line 4,201 ⟶ 4,649:
class ExpressionTree
{
object theTree_tree;
constructor(s)
Line 4,207 ⟶ 4,655:
auto level := new Integer(0);
s.forEach::(ch)
{
var node := new DynamicStruct();
ch =>
$43 { node.Level := level + 1; node.Operation := __subjmssg add } // +
$45 { node.Level := level + 1; node.Operation := __subjmssg subtract } // -
$42 { node.Level := level + 2; node.Operation := __subjmssg multiply } // *
$47 { node.Level := level + 2; node.Operation := __subjmssg divide } // /
$40 { level.append(10); ^ self } // (
$41 { level.reduce(10); ^ self } // )
:! {
node.Leaf := ch.toString().toReal();
node.Level := level + 3
};
if (nil == theTree_tree)
{
theTree_tree := node
}
else
{
if (theTree_tree.Level >= node.Level)
{
node.Left := theTree_tree;
node.Right := nilValuenil;
theTree_tree := node
}
else
{
var top := theTree_tree;
while ((nilValuenil != top.Right)&&(top.Right.Level < node.Level))
{ top := top.Right };
node.Left := top.Right;
node.Right := nilValuenil;
top.Right := node
}
}
Line 4,253 ⟶ 4,701:
eval(node)
{
if (node.containsProperty(subjconstmssg Leaf))
{
^ node.Leaf
Line 4,269 ⟶ 4,717:
get Value()
<= eval(theTree_tree);
readLeaves(list, node)
Line 4,276 ⟶ 4,724:
{ InvalidArgumentException.raise() };
if (node.containsProperty(subjconstmssg Leaf))
{
list.append(node.Leaf)
Line 4,288 ⟶ 4,736:
readLeaves(list)
<= readLeaves(list,theTree_tree);
}
 
Line 4,306 ⟶ 4,754:
theNumbers := new object[]
{
1 + randomGenerator.eval:nextInt(9),
1 + randomGenerator.eval:nextInt(9),
1 + randomGenerator.eval:nextInt(9),
1 + randomGenerator.eval:nextInt(9)
}
}
Line 4,316 ⟶ 4,764:
{
console
.printLine:("------------------------------- Instructions ------------------------------")
.printLine:("Four digits will be displayed.")
.printLine:("Enter an equation using all of those four digits that evaluates to 24")
.printLine:("Only * / + - operators and () are allowed")
.printLine:("Digits can only be used once, but in any order you need.")
.printLine:("Digits cannot be combined - i.e.: 12 + 12 when given 1,2,2,1 is not allowed")
.printLine:("Submit a blank line to skip the current puzzle.")
.printLine:("Type 'q' to quit")
.writeLine()
.printLine:("Example: given 2 3 8 2, answer should resemble 8*3-(2-2)")
.printLine:("------------------------------- --------------------------------------------")
}
prompt()
{
theNumbers.forEach::(n){ console.print(n," ") };
console.print:(": ")
}
Line 4,341 ⟶ 4,789:
var leaves := new ArrayList();
tree.readLeaves:(leaves);
ifnot (leaves.ascendant().sequenceEqual(theNumbers.ascendant()))
{ console.printLine:("Invalid input. Enter an equation using all of those four digits. Try again."); ^ self };
var result := tree.Value;
Line 4,372 ⟶ 4,820:
if (expr == "")
{
console.printLine:("Skipping this puzzle"); self.newPuzzle()
}
else
Line 4,382 ⟶ 4,830:
catch(Exception e)
{
console.printLine:"An error occurred. Check your input and try again."(e)
//console.printLine:"An error occurred. Check your input and try again."
}
};
Line 4,390 ⟶ 4,839:
}
}
 
// --- program ---
 
public program()
Line 5,385 ⟶ 5,836:
 
</pre>
 
=={{header|Frink}}==
<syntaxhighlight lang="frink">ops = ["+", "-", "*", "/"]
 
chosen = new array[[4], {|x| random[1,9]}]
println[chosen]
 
for d = chosen.lexicographicPermute[]
multifor o = [ops, ops, ops]
{
str = "((" + d@0 + o@0 + d@1 + ")" + o@1 + d@2 + ")" + o@2 + d@3
if eval[str] == 24
println[str]
str = "(" + d@0 + o@0 + d@1 + ")" + o@1 + "(" + d@2 + + o@2 + d@3 + ")"
if eval[str] == 24
println[str]
}</syntaxhighlight>
{{out}}
<pre>
[9, 8, 7, 4]
(4+8)*(9-7)
((7+8)-9)*4
((7-9)+8)*4
(8+4)*(9-7)
((8+7)-9)*4
((8-9)+7)*4
(8*9)/(7-4)
(9-7)*(4+8)
(9-7)*(8+4)
(9*8)/(7-4)
</pre>
 
=={{header|FutureBasic}}==
24 Game
 
May 17, 2024
 
Rich Love
 
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 6 2", @"1 9 3 1", @"2 2 3 2", @"2 7 3 2", @"6 4 9 8",¬
@"2 8 2 1", @"3 2 5 2", @"6 5 4 4", @"2 6 6 8", @"2 4 3 1",¬
@"2 8 1 1", @"2 7 8 2", @"3 9 6 2", @"3 5 2 1", @"3 3 2 2",¬
@"3 7 1 1", @"3 8 9 3", @"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 6 8 5",¬
@"5 7 1 1", @"5 8 9 5", @"8 6 4 2", @"5 2 2 2", @"5 4 1 1",¬
@"2 5 8 2", @"3 4 3 3", @"6 6 2 1", @"6 7 8 9", @"6 1 4 8",¬
@"4 6 9 4", @"9 5 5 9", @"7 5 6 5", @"7 4 9 4", @"8 1 8 6",¬
@"7 1 2 2", @"7 3 4 1", @"7 4 1 1", @"7 8 8 9", @"8 4 2 1",¬
@"4 5 7 9", @"7 3 3 3", @"9 3 2 7", @"2 3 5 3", @"9 7 4 2",¬
@"9 1 8 3", @"9 2 4 3", @"9 4 1 3", @"4 7 8 2", @"1 8 6 2",¬
@"6 1 6 1", @"3 5 6 8", @"1 8 3 1", @"5 7 1 3", @"6 2 3 4",¬
@"5 5 6 1", @"2 6 1 2", @"8 1 2 9", @"4 9 6 1", @"6 4 1 2",¬
@"4 7 3 2", @"5 5 4 9", @"9 2 7 1", @"5 5 6 3", @"6 2 4 2",¬
@"9 4 3 7", @"1 5 7 6", @"5 3 4 7", @"1 1 3 5", @"1 4 5 2",¬
@"1 3 8 2", @"1 5 6 2", @"1 5 8 1", @"2 6 7 1", @"2 3 4 2",¬
@"2 3 6 3", @"2 6 8 2", @"3 4 5 9", @"4 7 8 4", @"3 1 8 4",¬
@"2 8 8 2"]
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
 
short ExtraNumbers:ExtraNumbers = 0
 
for i = 1 to len$(fn stringpascalstring(expr))
if asc(mid$(fn stringpascalstring(expr),i,1)) > 48 && asc(mid$(fn stringpascalstring(expr),i,1)) < 58
ExtraNumbers ++
end if
next i
 
if ExtraNumbers > 4
fn EraseErrorText
text ,,fn colorRed
TryAgain = _true
print %(10,200);"Error! Extra numbers not allowed": goto "InputExpression"
text ,,fn colorWhite
end if
 
 
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}}==
Line 6,146 ⟶ 6,915:
}
</syntaxhighlight>
 
=={{header|jq}}==
'''Works with jq, the C implementation of jq'''
 
'''Works with gojq, the Go implementation of jq'''
 
Note that the RPN evaluator used here allows expressions such as "1 2 3 + +".
 
Note also that in RPN expressions:
* If a and b are numeric, then "a b -" is evaluated to the arithmetic expression `a - b`.
* If a and b are numeric, then "a b /" is evaluated as a/b, which need not be an integer.
 
For the "24 Game":
* Spaces may be omitted in RPN input.
* When comparing a result to 24, `round` is used.
 
The [[:Category:Jq/MRG32k3a.jq | MRG32k3a]] module is used for generating pseudo-random numbers.
<syntaxhighlight lang="jq">
 
### The MRG32k3a combined recursive PRNG - see above
import "MRG32k3a" as MRG {search: "."};
 
### Generic utilities
def sum(stream): reduce stream as $x (0; .+$x);
 
# like while/2 but emit the final term rather than the first one
def whilst(cond; update):
def _whilst:
if cond then update | (., _whilst) else empty end;
_whilst;
 
### Reverse Polish Notation
# An array of the allowed operators
def operators: "+-*/" | split("");
 
# If $a and $b are numbers and $c an operator, then "$a $b $c" is evaluated as an RPN expression.
# Output: {emit, result} with .emit == null if there is a valid result.
def applyOperator($a; $b; $c):
if ([$a,$b] | map(type) | unique) == ["number"]
then
if $c == "+" then {result: ($a + $b)}
elif $c == "-" then {result: ($a - $b)}
elif $c == "*" then {result: ($a * $b)}
elif ($c == "/") then {result: ($b / $a)}
else {emit: "unrecognized operator: \($c)"}
end
else {emit: "invalid number"}
end;
 
# Input: an array representing an RPN expression.
# Output: {emit, result} as per applyOperator/3
# Example: [1,2,3,"+","+"] | evaluate #=> 6
def evaluate:
if length == 1
then if .[0]|type == "number" then {result: .[0]}
else {emit: "invalid RPN expression"}
end
elif length < 3 then {emit: "invalid RPN expression: \(. | join(" "))"}
else . as $in
| (first( range(0; length) as $i | select(any( operators[]; . == $in[$i]) ) | $i) // null) as $ix
| if $ix == null then {emit: "invalid RPN expression"}
else applyOperator(.[$ix-2]; .[$ix-1]; .[$ix]) as $result
| if $result.result then .[:$ix-2] + [$result.result] + .[$ix+1:] | evaluate
else $result
end
end
end;
 
### The "24 Game"
 
# . is the putative RPN string to be checked.
# $four is the string of the four expected digits, in order.
# Output: {emit, result} with .emit set to "Correct!" if .result == 24
def check($four):
if (gsub("[^1-9]";"") | explode | sort | implode) != $four
then {emit: "You must use each of the four digits \($four | split("") | join(" ")) exactly once:"}
else . as $in
| {s: [], emit: null}
| [$in | split("")[] | select(. != " ")
| . as $in | explode[0] | if . >= 48 and . <= 57 then . - 48 else $in end]
| evaluate
| if .result
then if .result|round == 24 then .emit = "Correct!"
else .emit = "Value \(.result) is not 24."
end
else .emit += "\nTry again, or enter . to start again, or q to quit."
end
end ;
 
def run:
# Populate .digits with four non-negative digits selected at random, with replacement:
{digits: (9 | MRG::prn(4) | map(. + 1))}
| (.digits | sort | join("")) as $four
| "At the prompt, enter an RPN string (e.g. 64*1+1-), or . for a new set of four digits, or q to quit.",
"Make 24 using these digits, once each, in any order: \(.digits):",
( whilst( .stop | not;
.emit = null
| . as $state
| try input catch halt
| if IN( "q", "quit") then halt
elif . == "." then $state | .stop = true
else check($four)
| if .result then .stop = true end
end )
| select(.emit).emit ),
# rerun
run;
 
run
</syntaxhighlight>
{{output}}
The following is an illustrative transcript.
<pre>
$ jq -nRr -f 24-game.jq
At the prompt, enter an RPN string (e.g. 64*1+1-), or . for a new set of four digits, or q to quit.
Make 24 using these digits, once each, in any order: [7,7,6,8]:
7768+++
Value 28 is not 24.
At the prompt, enter an RPN string (e.g. 64*1+1-), or . for a new set of four digits, or q to quit.
Make 24 using these digits, once each, in any order: [7,8,6,8]:
.
At the prompt, enter an RPN string (e.g. 64*1+1-), or . for a new set of four digits, or q to quit.
Make 24 using these digits, once each, in any order: [7,2,1,8]:
82*71++
Correct!
At the prompt, enter an RPN string (e.g. 64*1+1-), or . for a new set of four digits, or q to quit.
Make 24 using these digits, once each, in any order: [6,4,2,6]:
q
$
</pre>
 
=={{header|Julia}}==
Line 6,188 ⟶ 7,087:
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}}==
Line 9,833 ⟶ 10,833:
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}}==
Line 11,235 ⟶ 12,262:
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">import os
import rand
import rand.seed
Line 11,315 ⟶ 12,342:
{{libheader|Wren-ioutil}}
{{libheader|Wren-seq}}
<syntaxhighlight lang=ecmascript"wren">import "random" for Random
import "./ioutil" for Input
import "./seq" for Stack
 
var R = Random.new()
Line 11,368 ⟶ 12,395:
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>