Skip to content

Instantly share code, notes, and snippets.

@volodymyr-korolyov
Last active July 25, 2016 16:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save volodymyr-korolyov/28171ed47d215d4027697dfcb3bb384d to your computer and use it in GitHub Desktop.
Save volodymyr-korolyov/28171ed47d215d4027697dfcb3bb384d to your computer and use it in GitHub Desktop.
/**
* Straightforward Scala implementation
*/
object Postfix {
def main(args: Array[String]): Unit = {
println(eval("0 1 R"))
println(eval("0 0 R"))
println(eval("1 0 A 1 R N N"))
println(eval("0 0 A 0 N 0 N A R"))
println(eval("0 1 A 0 N 1 N A R"))
println(eval("1 0 A 1 N 0 N A R"))
println(eval("1 1 A 1 N 1 N A R"))
println(eval("1 1 A 1 N 1 N A X"))
println(eval("1 1 A 0 N 0 N A X"))
}
def eval(expression: String): Boolean = eval(expression.split(" ").toList, List.empty)
def eval(expressions: List[String], stack: List[Boolean]): Boolean = (expressions, stack) match {
// Nothing to parse, return result
case (Nil, r :: Nil) => r
// Convert numbers to booleans
case ("0" :: rest, restStack) => eval(rest, false :: restStack);
case ("1" :: rest, restStack) => eval(rest, true :: restStack);
// Execute operations
case ("A" :: rest, a :: b :: restStack) => eval(rest, (a && b) :: restStack);
case ("R" :: rest, a :: b :: restStack) => eval(rest, (a || b) :: restStack);
case ("X" :: rest, a :: b :: restStack) => eval(rest, xor(a, b) :: restStack);
case ("N" :: rest, a :: restStack) => eval(rest, (!a) :: restStack);
// Notify about wrong input
case default => throw new RuntimeException(s"Failed to match [$default]");
}
def xor(a: Boolean, b: Boolean) = (a != b)
}
/**
* Separates definition of logical functions from actual parsing.
* Parsing code is harder to read, but it isn't changed when new function is added.
*/
object Postfix2 {
def main(args: Array[String]): Unit = {
println(eval("0 1 R"))
println(eval("0 0 R"))
println(eval("1 0 A 1 R N N"))
println(eval("0 0 A 0 N 0 N A R"))
println(eval("0 1 A 0 N 1 N A R"))
println(eval("1 0 A 1 N 0 N A R"))
println(eval("1 1 A 1 N 1 N A R"))
println(eval("1 1 A 1 N 1 N A X"))
println(eval("1 1 A 0 N 0 N A X"))
}
val functions: Map[String, Any] = Map(
"0" -> (() => false),
"1" -> (() => true),
"A" -> ((a: Boolean, b: Boolean) => a && b),
"R" -> ((a: Boolean, b: Boolean) => a || b),
"X" -> ((a: Boolean, b: Boolean) => xor(a, b)),
"N" -> ((a: Boolean) => !a)
)
def eval(expression: String): Boolean = eval(expression.split(" ").toList, List.empty)
def eval(expressions: List[String], stack: List[Boolean]): Boolean = (expressions, stack) match {
// Nothing to parse, return result
case (Nil, r :: Nil) => r
// Apply function to stack
case (opCode :: rest, restStack) => eval(rest, execute(opCode, restStack))
// Notify about wrong input
case default => throw new RuntimeException(s"Failed to match [$default]");
}
def execute(opCode: String, stack: List[Boolean]): List[Boolean] = (functions(opCode), stack) match {
// Function with no argument
case (f: (() => Boolean), restStack) => f() :: restStack
// Single argument function
case (f: ((Boolean) => Boolean), a :: restStack) => f(a) :: restStack
// 2-argument function
case (f: ((Boolean, Boolean) => Boolean), a :: b :: restStack) => f(a, b) :: restStack
// Function with unexpected signature
case default => throw new RuntimeException(s"Failed to find match for function [$opCode]");
}
def xor(a: Boolean, b: Boolean) = (a != b)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment