RosettaCodeData/Task/24-game/Argile/24-game.argile
2013-04-10 14:23:37 -07:00

110 lines
3.3 KiB
Text

use std, array, list
do
generate random digits
show random digits
let result = parse expression (get input line)
if result != ERROR
if some digits are unused
print "Wrong ! (you didn't use all digits)" ; failure++
else if result == 24.0
print "Correct !" ; success++
else
print "Wrong ! (you got "result")" ; failure++
while play again ?
print "success:"success" failure:"failure" total:"(success+failure) as int
let success = 0, failure = 0.
.: generate random digits :.
our nat seed = 0xc6f31 (: default seed when /dev/urandom doesn't exist :)
let urandom = fopen "/dev/urandom" "r"
if urandom isn't nil
fread &seed size of seed 1 urandom
fclose urandom
Cfunc srandom seed
seed = (Cfunc random) as nat
for each (val int d) from 0 to 3
digits[d] = '1' + (seed % 9)
seed /= 9
let digits be an array of 4 byte
.: show random digits :.
print "Enter an expression that equates to 24 using only all these digits:"
printf "%c , %c , %c , %c\n"(digits[0])(digits[1])(digits[2])(digits[3])
printf "24 = "
.: some digits are unused :. -> bool
for each (val int d) from 0 to 3
return true if digits[d] != '\0'
false
.: get input line :. -> text
our array of 64 byte line
Cfunc fgets (line) (size of line) (stdin)
let int i
for (i = 0) (line[i] != 0) (i++)
line[i] = '\0' if (line[i] == '\n')
line as text
.: play again ? :. -> bool
while true
printf "Play again ? (y/n) " ; Cfunc fflush stdout
let answer = get input line
switch answer[0]
case 'n' {return false}
case 'y' {return true }
default {continue }
false
=: ERROR := -> real {-32202.0}
.: parse expression <text expr> :. -> real
let x = 0.0, x_is_set = false, op = ' '.
let stack be a list of State ; class State {byte op; real x}
for (stack = nil) (*expr != 0) (expr++)
switch *expr
case '+' ; case '-' ; case '*' ; case '/'
error "bad syntax" if not x_is_set
op = *expr
case '1' ; case '2' ; case '3' ; case '4' ; case '5'
case '6' ; case '7' ; case '8' ; case '9'
error "missing operator" if (x_is_set and op == ' ')
error "unavailable digit" unless consume digit expr[0]
do operation with (expr[0] - '0') as real
case (Cgen "'('")
error "missing operator" if (op == ' ' but x_is_set)
(new list (new State) (code of del State())) << stack
op = ' ' ; x_is_set = false (: start fresh state :)
case (Cgen "')'")
error "mismatched parenthesis" if stack is nil
error "wrong syntax" if not x_is_set
let y = x
x = stack.data.x ; op = stack.data.op
delete pop stack
do operation with y
default {error "disallowed character"}
.:new State :. -> State {let s=new(State); s.x=x; s.op=op; s}
.:del State <State s>:. { free s }
.:do operation with <real y>:.
switch op
case '+' {x += y}
case '-' {x -= y}
case '*' {x *= y}
case '/' {x /= y}
default {x = y; x_is_set = true}
op = ' '
=:error<text msg>:= ->real {eprint "Error: "msg" at ["expr"]";return ERROR}
.:consume digit <byte b>:. -> bool
for each (val int d) from 0 to 3
if digits[d] == b
digits[d] = '\0'
return true
false
if stack isn't nil
delete all stack
error "unclosed parenthesis"
return x