Skip to content

Instantly share code, notes, and snippets.

@rokon12
Created August 29, 2014 19:59
Show Gist options
  • Save rokon12/f7a048d20d1db717e4d6 to your computer and use it in GitHub Desktop.
Save rokon12/f7a048d20d1db717e4d6 to your computer and use it in GitHub Desktop.
Command line scala postfix expression evaluator Input: "1 2 + 3 4 5 - - * 6 7 8 - * /" * Output: (((8 - 7) * 6) / (((5 - 4) - 3) * (2 + 1))) = -1 * */
package calculator
import java.util.Stack
/**
* Created by Bazlur Rahman Rokon on 8/29/14.
*/
object Calculator {
trait Operator {
def operate(lhs: Int, rhs: Int): Int
}
object Operator {
val operators: Map[String, Operator] =
Map("+" -> Add, "-" -> Substract, "*" -> Multiply, "/" -> Divide)
def unapply(token: String): Option[Operator] =
operators.get(token)
}
case object Add extends Operator {
override def operate(lhs: Int, rhs: Int): Int = lhs + rhs
override val toString = "+"
}
case object Substract extends Operator {
override def operate(lhs: Int, rhs: Int): Int = lhs - rhs
override val toString = "-"
}
case object Multiply extends Operator {
override def operate(lhs: Int, rhs: Int): Int = lhs * rhs
override val toString = "*"
}
case object Divide extends Operator {
override def operate(lhs: Int, rhs: Int): Int = lhs / rhs
override val toString = "/"
}
object Number {
def unapply(token: String): Option[Int] = try {
Some(token.toInt)
} catch {
case _: NumberFormatException => None
}
}
sealed trait Expression
case class NumberExpression(value: Int) extends Expression
case class OperationExpression(lhs: Expression, rhs: Expression, op: Operator) extends Expression
def parse(expression: String): Expression = {
val stack: Stack[Expression] = new Stack[Expression]
for (token <- expression.split(" ")) token match {
case Number(num) => stack.push(NumberExpression(num))
case Operator(op) =>
val lsh = stack.pop()
val rhs = stack.pop()
stack.push(OperationExpression(lsh, rhs, op))
case _ => throw new IllegalArgumentException("Invalid token: " + token)
}
stack.pop()
}
def calculate(expression: Expression): Int = expression match {
case NumberExpression(value) => value
case OperationExpression(lhs, rhs, op) => op.operate(calculate(lhs), calculate(rhs))
}
def toInfix(expression: Expression): String = expression match {
case NumberExpression(value) => value.toString
case OperationExpression(lhs, rhs, op) => s"(${toInfix(lhs)} $op ${toInfix(rhs)})"
}
/**
* Command line scala postfix expression evaluator
*
* Input: "1 2 + 3 4 5 - - * 6 7 8 - * /"
* Output: (((8 - 7) * 6) / (((5 - 4) - 3) * (2 + 1))) = -1
*
* @param args
*/
def main(args: Array[String]) {
if (args.length != 1) {
throw new IllegalArgumentException("Usage: Calculator <expression>")
} else {
val expression = parse(args(0))
println(s"${toInfix(expression)} = ${calculate(expression)}")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment