blob: 09fa2c13ea923e9a677346962fe5ad5e8c57af09 [file] [log] [blame] [edit]
package TwentyFourGame
/**
* @author yole
*/
import java.util.*
import java.io.*
fun StringBuilder.takeFirst(): Char {
if (this.length() == 0) return 0.toChar()
val c = this.charAt(0)
this.deleteCharAt(0)
return c
}
class Evaluator(val expr: StringBuilder, val numbers: ArrayList<Int>) {
fun checkFirst(expect: Char): Boolean {
if (expr.length() > 0 && expr.charAt(0) == expect) {
expr.deleteCharAt(0)
return true
}
return false
}
fun evaluateArg(): Int {
val c = expr.takeFirst()
when(c) {
in '0'..'9' -> {
val n = c - '0'
val index = numbers.indexOf(n)
if (index < 0) throw Exception("You used incorrect number: " + n)
numbers.remove(index) // gotcha: conflict between remove(Object) and remove(int)
return n
}
'(' -> {
val result = evaluate()
if (expr.takeFirst() != ')') throw Exception(") expected")
return result
}
0.toChar() -> throw Exception("Syntax error: Character expected")
else -> throw Exception("Syntax error: Unrecognized character " + c)
}
}
fun evaluateMult(): Int {
val lhs = evaluateArg()
if (checkFirst('*'))
return lhs * evaluateMult()
if (checkFirst('/'))
return lhs / evaluateMult()
return lhs
}
fun evaluate(): Int {
val lhs = evaluateMult()
if (checkFirst('+'))
return lhs + evaluate()
if (checkFirst('-'))
return lhs - evaluate()
return lhs
}
fun evaluateAll(): Int {
val result = evaluate()
if (expr.length() > 0) throw Exception("unexpected text: " + expr)
return result
}
}
fun main(args: Array<String>) {
println("24 game")
val numbers = ArrayList<Int>(4)
val rnd = Random();
val prompt = StringBuilder()
for(val i in 0..3) {
val n = rnd.nextInt(9) + 1
numbers.add(n)
if (i > 0) prompt.append(" ");
prompt.append(n)
}
println("Your numbers: " + prompt)
println("Enter your expression:")
val reader = BufferedReader(InputStreamReader(System.`in`))
val expr = StringBuilder(reader.readLine())
try {
val result = Evaluator(expr, numbers).evaluateAll()
if (result != 24)
println("Sorry, that's " + result)
else
println("You won!");
}
catch(e: Throwable) {
println(e.getMessage())
}
}