59 lines
1.6 KiB
Plaintext
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
|