How to achieve the expression simplification with distributivity rule in Scala? - scala

I want to write a scala program simplifying this mathematical expression using distributivity rule:
a*b+a*c = a(b+c)
I quickly wrote the following code in order to solve this example:
object Test {
sealed abstract class Expr
case class Var(name: String) extends Expr
case class BinOp(operator: String, left: Expr, right: Expr) extends Expr
def main(args: Array[String]) {
val expr = BinOp("+", BinOp("*", Var("a"), Var("b")), BinOp("*", Var("a"), Var("c")))
println(simplify(expr)) //outputs "a(b + c)"
}
def simplify(expr: Expr) : String = expr match {
case BinOp("+", BinOp("*", Var(x), Var(a)), BinOp("*", Var(y), Var(b))) if (x == y) => "" + x + "*(" + a + " + " + b + ")"
case _ => "" //no matter for the test since I test the first case statically
}
}
Is there a better way to achieve this?
What is the best way to manage the order of operand without duplicating cases for each combination (would be ugly...)? Indeed, what about these expressions:
a*b+a*c = a(b+c)
a*b+c*a = a(b+c)
b*a+a*c = a(b+c)
b*a+c*a = a(b+c)

If Expr keeps commutative law, it must be
def simplify(expr: Expr) : String = expr match {
case expr # BinOp("+", BinOp("*", Var(x), Var(a)), BinOp("*", Var(y), Var(b))) => {
def another(that: String) = {
Seq((x, a), (a, x)) find (_._1 == that) map (_._2)
}
val byY = another(y).map(z => BinOp("+", Var(y), BinOp("*", Var(z), Var(b)))) // combine by y
val byB = another(b).map(z => BinOp("+", Var(b), BinOp("*", Var(z), Var(y)))) // combine by b
(byY orElse byB getOrElse expr).toString
}
case _ => "" //no matter for the test since I test the first case statically
}
byY and byB have the same structure. This is not the best, you maybe reuse some piece of code. :P

Related

Can I avoid using asInstanceOf in a pattern match when matching a stateful subclass object?

As I was modelling expressions like Var("x") or Number(7) and writing an eval function with pattern matching, I ran into a case where I could not avoid using the ´asInstanceOf` method.
2 restrictions
I do not want to avoid pattern matching by declaring an eval method in Expr and define it in its subclasses (cf. Expression problem, I prefer pattern match).
I also do not want something like Var("x", 7).
sealed trait Expr
object Expr {
def eval(e: Expr): Int = e match {
case Number(n) => n
case Var(_) => e.asInstanceOf[Var].getValue()
}
}
case class Number(n: Int) extends Expr
case class Var(s: String) extends Expr {
var value = 0
def getValue(): Int = value
def updateValue(x: Int): Unit = {
this.value = x
}
}
val x = Var("x")
x.updateValue(1)
Expr.eval(x) // 1
When I define the second case like this: case Var(x) => Var(x).getValue(), i get Expr.eval(x) // 0. This is, because Var(x) on the right side will construct a fresh Var with value 0.
I'm ok with using asInstanceOf but in the sense of improvement, I wonder if there is a cleaner solution than using asInstanceOf, which I haven't found yet.
You can use # to bind a variable to a pattern. Use it like this:
def eval(e: Expr): Int = e match {
case Number(n) => n
case v#Var(_) => v.getValue()
}
You can also check the type of a variable in a pattern match
def eval(e: Expr): Int = e match {
case Number(n) => n
case v: Var => v.getValue()
}

Assign value to variable in Scala Parser

i have a question about the Parser in Scala. I'll just post the important part here so that there would not be too much codes. For the eval Function:
def eval(t: Term): Double = t match {
case Addition(l, r) => eval(l) + eval(r)
case Multiplication(l, r) => eval(l) * eval(r)
case Numeric(i) => i
case Variable("X") => 3
}
And the calculate function:
def calculate(arg: String): Double = {
return eval(parseAll(term, arg).get)
}
now i should overload the function "calculate" so that it takes an extra Parameter tup : (String, Double) and assign the value for this String. For example ("Y",2) then Y = 2 in the Parser. And then calculate the parser. But i don't know how to assign the value for this String. I had a stupid idea and tried this but it didn't work.
def calculate(arg: String, tup : (String, Double)) : Double = {
tup match {
case (a,b) => {
def eval(t : Term): Double = t match {
case Variable(a) => b
}
return eval(parseAll(term, arg).get)
}
}
can you guys pls help me out ? Thank you !!
You're almost there, you just need to tell the compiler that the a in your Variable pattern is actually the a from your (a, b) pattern. By default, what you do is called shadowing of the variable name a (in the scope of this pattern match, a is the value extracted in Variable, and the other a is forgotten).
What you want is something like
...
case Variable(`a`) => b
...
or, if your expression gets a little more complicated, you should rather use a guard:
...
case Variable(v) if v == a => b
...
EDIT However, now your eval function is not well defined. You need to put it all at once:
def eval(t: Term, varAssignement: (String, Double)): Double = t match {
case Addition(l, r) => eval(l) + eval(r)
case Multiplication(l, r) => eval(l) * eval(r)
case Numeric(i) => i
case Variable(a) if a == varAssignment._1 => varAssignment._2
}
Or, if you want to have multiple variables:
def eval(t: Term, assignments: Map[String, Double]): Double = t match {
case Addition(l, r) => eval(l) + eval(r)
case Multiplication(l, r) => eval(l) * eval(r)
case Numeric(i) => i
case Variable(a) if assignments.exists(a) => assignments(a)
}
Beware that you'll still get MatchErrors whenever an unassigned variable is used.

Evaluation tree

I am looking to build an evaluation tree, for starters, for arithmetic expressions.
I have the following case classes defined:
abstract class Expr
case class Num(n: Integer) extends Expr
case class Plus(e1: Expr, e2: Expr) extends Expr
My parser, when it sees the expression 1 + 1 + 1 produces the following tree:
Plus(Plus(Num(1), Num(1)), Num(1))
I then have the following data type defined:
case class Tree[Expr](e: Expr, children: List[Tree[Expr]])
Here is a badly drawn evaluation tree:
Num(1) Num(1)
----------------------------
Plus(Num(1), Num(1)) Num(1)
---------------------------------------
Plus(Plus(Num(1),Num(1)), Num(1))
I want to build up a tree data structure representing that. So, the resulting output of evaluation would be:
Tree(
Plus(Plus(Num(1), Num(1)), Num(1)),
List(Tree(Plus(Num(1),Num(1),
List(Tree(Num(1), List()),
Tree(Num(1), List()))),
Tree(Num(1), List())))
I want to have a method eval:
def eval(e: Expr, t: Tree[Expr]): Tree[Expr] = (e, t) match {
// Do the matching on Num
case Num(n) ........ =>
case Plus(e1, e2) ...... =>
}
Is it the right way to represent this evaluation tree and if so, how can I go about creating such a nested tree data structure.
EDIT: Here is a method eval for addition only
def eval(e: Expr): Tree[Expr] = e match {
case Num(n) => Tree(Num(n), Nil)
case Plus(e1, e2) => Tree(Plus(e1, e2), List(eval(e1), eval(e2)))
}
You may have it like this:
def toTree(e: Expr): Tree[Expr] = e match {
case Plus(e1, e2) => Tree(e, List(eval(e1), eval(e2)))
case _ => Tree(e, List())
}
However, you'd better omit Tree as #puhlen suggests. The following method should be enough:
def children(e: Expr): List[Expr] = e match {
case Plus(e1, e2) => List(e1, e2)
case _ => List()
}
Just use it wherever you would use Tree.children

pattern matching, static or dynamic binding

I wanted to know in a pattern matching, like in the following, do we say that the case classes are bound dynamically or statically?
sealed trait Expr
case class Lit(n: Int) extends Expr
case class Add(l: Expr, r: Expr) extends Expr
class Eval {
def eval(e: Expr): Int = e match {
case Lit(n) => n
case Add(l, r) => eval(l) + eval(r)
}
}
class Printo {
def printo(e: Expr): Unit = e match {
case Lit(n) => print(" " + n + " ")
case Add(l, r) => printo(l); print("+"); printo(r)
}
}
//Test
object TestExpr {
def main(args: Array[String]) {
val eval = new Eval
val printo = new Printo
val expr1 =
Add(Add(Lit(4), Add(Lit(7), Lit(10))),
Add(Lit(4), Add(Lit(7), Lit(10))))
val x = eval.eval(expr1)
p + "" + println(" = " + x)
}
}
How I can know if the Lit(n) or Add(l, r) are called / bound statically or dynamically?

Scala Extractor with Argument

Is there a syntax in Scala that allows extractors to take a customization argument? This example is a bit contrived. Suppose I have a binary search tree on integers, and I want to match on the current node if its value is divisible by some custom value.
Using F# active patterns, I can do the following:
type Tree =
| Node of int * Tree * Tree
| Empty
let (|NodeDivisibleBy|_|) x t =
match t with
| Empty -> None
| Node(y, l, r) -> if y % x = 0 then Some((l, r)) else None
let doit = function
| NodeDivisibleBy(2)(l, r) -> printfn "Matched two: %A %A" l r
| NodeDivisibleBy(3)(l, r) -> printfn "Matched three: %A %A" l r
| _ -> printfn "Nada"
[<EntryPoint>]
let main args =
let t10 = Node(10, Node(1, Empty, Empty), Empty)
let t15 = Node(15, Node(1, Empty, Empty), Empty)
doit t10
doit t15
0
In Scala, I can do something similar, but not quite what I want:
sealed trait Tree
case object Empty extends Tree
case class Node(v: Int, l: Tree, r: Tree) extends Tree
object NodeDivisibleBy {
def apply(x: Int) = new {
def unapply(t: Tree) = t match {
case Empty => None
case Node(y, l, r) => if (y % x == 0) Some((l, r)) else None
}
}
}
def doit(t: Tree) {
// I would prefer to not need these two lines.
val NodeDivisibleBy2 = NodeDivisibleBy(2)
val NodeDivisibleBy3 = NodeDivisibleBy(3)
t match {
case NodeDivisibleBy2(l, r) => println("Matched two: " + l + " " + r)
case NodeDivisibleBy3(l, r) => println("Matched three: " + l + " " + r)
case _ => println("Nada")
}
}
val t10 = Node(10, Node(1, Empty, Empty), Empty)
val t15 = Node(15, Node(1, Empty, Empty), Empty)
doit(t10)
doit(t15)
It would be great if I could do:
case NodeDivisibleBy(2)(l, r) => println("Matched two: " + l + " " + r)
case NodeDivisibleBy(3)(l, r) => println("Matched three: " + l + " " + r)
but this is a compile time error: '=>' expected but '(' found.
Thoughts?
From the spec:
SimplePattern ::= StableId ‘(’ [Patterns] ‘)’
An extractor pattern x(p1, ..., pn) where n ≥ 0 is of the same
syntactic form as a constructor pattern. However, instead of a case
class, the stable identifier x denotes an object which has a member
method named unapply or unapplySeq that matches the pattern.
and:
A stable identifier is a path which ends in an identifier.
i.e., not an expression like NodeDivisibleBy(2).
So no, this isn't possible in any straightforward way in Scala, and personally I think that's just fine: having to write the following (which by the way I'd probably define in the NodeDivisibleBy object and import):
val NodeDivisibleBy2 = NodeDivisibleBy(2)
val NodeDivisibleBy3 = NodeDivisibleBy(3)
is a small price to pay for the increased readability of not having to decipher arbitrary expressions in the case clause.
As Travis Brown has noted, it's not really possible in scala.
What I do in that scenario is just separating the decomposition from the test with a guard and an alias.
val DivisibleBy = (n: Node, x: Int) => (n.v % x == 0)
def doit(t: Tree) = t match {
case n # Node(y, l, r) if DivisibleBy(n,2) => println("Matched two: " + l + " " + r)
case n # Node(y, l, r) if DivisibleBy(n,3) => println("Matched three: " + l + " " + r)
case _ => println("Nada")
}
Defining a separate DivisibleBy is obviously complete overkill in this simple case, but may help readability in more complex scenarios in a similar way as F# active patterns do.
You could also define divisibleBy as a method of Node and have:
case class Node(v: Int, l: Tree, r: Tree) extends Tree {
def divisibleBy(o:Int) = (v % o)==0
}
def doit(t: Tree) = t match {
case n # Node(y, l, r) if n divisibleBy 2 => println("Matched two: " + l + " " + r)
case n # Node(y, l, r) if n divisibleBy 3 => println("Matched three: " + l + " " + r)
case _ => println("Nada")
}
which I think is more readable (if more verbose) than the F# version
Bind together the case class, predicate and arguments, then match on the result as usual.
case class Foo(i: Int)
class Testable(val f: Foo, val ds: List[Int])
object Testable {
def apply(f: Foo, ds: List[Int]) = new Testable(f, ds)
def unapply(t: Testable): Option[(Foo, List[Int])] = {
val xs = t.ds filter (t.f.i % _ == 0)
if (xs.nonEmpty) Some((t.f, xs)) else None
}
}
object Test extends App {
val f = Foo(100)
Testable(f, List(3,5,20)) match {
case Testable(f, 3 :: Nil) => println(s"$f matched three")
case Testable(Foo(i), 5 :: Nil) if i < 50
=> println(s"$f matched five")
case Testable(f, ds) => println(s"$f matched ${ds mkString ","}")
case _ => println("Nothing")
}
}
Late answer, but there is a scalac plugin providing syntax ~(extractorWithParam(p), bindings), with all safety from compilation: https://github.com/cchantep/acolyte/tree/master/scalac-plugin#match-component
As I know answer is no.
I also use the previous way for this case.