scala coding to do the Huffman decoding, but wrong result - scala

abstract class CodeTree
case class Fork(left: CodeTree, right: CodeTree, chars: List[Char], weight: Int) extends CodeTree
case class Leaf(char: Char, weight: Int) extends CodeTree
type Bit = Int
def decode(tree: CodeTree, bits: List[Bit]): List[Char] = {
if(!bits.isEmpty) {
bits.head match {
case 0 => tree match {
case Fork(l, r, _, _) => decode(l, bits.tail)
case Leaf(_, _) => chars(tree) ::: decode(frenchCode, bits.tail)
}
case 1 => tree match {
case Fork(l, r, _, _) => decode(r, bits.tail)
case Leaf(_, _) => chars(tree) ::: decode(frenchCode, bits.tail)
}
}
}
else Nil
}
val frenchCode: CodeTree = Fork(Fork(Fork(Leaf('s',121895),Fork(Leaf('d',56269),Fork(Fork(Fork(Leaf('x',5928),Leaf('j',8351),List('x','j'),14279),Leaf('f',16351),List('x','j','f'),30630),Fork(Fork(Fork(Fork(Leaf('z',2093),Fork(Leaf('k',745),Leaf('w',1747),List('k','w'),2492),List('z','k','w'),4585),Leaf('y',4725),List('z','k','w','y'),9310),Leaf('h',11298),List('z','k','w','y','h'),20608),Leaf('q',20889),List('z','k','w','y','h','q'),41497),List('x','j','f','z','k','w','y','h','q'),72127),List('d','x','j','f','z','k','w','y','h','q'),128396),List('s','d','x','j','f','z','k','w','y','h','q'),250291),Fork(Fork(Leaf('o',82762),Leaf('l',83668),List('o','l'),166430),Fork(Fork(Leaf('m',45521),Leaf('p',46335),List('m','p'),91856),Leaf('u',96785),List('m','p','u'),188641),List('o','l','m','p','u'),355071),List('s','d','x','j','f','z','k','w','y','h','q','o','l','m','p','u'),605362),Fork(Fork(Fork(Leaf('r',100500),Fork(Leaf('c',50003),Fork(Leaf('v',24975),Fork(Leaf('g',13288),Leaf('b',13822),List('g','b'),27110),List('v','g','b'),52085),List('c','v','g','b'),102088),List('r','c','v','g','b'),202588),Fork(Leaf('n',108812),Leaf('t',111103),List('n','t'),219915),List('r','c','v','g','b','n','t'),422503),Fork(Leaf('e',225947),Fork(Leaf('i',115465),Leaf('a',117110),List('i','a'),232575),List('e','i','a'),458522),List('r','c','v','g','b','n','t','e','i','a'),881025),List('s','d','x','j','f','z','k','w','y','h','q','o','l','m','p','u','r','c','v','g','b','n','t','e','i','a'),1486387)
val secret: List[Bit] = List(0,0,1,1,1,0,1,0,1,1,1,0,0,1,1,0,1,0,0,1,1,0,1,0,1,1,0,0,1,1,1,1,1,0,1,0,1,1,0,0,0,0,1,0,1,1,1,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,1)
def decodedSecret: List[Char] = decode(frenchCode, secret)ode here
I am new to scala, and learning the pattern matching now, I want to do the huffman decoding, now I could get a list, but it is the wrong answer, hope someone could find the mistake.

There are several issues with your code.
You do not want to consume a bit when you hit a leaf. A character of the leaf should also be added if there is no bit in your code.
In the decode methode you do not want to reference frenchCode, but code instead that is given as a parameter.
You can access the char of the leaf via pattern matching, i.e. case Leaf(codeChar, _) => ...
Btw. your code will be way cleaner if you start matching on the tree. Only if it matches to a fork you look at the head of your bit list.
Hope that helps. ;)

Related

Scala order implicit conversions?

I have some problem in scala order implicit, can someone help me?
Below are some classes definition, and what I want to do is to compare Leaf and Node through it's 'popularity'.
class Tree
case class EmptyTree() extends Tree
case class Leaf(label: String, popularity: Double) extends Tree
case class Node(popularity: Double, left: Tree, right: Tree) extends Tree
for exampel:
val a = Leaf("a",10)
val b = Leaf("b",20)
val c = Node(30,a,b)
if we want to compare a and b through it's popularity, it is easy to do by adding the implicit transformations, like that:
implicit val leavesOrder = new Ordering[Leaf] {
override def compare(x: Leaf, y: Leaf) =
implicitly[Ordering[Double]].compare(x.popularity, y.popularity)
}
but if I want to compare a and c through it's popularity, I am confused about it and don't konw how to add the implicit transformations?
Can someone help me?
You can create an implicit Ordering for Tree if you want to compare Leafs and Nodes.
Here's some (incomplete) code, on how you could do that:
implicit val treeOrder = new Ordering[Tree] {
override def compare(x: Tree, y: Tree) = (x,y) match {
case (Leaf(_,xP), Leaf(_,yP)) => xP compare yP
case (Node(xP,_,_), Leaf(_,yP)) => xP compare yP
case (Node(xP,_,_), Node(yP,_,_)) => xP compare yP
case (EmptyTree(), _) => -1
/* Add the rest of the cases here */
}
}
Bonus points for changing Tree to be a sealed trait, so that the compiler can tell you when your pattern matching is incomplete :)
Id do something like this. Change your Tree class to a sealed trait this means the pattern matching is exhaustive so the compiler can tell you if your missing something. Then you need to match on each of the types that a Tree can be. Not all of them have a popularity.
sealed trait Tree
case object EmptyTree extends Tree
case class Leaf(label: String, popularity: Double) extends Tree
case class Node(popularity: Double, left: Tree, right: Tree) extends Tree
implicit val treeOrdering = new Ordering[Tree] {
private val doubleOrdering = implicitly[Ordering[Double]]
def compare(a: Tree, b: Tree): Int = {
(a, b) match {
case (Node(p1, _, _), Node(p2, _, _)) => doubleOrdering.compare(p1, p2)
case (Leaf(_, p1), Node(p2, _, _)) => doubleOrdering.compare(p1, p2)
case (Node(p1, _, _), Leaf(_, p2)) => doubleOrdering.compare(p1, p2)
case (Leaf(_, p1), Leaf(_, p2)) => doubleOrdering.compare(p1, p2)
case (EmptyTree, _) => -1
case (_, EmptyTree) => 1
}
}
}

Scala: How to compute the sum of all elements in the leaves of a Binary Tree?

I'm learning Scala by working the exercises from the book "Scala for the Impatient". Given the following way to model binary trees with case classes, one question asks to compute the sum of all elements in the leaves.
sealed abstract class BinaryTree
case class Leaf(value: Int) extends BinaryTree
case class Node(left: BinaryTree, right: BinaryTree) extends BinaryTree
My solution is as follows and works as expected. However, I'm using a MutableList and because Scala favors immutability, I am wondering if there's a way to solve the problem using List?
def leafSum(tree: BinaryTree): Int = {
collectLeaves(tree) { MutableList[Int]() }.sum
}
private def collectLeaves(tree: BinaryTree)(leaves: MutableList[Int]): MutableList[Int] = tree match {
case Node(left, right) =>
collectLeaves(left)(leaves); collectLeaves(right)(leaves)
case Leaf(value) => leaves += value
}
Using a List is not a good idea for the reason that when you concatenate two lists, you will have to copy their content so an O(n) complexity operation each time you encounter a Node.
If you really want to do it with Lists, you could do it like this:
def leafSum(tree: BinaryTree): Int = {
collectLeaves(tree).sum
}
private def collectLeaves(tree: BinaryTree): List[Int] = tree match {
case Node(left, right) => collectLeaves(left) ::: collectLeaves(right)
case Leaf(value) => List(value)
}
although in my opinion it's better to compute directly the sum as you don't need to store the values in the leaves:
def sum(tree: BinaryTree): Int = tree match {
case Node(left, right) => sum(left) + sum(right)
case Leaf(value) => value
}
Here's a recursive approach that doesn't use a helper method that I think is fairly elegant. Note it's not tail recursive and will run out of memory for large inputs.
def leafSum(tree: BinaryTree): Int = tree match{
case leaf:Leaf => leaf.value
case node:Node => leafSum(node.left) + leafSum(node.right)
}

Extracting members of a collection based on the contained type when the member is covariant on that type

I have a case class covariant on the type of one of its member variables, which is constrained to be of a particular type:
case class MyCount[+T <: Identifier](
id: T,
count: Long,
)
Identifier is a sealed trait with two concrete implementations though I don't believe that this matters for the question:
sealed trait Identifier
case class IdentifierFoo(...) implements Identifier
case class IdentifierBar(...) implements Identifier
Given a collection of MyCount[Identifier] I want to:
Extract all MyCount[IdentifierFoo]
Have the resulting collection have a type SomeCollection[MyCount[IdentifierFoo]]
The obvious (to me) way of doing it would be as follows:
src.collect { case countFoo: MyCount[IdentifierFoo] => countFoo }
However, this fails because the type of Count cannot be checked accurately at runtime due to type erasure: the result (incorrectly) gets all Counts. I've ended up doing something quite hairy looking:
src.collect { count =>
count.id match { case IdentifierFoo => {
count match {case countFoo: MyCount[IdentifierFoo] => countFoo }
} } }
This works but is ugly. I also tried matching the entire count as follows:
src.collect { case countFoo: MyCount[IdentifierFoo](_: IdentifierFoo, _) => countFoo }
...but this seems to not be valid in Scala 2.10, which is what I am constrained to. Is there a better way of doing what I want to do?
As #m-z mentions, you're better of matching on the structure than the types, but if you want the result to be of type List[MyCount[IdentifierFoo]], you have to cast the values:
val list: List[MyCount[Identifier]] = List(MyCount(IdentifierFoo(1), 2), MyCount(IdentifierBar(2), 3), MyCount(IdentifierBar(3), 4))
list.collect{ case countFoo # MyCount(_ : IdentifierFoo,_) => countFoo.asInstanceOf[MyCount[IdentifierFoo]]}
res0: List[MyCount[IdentifierFoo]] = List(MyCount(IdentifierFoo(1),2))
list.collect{ case countFoo # MyCount(_ : IdentifierBar,_) => countFoo.asInstanceOf[MyCount[IdentifierBar]]}
res1: List[MyCount[IdentifierBar]] = List(MyCount(IdentifierBar(2),3), MyCount(IdentifierBar(3),4))
Since you have extractors for IdentifierFoo and IdentifierBar and know their structure, you can use them. By using extractors, you aren't matching solely on the type, so we get around type erasure.
list.collect { case countFoo # MyCount(IdentifierFoo(_), _) => countFoo }
eg:
sealed trait Identifier
case class IdentifierFoo(id: Int) extends Identifier
case class IdentifierBar(id: Int) extends Identifier
case class MyCount[+T <: Identifier](id: T, count: Long)
val list = List(MyCount(IdentifierFoo(1), 2), MyCount(IdentifierBar(2), 3), MyCount(IdentifierBar(3), 4))
scala> list.collect { case countFoo # MyCount(IdentifierFoo(_), _) => countFoo }
res142: List[MyCount[Product with Serializable with Identifier]] = List(MyCount(IdentifierFoo(1),2))
scala> list.collect { case countFoo # MyCount(IdentifierBar(_), _) => countFoo }
res143: List[MyCount[Product with Serializable with Identifier]] = List(MyCount(IdentifierBar(2),3), MyCount(IdentifierBar(3),4))

Folding on case classes

I have a situation where I have a couple of case classes where all of their variables are optional.
Let's say I have:
case class Size(width: Option[Int], height: Option[Int])
case class Foo(a: Option[String], b: Option[Boolean], c: Option[Char])
Given a collection of the same type of case class I would like to fold over them comparing the option values and keep the values which are defined. I.e. for Size:
values.foldLeft(x) { (a, b) =>
Size(a.width.orElse(b.width), a.height.orElse(b.height))
}
I would like to do this in a more general way for any of the case classes like the ones above. I'm thinking about doing something with unapply(_).get etc. Does anyone know a smart way to solve this?
Ok, consider this:
def foldCase[C,T1](unapply: C => Option[Option[T1]], apply: Option[T1] => C)
(coll: Seq[C]): C = {
coll.tail.foldLeft(coll.head) { case (current, next) =>
apply(unapply(current).get orElse unapply(next).get)
}
}
case class Person(name: Option[String])
foldCase(Person.unapply, Person.apply)(List(Person(None), Person(Some("Joe")), Person(Some("Mary"))))
One could overload foldCase to accept two, three, or more parameters, one version of f for each arity. It could then be used with any case class. Since there's the tuple-thing to worry about, below's one way to make it work with case classes or two parameters. Expanding it to more parameters is then trivial, though a bit tiresome.
def foldCase[C,T1,T2](unapply: C => Option[(Option[T1], Option[T2])], apply: (Option[T1], Option[T2]) => C)
(coll: Seq[C]): C = {
def thisOrElse(current: (Option[T1], Option[T2]), next: (Option[T1], Option[T2])) =
apply(current._1 orElse next._1, current._2 orElse next._2)
coll.tail.foldLeft(coll.head) { case (current, next) =>
thisOrElse(unapply(current).get, unapply(next).get)
}
}
val list = Person(None, None) :: Person(Some("Joe"), None) :: Person(None, Some(20)) :: Person(Some("Mary"), Some(25)) :: Nil
def foldPerson = foldCase(Person.unapply, Person.apply) _
foldPerson(list)
To use it overloaded, just put all definitions inside one object:
object Folder {
def foldCase[C,T1](unapply: C => Option[Option[T1]], apply: Option[T1] => C)
(coll: Seq[C]): C = {
coll.tail.foldLeft(coll.head) { case (current, next) =>
apply(unapply(current).get orElse unapply(next).get)
}
}
def foldCase[C,T1,T2](unapply: C => Option[(Option[T1], Option[T2])], apply: (Option[T1], Option[T2]) => C)
(coll: Seq[C]): C = {
def thisOrElse(current: (Option[T1], Option[T2]), next: (Option[T1], Option[T2])) =
apply(current._1 orElse next._1, current._2 orElse next._2)
coll.tail.foldLeft(coll.head) { case (current, next) =>
thisOrElse(unapply(current).get, unapply(next).get)
}
}
}
When you do this, however, you'll have to explicitly turn apply and unapply into functions:
case class Question(answer: Option[Boolean])
val list2 = List(Question(None), Question(Some(true)), Question(Some(false)))
Folder.foldCase(Question.unapply _, Question.apply _)(list2)
It might be possible to turn it into a structural type, so that you only need to pass the companion object, but I couldn't do it. On #scala, I was told the answer is a definitive no, at least to how I approached the problem.
[Code updated]
Here is an solution which requires only one abstract class per "arity":
abstract class Foldable2[A,B](val a:Option[A], val b:Option[B]) {
def orElse[F <: Foldable2[A,B]](that: F)(implicit ev: this.type <:< F) =
getClass.getConstructor(classOf[Option[A]], classOf[Option[B]]).newInstance(
this.a.orElse(that.a), this.b.orElse(that.b)
)
}
case class Size(w: Option[Int], h: Option[Int]) extends Foldable2(w, h)
println(Size(Some(1),None).orElse(Size(Some(2),Some(42))))
//--> Size(Some(1),Some(42))
Note that the implicit <:< argument will give a compile time error when other case classes with the same constructor arguments are passed to the method.
However, a "well formed" constructor is required, else the reflection code will blow up.
You can use productElement or productIterator (on scala.Product) to generically retrieve/iterate the elements of case classes (and tuples), but they're typed as Any, so there will be some pain.

How to pattern match large Scala case classes?

Consider the following Scala case class:
case class WideLoad(a: String, b: Int, c: Float, d: ActorRef, e: Date)
Pattern matching allows me to extract one field and discard others, like so:
someVal match {
case WideLoad(_, _, _, d, _) => d ! SomeMessage(...)
}
What I would like to do, and what's more relevant when a case class has ~20 odd fields, is to extract only a few values in a way that does not involve typing out WideLoad(_, _, _, _, _, some, _, _, _, thing, _, _, interesting).
I was hoping that named args could help here, although the following syntax doesn't work:
someVal match {
case WideLoad(d = dActor) => dActor ! SomeMessage(...)
// ^---------- does not compile
}
Is there any hope here, or am I stuck typing out many, many _, _, _, _?
EDIT: I understand that I can do case wl # WideLoad(...whatever...) => wl.d, yet I'm still wondering whether there's even terser syntax that does what I need without having to introduce an extra val.
I don't know if this is appropriate, but you can also build an object just to match that field, or that set of fields (untested code):
object WideLoadActorRef {
def unapply(wl: WideLoad): Option[ActorRef] = { Some(wl.d) }
}
someVal match {
case WideLoadActorRef(d) => d ! someMessage
}
or even
object WideLoadBnD {
def unapplySeq(wl: WideLoad): Option[(Int,ActorRef)] = { Some((wl.b,wl.d)) }
}
someVal match {
case WideLoadBnD(b, d) => d ! SomeMessage(b)
}
You can always fall back to guards. It's not really nice, but better than normal pattern matching for you monster case classes :-P
case class Foo(a:Int, b:Int, c:String, d:java.util.Date)
def f(foo:Foo) = foo match {
case fo:Foo if fo.c == "X" => println("found")
case _ => println("arrgh!")
}
f(Foo(1,2,"C",new java.util.Date())) //--> arrgh!
f(Foo(1,2,"X",new java.util.Date())) //--> found
That said I think you should rethink your design. Probably you can logically group some parameters together using case classes, tuples, lists, sets or maps. Scala does support nested pattern matching:
case class Bar(a: Int, b:String)
case class Baz(c:java.util.Date, d:String)
case class Foo(bar:Bar, baz:Baz)
def f(foo:Foo) = foo match {
case Foo(Bar(1,_),Baz(_,"X")) => println("found")
case _ => println("arrgh!")
}
f(Foo(Bar(1,"c"),Baz(new java.util.Date, "X"))) //--> found
f(Foo(Bar(1,"c"),Baz(new java.util.Date, "Y"))) //--> arrgh!
You can just specify the type in the matched pattern:
case class WideLoad(a: String, b: Int, c: Float, d: ActorRef, e: Date)
val someVal = WideLoad(...)
someVal match {
case w: WideLoad => w.d ! SomeMessage(...)
}
You can create a new case class which is a summary of your larger case class
case class WideLoad(a: String, b: Int, c: Float, d: ActorRef, e: Date)
case class WideLoadSummary(d: ActorRef, e: Date)
And then pattern match as normal.
val someVal = WideLoadSummary(wideload.d, wideload.e)
someVal match {
case WideLoadSummary(d, _) => d ! SomeMessage(...)
}