Last active
July 25, 2016 16:57
-
-
Save volodymyr-korolyov/28171ed47d215d4027697dfcb3bb384d to your computer and use it in GitHub Desktop.
Scala solution to https://github.com/functional-kats-cork/boolean-postfix-kata
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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