I wrote an expression simplifier that takes a string as input, converts it into a syntax tree, simplifies that tree, and then finally walks through the tree to convert the output back to a string. I am having a hard time figuring out how to get my parenthesis back into my expression when I am printing a nested solution such as: (a || !b) && c Right now my code gives me a solution of a || !b && c. It seems as though my solution is correct because the simplified tree outputs correctly, I just don't know how to add the parentheses when walking through it.
Here is my code:
import scala.util.parsing.combinator._
import scala.io.StdIn.readLine
abstract class Expression
case class And(l: Expression, r: Expression) extends Expression
case class Or(l: Expression, r: Expression) extends Expression
case class Not(arg: Expression) extends Expression
case class Var(n: Char) extends Expression
case object True extends Expression
case object False extends Expression
object Simplifier extends Combinators {
def eval(e: Expression): Expression = e match {
case Or(True, _) => True
case Or(_, True) => True
case Or(l, False) => l
case Or(False, r) => r
case Or(l, r) => {
val leval = eval(l)
val reval = eval(r)
(leval, reval) match {
case (True, _) => True
case (_, True) => True
case (l, False) => l
case (False, r) => r
case (leval, reval) => Or(eval(l),eval(r))
}
}
case And(True, r) => if(r == True) {return True} else {return r}
case And(l, True) => if(l == True) {return True} else {return l}
case And(False, _) => False
case And(_, False) => False
case And(l, r) => {
val leval = eval(l)
val reval = eval(r)
(leval, reval) match {
case (True, r) => if(r == True) {return True} else {return r}
case (l, True) => if(l == True) {return True} else {return l}
case (False, _) => False
case (_, False) => False
case (leval, reval) => And(eval(l), eval(r))
}
}
case Not(True) => False
case Not(False) => True
case Not(arg) => Not(eval(arg))
case Var(n) => Var(n)
}
def stringify(e: Expression): String = e match{
case Or(l, r) => {
stringify(l) + " || " + stringify(r)
}
case And(l, r) => {
stringify(l) + " && " + stringify(r)
}
case Not(arg) => {
"!" + stringify(arg)
}
case Var(n) => n.toString()
case True => "true"
case False => "false"
}
def main(args:Array[String]): Unit = {
var response: String = ""
do {
println("expression? ")
val input = readLine()
val expr: Expression = parseAll(e, input).get
println(eval(expr))
val simplifiedExpression: String = stringify(eval(expr))
println(simplifiedExpression)
println("Would you like to enter another expression? (y/n): ")
response = readLine()
} while (response != "n")
}
}
class Combinators extends JavaTokenParsers {
def e: Parser[Expression] = t ~ or ~ e ^^ {case l ~ _ ~ r => Or(l, r)} | t
def t: Parser[Expression] = f ~ and ~ t ^^ {case l ~ _ ~ r => And(l, r)} | f
def f: Parser[Expression] = not ~ a ^^ {case _ ~ arg => Not(arg)} | a
def a: Parser[Expression] = openparen ~ e ~ closeparen ^^ {case _ ~ e ~ _ => e} | c
def c: Parser[Expression] = "true" ^^ {case "true" => True} | "false" ^^ {case "false" => False} | z
def z: Parser[Var] = "[a-c]".r ^^ {str => Var(str.head)}
def and[Expression] = "&&"
def or[Expression] = "||"
def not[Expression] = "!"
def openparen[Expression] = "("
def closeparen[Expression] = ")"
}
Your stringify method never puts any parentheses, so that cannot be correct, as you figured out. The easiest improvement would be to always put parentheses instead. For example:
case Or(l, r) => {
"(" + stringify(l) + " || " + stringify(r) + ")"
}
And similarly for the other cases.
Related
I've refactored my code for day 12 of advent of code by using monocle, a lens library in scala.
Is it possible to improve this code :
type Register = String
type Mem = Map[String, Int]
#Lenses
case class State(mem: Mem, pointer: Int)
def processInstruction(instructions: Seq[Instruction]): State => State = { s =>
(instructions(s.pointer) match {
case Inc(r) =>
State.pointer.modify( _ + 1) andThen (State.mem composeLens at(r)).modify(_.map(_ + 1))
case Dec(r) =>
State.pointer.modify( _ + 1) andThen (State.mem composeLens at(r)).modify(_.map(_ - 1))
case CpyInt(v, to) =>
State.pointer.modify( _ + 1) andThen (State.mem composeLens at(to)).set(Some(v))
case CpyReg(from, to) =>
State.pointer.modify( _ + 1) andThen (State.mem composeLens at(to)).set(Some(s.mem(from)))
case Jnz(r, v) => if (r != "1" && s.mem(r) == 0)
State.pointer.modify( _ + 1)
else
State.pointer.modify( _ + v )
}).apply(s)
}
And here is another try, separating the modification of each field
def processInstruction2(instructions: Seq[Instruction]): State => State = { s =>
val ptr = instructions(s.pointer) match {
case Jnz(r, v) if !(r != "1" && s.mem(r) == 0) => State.pointer.modify(_ + v)
case _ => State.pointer.modify(_ + 1)
}
val mem = instructions(s.pointer) match {
case Inc(r) => (State.mem composeLens at(r)).modify(_.map(_ + 1))
case Dec(r) => (State.mem composeLens at(r)).modify(_.map(_ - 1))
case CpyInt(v, to) => (State.mem composeLens at(to)).set(Some(v))
case CpyReg(from, to) => (State.mem composeLens at(to)).set(Some(s.mem(from)))
case _ => identity[State]
}
(ptr andThen mem)(s)
}
One more question : is there a way to use Map.withDefaultValue with monocle ?
The full code is here : https://gist.github.com/YannMoisan/b8ba25afc041d88706545527d9ec1988
You might want to use the second approach, because it separates handling of two fields.
However, the functions shouldn't be interpreted in sequence (andThen), but rather they should be combined as PartialFunctions with orElse.
def processInstruction3(instructions: Seq[Instruction]): State => State = {
val ptr: PartialFunction[Instruction, State => State] = {
case Jnz(r, v) =>
State.pointer.modify(_ + v)
}
val incPointer: State => State = State.pointer.modify( _ + 1)
def reg(r: String): Lens[State, Option[Int]] = State.mem composeLens at(r)
val mem: PartialFunction[Instruction, State => State] = {
case Inc(r) => reg(r).modify(_.orElse(Option(0)).map(_ + 1))
case Dec(r) => reg(r).modify(_.orElse(Option(0)).map(_ - 1))
case CpyInt(v, to) => reg(to).set(Some(v))
case CpyReg(from, to) => s => reg(to).set(reg(from).get(s))(s)
}
val interpreter = ptr orElse (mem andThen (_ andThen incPointer))
s => instructions.foldLeft(s)((s, i) => interpreter(i)(s))
}
UPDATE (after the Yann Moisan comment)
The execution may not terminate in case of infinite loop in user's program. So instead of the foldLeft we need some recursive function that will extract the next instruction by pointer:
#tailrec
def loop(s: State): State = {
if(s.pointer>=instructions.length)
s
else {
val instruction = instructions(s.pointer)
val nextState = interpreter(instruction)(s)
loop(nextState)
}
}
loop _
(The last line of processInstruction3 should be replaced with the above code)
I have a case class that has multiple parameters of which some are Options. Here is a simplified example:
case class Foobar(a: String, b: Option[String], c: Option[CustomClass])
I want to be able to match cases of Foobar where b and/or c is not None. For example, one case could be:
testResult match {
case Foobar("str1", Some(_), None) => "good"
case Foobar("str2", None, Some(_)) => "ok"
case _ => "bad"
}
Furthermore, I want to reference the case patterns via variables and this is where I'm stuck. I want to do something like the following:
val goodPat = Foobar("str1", Some(_), None) // compile fail
val okPat = Foobar("str2", None, Some(_)) // compile fail
testResult match {
case `goodPat` => "good"
case `okPat` => "ok"
case _ => "bad"
}
Is something like this possible? Is there another way to specify "not None"? Is there another way to approach this problem?
EDIT: I'm adding more details and context to the question. I have a large List of 2-tuples representing unit tests for a particular function. The 2-tuples represent the input and expected output. Eg.
// imagine this list is much bigger and Foobar contains more Option parameters
val tests = List(
("test1", Foobar("idkfa", None, None)),
// I know these fail to compile but I need to do something like this
("test2", Foobar("idclip", Some("baz"), Some(_)),
("test3", Foobar("iddqd", Some(_), None)
)
tests.foreach(test => {
val (input, expected) = test
myFunction(input) match {
case `expected` => println("ok")
case _ => println("bad")
}
})
I think you seeking for something like this:
case class DoomOpt(s: String)
case class Foobar(a: String, b: Option[String], c: Option[DoomOpt])
def myFunction(s: String): Foobar = { // your code here }
val tests = Map[String, PartialFunction[Foobar, Unit]](
"idkfa" → { case Foobar("idkfa", None, None) ⇒ },
"test2" → { case Foobar("idclip", Some("baz"), Some(_)) ⇒ },
"test3" → { case Foobar("iddqd", Some(_), None) ⇒ },
"idspispopd" → { case Foobar("idspispopd", Some(_), None) ⇒ }
)
tests.foreach { case (input, checker) =>
if (checker.isDefinedAt(myFunction(input)))
println("ok")
else
println("bad")
}
Pattern matching uses extractors which provide the unapply function to deconstruct the object. So... you can just supply your custom extractor in this case. Create a list of these extractor test cases and apply them one by one.
case class Foobar(s: String, o: Option[Int])
trait TestExtractor {
def unapply(fbar: Foobar): Boolean
}
object somePatExtractor extends TestExtractor {
def unapply(fbar: Foobar): Boolean = fbar match {
case Foobar("yes", Some(_)) => true
case _ => false
}
}
object nonePatExtractor extends TestExtractor {
def unapply(fbar: Foobar): Boolean = fbar match {
case Foobar("yes", None) => true
case _ => false
}
}
object bazPatExtractor extends TestExtractor {
def unapply(fbar: Foobar): Boolean = fbar match {
case Foobar("yes", Some("baz")) => true
case _ => false
}
}
val testList: List[(String, TestExtractor)] = List(("test1", nonePatExtractor), ("test2", bazPatExtractor), ("test3", somePatExtractor))
val fooToTest = Foobar("yes", Some(5))
testList.foreach({
case (testName, extractor) => {
fooToTest match {
case pat # extractor() => println("testName :: " + testName + ", Result :: ok")
case _ => println("testName :: " + testName + ", Result :: bad")
}
}
})
And if you are looking for a more extendible approach then you can consider something like following,
case class Foobar(s: String, o1: Option[Int], o2: Option[String])
case class TestCondition(df: Foobar => Boolean) {
def test(foobar: Foobar): Boolean = df(foobar)
}
val o1IsNone = TestCondition(f => f.o1.isEmpty)
val o1IsSome = TestCondition(f => f.o1.isDefined)
val o2IsNone = TestCondition(f => f.o2.isEmpty)
val o2IsSome = TestCondition(f => f.o2.isDefined)
case class TestCase(tcs: List[TestCondition]) {
def test(foobar: Foobar) = tcs.foldLeft(true)({ case (acc, tc) => acc && tc.test(foobar) })
}
val testList = List[(String, TestCase)](
("test1", TestCase(List(o1IsSome, o2IsSome))),
("test2", TestCase(List(o1IsSome, o2IsNone))),
("test3", TestCase(List(o1IsNone, o2IsSome))),
("test4", TestCase(List(o1IsNone, o2IsNone)))
)
val foobarToTest = Foobar("yes", Some(5), None)
testList.foreach({
case (testName, testCase) => {
foobarToTest match {
case foobar: Foobar if testCase.test(foobar) => println("testName :: " + testName + ", Result :: ok")
case _ => println("testName :: " + testName + ", Result :: bad")
}
}
})
Using the following code, I can compare a value from a key in a map with a value.
e.g"column1 > 2" will compare map("column1")>2 and result is true or false based on the map. But how to process a list of such map? I have a table in a database, so I will get a list of row, each row could be represented as a map, and then I need to process each row, and print whether the row match a condition. I knew that could be done in sql easily, but I'd like to know how this can be done in scala.
package test
import scala.util.parsing.combinator.syntactical._
object BookParse extends StandardTokenParsers {
val lookup=Map[String,Double]("column1"->1,"column2"->2)
lexical.delimiters ++= List(">","<",">=","!=","<>","<=","=")
def value[double] = numericLit ^^ { s => s.toDouble }
def columnValue[double]=ident ^^ {s=>lookup(s)}
def condition=(columnValue|value)~(">"|"<"|"<="|">="|"<>"|"!="|"=")~(columnValue|value) ^^ {
case left ~x ~ right=>{
x match {
case ">" =>if (left > right) println("true") else println("false")
case "<" =>if (left < right) println("true") else println("false")
case "<>"=>if (left != right) println("true") else println("false")
case "!="=>if (left != right) println("true") else println("false")
case ">="=>if (left >= right) println("true") else println("false")
case "<="=>if (left <= right) println("true") else println("false")
case "="=> if (left == right) println("true") else println("false")
}
}
}
def parse(s: String) = {
val tokens = new lexical.Scanner(s)
phrase(condition)(tokens)
}
def test(extrString: String) = {
parse(extrString) match {
case Success(_,_) => println("done")
case Failure(msg, _) => println("Failure: " + msg)
case Error(msg, _) => println("Error: " + msg)
}
}
def main(args: Array[String]) {
test("column1 > 2")
}
}
One slightly nicer way to do this would be to have the parsers return "expressions" that can be evaluated in the context of a map (instead of relying on side effects inside the parser).
import scala.util.parsing.combinator.syntactical._
object BookParse extends StandardTokenParsers {
lexical.delimiters ++= List(">", "<", ">=", "!=", "<>", "<=", "=")
val value: Parser[Map[String, Double] => Double] =
numericLit ^^ (v => _ => v.toDouble)
val columnValue: Parser[Map[String, Double] => Double] =
ident ^^ (name => env => env(name))
val condition: Parser[Map[String, Double] => Boolean] =
(columnValue | value) ~
(">" | "<" | "<=" | ">=" | "<>" | "!=" | "=") ~
(columnValue | value) ^^ {
case left ~ ">" ~ right => env => left(env) > right(env)
case left ~ "<" ~ right => env => left(env) < right(env)
case left ~ "<>" ~ right => env => left(env) != right(env)
case left ~ "!=" ~ right => env => left(env) != right(env)
case left ~ ">=" ~ right => env => left(env) >= right(env)
case left ~ "<=" ~ right => env => left(env) <= right(env)
case left ~ "=" ~ right => env => left(env) == right(env)
}
def parse(s: String) = {
val tokens = new lexical.Scanner(s)
phrase(condition)(tokens)
}
}
Now if you've got some example data:
val rows: List[Map[String, Double]] = List(
Map("column1" -> 1, "column2" -> 2),
Map("column1" -> 3, "column2" -> 3)
)
You can write the following:
scala> val myCond = BookParse.parse("column1 > 2").get
myCond: Map[String,Double] => Boolean = <function1>
scala> rows.filter(myCond)
res0: List[Map[String,Double]] = List(Map(column1 -> 3.0))
(Note that there are several ways you could improve the error handling here.)
I have multiple Option's. I want to check if they hold a value. If an Option is None, I want to reply to user about this. Else proceed.
This is what I have done:
val name:Option[String]
val email:Option[String]
val pass:Option[String]
val i = List(name,email,pass).find(x => x match{
case None => true
case _ => false
})
i match{
case Some(x) => Ok("Bad Request")
case None => {
//move forward
}
}
Above I can replace find with contains, but this is a very dirty way. How can I make it elegant and monadic?
Edit: I would also like to know what element was None.
Another way is as a for-comprehension:
val outcome = for {
nm <- name
em <- email
pwd <- pass
result = doSomething(nm, em, pwd) // where def doSomething(name: String, email: String, password: String): ResultType = ???
} yield (result)
This will generate outcome as a Some(result), which you can interrogate in various ways (all the methods available to the collections classes: map, filter, foreach, etc.). Eg:
outcome.map(Ok(result)).orElse(Ok("Bad Request"))
val ok = Seq(name, email, pass).forall(_.isDefined)
If you want to reuse the code, you can do
def allFieldValueProvided(fields: Option[_]*): Boolean = fields.forall(_.isDefined)
If you want to know all the missing values then you can find all missing values and if there is none, then you are good to go.
def findMissingValues(v: (String, Option[_])*) = v.collect {
case (name, None) => name
}
val missingValues = findMissingValues(("name1", option1), ("name2", option2), ...)
if(missingValues.isEmpty) {
Ok(...)
} else {
BadRequest("Missing values for " + missingValues.mkString(", ")))
}
val response = for {
n <- name
e <- email
p <- pass
} yield {
/* do something with n, e, p */
}
response getOrElse { /* bad request /* }
Or, with Scalaz:
val response = (name |#| email |#| pass) { (n, e, p) =>
/* do something with n, e, p */
}
response getOrElse { /* bad request /* }
if ((name :: email :: pass :: Nil) forall(!_.isEmpty)) {
} else {
// bad request
}
I think the most straightforward way would be this:
(name,email,pass) match {
case ((Some(name), Some(email), Some(pass)) => // proceed
case _ => // Bad request
}
A version with stone knives and bear skins:
import util._
object Test extends App {
val zero: Either[List[Int], Tuple3[String,String,String]] = Right((null,null,null))
def verify(fields: List[Option[String]]) = {
(zero /: fields.zipWithIndex) { (acc, v) => v match {
case (Some(s), i) => acc match {
case Left(_) => acc
case Right(t) =>
val u = i match {
case 0 => t copy (_1 = s)
case 1 => t copy (_2 = s)
case 2 => t copy (_3 = s)
}
Right(u)
}
case (None, i) =>
val fails = acc match {
case Left(f) => f
case Right(_) => Nil
}
Left(i :: fails)
}
}
}
def consume(name: String, email: String, pass: String) = Console println s"$name/$email/$pass"
def fail(is: List[Int]) = is map List("name","email","pass") foreach (Console println "Missing: " + _)
val name:Option[String] = Some("Bob")
val email:Option[String]= None
val pass:Option[String] = Some("boB")
val res = verify(List(name,email,pass))
res.fold(fail, (consume _).tupled)
val res2 = verify(List(name, Some("bob#bob.org"),pass))
res2.fold(fail, (consume _).tupled)
}
The same thing, using reflection to generalize the tuple copy.
The downside is that you must tell it what tuple to expect back. In this form, reflection is like one of those Stone Age advances that were so magical they trended on twitter for ten thousand years.
def verify[A <: Product](fields: List[Option[String]]) = {
import scala.reflect.runtime._
import universe._
val MaxTupleArity = 22
def tuple = {
require (fields.length <= MaxTupleArity)
val n = fields.length
val tupleN = typeOf[Tuple2[_,_]].typeSymbol.owner.typeSignature member TypeName(s"Tuple$n")
val init = tupleN.typeSignature member nme.CONSTRUCTOR
val ctor = currentMirror reflectClass tupleN.asClass reflectConstructor init.asMethod
val vs = Seq.fill(n)(null.asInstanceOf[String])
ctor(vs: _*).asInstanceOf[Product]
}
def zero: Either[List[Int], Product] = Right(tuple)
def nextProduct(p: Product, i: Int, s: String) = {
val im = currentMirror reflect p
val ts = im.symbol.typeSignature
val copy = (ts member TermName("copy")).asMethod
val args = copy.paramss.flatten map { x =>
val name = TermName(s"_$i")
if (x.name == name) s
else (im reflectMethod (ts member x.name).asMethod)()
}
(im reflectMethod copy)(args: _*).asInstanceOf[Product]
}
(zero /: fields.zipWithIndex) { (acc, v) => v match {
case (Some(s), i) => acc match {
case Left(_) => acc
case Right(t) => Right(nextProduct(t, i + 1, s))
}
case (None, i) =>
val fails = acc match {
case Left(f) => f
case Right(_) => Nil
}
Left(i :: fails)
}
}.asInstanceOf[Either[List[Int], A]]
}
def consume(name: String, email: String, pass: String) = Console println s"$name/$email/$pass"
def fail(is: List[Int]) = is map List("name","email","pass") foreach (Console println "Missing: " + _)
val name:Option[String] = Some("Bob")
val email:Option[String]= None
val pass:Option[String] = Some("boB")
type T3 = Tuple3[String,String,String]
val res = verify[T3](List(name,email,pass))
res.fold(fail, (consume _).tupled)
val res2 = verify[T3](List(name, Some("bob#bob.org"),pass))
res2.fold(fail, (consume _).tupled)
I know this doesn't scale well, but would this suffice?
(name, email, pass) match {
case (None, _, _) => "name"
case (_, None, _) => "email"
case (_, _, None) => "pass"
case _ => "Nothing to see here"
}
I have such case classes:
abstract class Tree
case class Sum(l: Tree, r: Tree) extends Tree
case class Var(n: String) extends Tree
case class Const(v: Int) extends Tree
Now i write such object :
object Main {
type Environment = String => Int
def derive(t: Tree, v: String): Tree = t match {
case Sum(l, r) => Sum(derive(l, v), derive(r, v))
case Var(n) if (v == n) => Const(1)
case _ => Const(0)
}
def eval(t: Tree, env: Environment): Int = t match {
case Sum(l, r) => eval(l, env) + eval(r, env)
case Var(n) => env(n)
case Const(v) => v
}
def simple(t: Tree): Const = t match {
case Sum(l, r) if (l.isInstanceOf[Const] && r.isInstanceOf[Const]) => Const(l.asInstanceOf[Const].v + r.asInstanceOf[Const].v)
case Sum(l, r) if (l.isInstanceOf[Sum] && r.isInstanceOf[Sum]) => Const(simple(l).v+ simple(r).v)
case Sum(l, r) if (l.isInstanceOf[Sum]) => Const(simple(l).v + r.asInstanceOf[Const].v)
case Sum(l, r) if (r.isInstanceOf[Sum]) => Const(simple(r).v + l.asInstanceOf[Const].v)
}
def main(args: Array[String]) {
val exp: Tree = Sum(Sum(Var("x"), Var("x")), Sum(Const(7), Var("y")))
val env: Environment = {
case "x" => 5
case "y" => 7
}
println("Expression: " + exp)
println("Evaluation with x=5, y=7: " + eval(exp, env))
println("Derivative relative to x:\n " + derive(exp, "x"))
println("Derivative relative to y:\n " + derive(exp, "y"))
println("Simplified expression:\n" + simple(derive(exp, "x")))
}
}
I am new in scala. Is it possible write method simple with small count of code and maybe in scala way?
Thanks for advice.
You're almost there. In Scala, extractors can be nested:
def simple(t: Tree): Const = t match {
case Sum(Const(v1), Const(v2)) => Const(v1 + v2)
case Sum(s1 # Sum(_,_), s2 # Sum(_, _)) => Const(simple(s1).v+ simple(s2).v)
case Sum(s # Sum(_, _), Const(v)) => Const(simple(s).v + v)
case Sum(Const(v), s # Sum(_, _)) => Const(simple(s).v + v)
}
Of course, this will give you some warnings about incomplete matches, and the sx # Sum(_, _) repeatedly suggests that there may be a better approach that includes matching on Const and Var at the root level and making more recursive calls to simple.
Although this question has been closed, but I think this version should be a better one,
def simplify(t: Tree): Tree = t match {
case Sum(Const(v1), Const(v2)) => Const(v1 + v2)
case Sum(Const(v1), Sum(Const(v2), rr)) => simplify(Sum(Const(v1 + v2), simplify(rr)))
case Sum(l, Const(v)) => simplify(Sum(Const(v), simplify(l)))
case Sum(l, Sum(Const(v), rr)) => simplify(Sum(Const(v), simplify(Sum(l, rr))))
case Sum(Sum(ll, lr), r) => simplify(Sum(ll, simplify(Sum(lr, r))))
case Sum(Var(n), r) => Sum(simplify(r), Var(n))
case _ => t
}
it seems works with "complex" expressions with variables.
Just a small improvement:
def derive(t: Tree, v: String): Tree = t match {
case Sum(l, r) => Sum(derive(l, v), derive(r, v))
case Var(`v`) => Const(1)
case _ => Const(0)
}
How about this:
def simplify(t: Tree): Tree = t match {
case Sum(Const(v1),Const(v2)) => Const(v1+v2)
case Sum(left,right) => simplify(Sum(simplify(left),simplify(right)))
case _ => t //Not necessary, but for completeness
}
Note that it returns a Tree, not a Const, so it should be able to simplify trees with variables too.
I'm learning Scala so any suggestions as to why this wouldn't work etc. are more than welcome :-)
EDIT: Just discovered that the second case causes an infinite loop when using variables. Substitute it with:
case Sum(left,right) => Sum(simplify(left),simplify(right))
Unfortunately this breaks when left and right return Const, which could be simplified even further (e.g. Sum(Const(2),Const(3))).