RosettaCodeData/Task/24-game/Elena/24-game.elena
2023-12-16 21:33:55 -08:00

208 lines
5.1 KiB
Text

import system'routines;
import system'collections;
import system'dynamic;
import extensions;
// --- Expression ---
class ExpressionTree
{
object _tree;
constructor(s)
{
auto level := new Integer(0);
s.forEach::(ch)
{
var node := new DynamicStruct();
ch =>
$43 { node.Level := level + 1; node.Operation := mssg add } // +
$45 { node.Level := level + 1; node.Operation := mssg subtract } // -
$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
};
if (nil == _tree)
{
_tree := node
}
else
{
if (_tree.Level >= node.Level)
{
node.Left := _tree;
node.Right := nil;
_tree := node
}
else
{
var top := _tree;
while ((nil != top.Right)&&(top.Right.Level < node.Level))
{ top := top.Right };
node.Left := top.Right;
node.Right := nil;
top.Right := node
}
}
}
}
eval(node)
{
if (node.containsProperty(mssg Leaf))
{
^ node.Leaf
}
else
{
var left := self.eval(node.Left);
var right := self.eval(node.Right);
var op := node.Operation;
^ op(left, right);
}
}
get Value()
<= eval(_tree);
readLeaves(list, node)
{
if (nil == node)
{ InvalidArgumentException.raise() };
if (node.containsProperty(mssg Leaf))
{
list.append(node.Leaf)
}
else
{
self.readLeaves(list, node.Left);
self.readLeaves(list, node.Right)
}
}
readLeaves(list)
<= readLeaves(list,_tree);
}
// --- Game ---
class TwentyFourGame
{
object theNumbers;
constructor()
{
self.newPuzzle();
}
newPuzzle()
{
theNumbers := new object[]
{
1 + randomGenerator.nextInt(9),
1 + randomGenerator.nextInt(9),
1 + randomGenerator.nextInt(9),
1 + randomGenerator.nextInt(9)
}
}
help()
{
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(": ")
}
resolve(expr)
{
var tree := new ExpressionTree(expr);
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;
if (result == 24)
{
console.printLine("Good work. ",expr,"=",result);
self.newPuzzle()
}
else
{
console.printLine("Incorrect. ",expr,"=",result)
}
}
}
extension gameOp
{
playRound(expr)
{
if (expr == "q")
{
^ false
}
else
{
if (expr == "")
{
console.printLine("Skipping this puzzle"); self.newPuzzle()
}
else
{
try
{
self.resolve(expr)
}
catch(Exception e)
{
console.printLine(e)
//console.printLine:"An error occurred. Check your input and try again."
}
};
^ true
}
}
}
// --- program ---
public program()
{
var game := new TwentyFourGame().help();
while (game.prompt().playRound(console.readLine())) {}
}