24 game: Difference between revisions

8,131 bytes added ,  1 month ago
m
(8 intermediate revisions by 5 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,526 ⟶ 4,655:
auto level := new Integer(0);
s.forEach::(ch)
{
var node := new DynamicStruct();
Line 4,535 ⟶ 4,664:
$42 { node.Level := level + 2; node.Operation := mssg multiply } // *
$47 { node.Level := level + 2; node.Operation := mssg divide } // /
$40 { level.append(10); ^ self } // (
$41 { level.reduce(10); ^ self } // )
:! {
node.Leaf := ch.toString().toReal();
node.Level := level + 3
Line 4,625 ⟶ 4,754:
theNumbers := new object[]
{
1 + randomGenerator.nextInt:(9),
1 + randomGenerator.nextInt:(9),
1 + randomGenerator.nextInt:(9),
1 + randomGenerator.nextInt:(9)
}
}
Line 4,635 ⟶ 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,660 ⟶ 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 };
console
.printLine:"Invalid input. Enter an equation using all of those four digits. Try again.";
^ self
};
var result := tree.Value;
Line 4,694 ⟶ 4,820:
if (expr == "")
{
console.printLine:("Skipping this puzzle"); self.newPuzzle()
}
else
Line 4,704 ⟶ 4,830:
catch(Exception e)
{
console.printLine:(e)
//console.printLine:"An error occurred. Check your input and try again."
}
Line 10,259 ⟶ 10,385:
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,741 ⟶ 11,894:
{{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,794 ⟶ 11,947:
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>
1,480

edits