RosettaCodeData/Task/24-game/Icon/24-game.icon

59 lines
1.6 KiB
Plaintext

invocable all
link strings # for csort, deletec
procedure main()
help()
repeat {
every (n := "") ||:= (1 to 4, string(1+?8))
writes("Your four digits are : ")
every writes(!n," ")
write()
e := trim(read()) | fail
case e of {
"q"|"quit": return
"?"|"help": help()
default: {
e := deletec(e,' \t') # no whitespace
d := deletec(e,~&digits) # just digits
if csort(n) ~== csort(d) then # and only the 4 given digits
write("Invalid repsonse.") & next
if e ? (ans := eval(E()), pos(0)) then # parse and evaluate
if ans = 24 then write("Congratulations you win!")
else write("Your answer was ",ans,". Try again.")
else write("Invalid expression.")
}
}
}
end
procedure eval(X) #: return the evaluated AST
if type(X) == "list" then {
x := eval(get(X))
while x := get(X)(real(x), real(eval(get(X) | stop("Malformed expression."))))
}
return \x | X
end
procedure E() #: expression
put(lex := [],T())
while put(lex,tab(any('+-*/'))) do
put(lex,T())
suspend if *lex = 1 then lex[1] else lex # strip useless []
end
procedure T() #: Term
suspend 2(="(", E(), =")") | # parenthesized subexpression, or ...
tab(any(&digits)) # just a value
end
procedure help()
return write(
"Welcome to 24\n\n",
"Combine the 4 given digits to make 24 using only + - * / and ( ).\n ",
"All operations have equal precedence and are evaluated left to right.\n",
"Combining (concatenating) digits is not allowed.\n",
"Enter 'help', 'quit', or an expression.\n")
end