Week 4 exercise done
This commit is contained in:
parent
9d6c308e4d
commit
baf795690f
@ -21,9 +21,15 @@ case class Leaf(char: Char, weight: Int) extends CodeTree
|
|||||||
trait Huffman extends HuffmanInterface {
|
trait Huffman extends HuffmanInterface {
|
||||||
|
|
||||||
// Part 1: Basics
|
// Part 1: Basics
|
||||||
def weight(tree: CodeTree): Int = ??? // tree match ...
|
def weight(tree: CodeTree): Int = tree match{
|
||||||
|
case Fork(_,_,_, weight) => weight
|
||||||
|
case Leaf(_, weight) => weight
|
||||||
|
} // tree match ...
|
||||||
|
|
||||||
def chars(tree: CodeTree): List[Char] = ??? // tree match ...
|
def chars(tree: CodeTree): List[Char] = tree match{
|
||||||
|
case Fork(_,_,chars,_) => chars
|
||||||
|
case Leaf(char,_) => List(char)
|
||||||
|
} // tree match ...
|
||||||
|
|
||||||
def makeCodeTree(left: CodeTree, right: CodeTree) =
|
def makeCodeTree(left: CodeTree, right: CodeTree) =
|
||||||
Fork(left, right, chars(left) ::: chars(right), weight(left) + weight(right))
|
Fork(left, right, chars(left) ::: chars(right), weight(left) + weight(right))
|
||||||
@ -64,7 +70,9 @@ trait Huffman extends HuffmanInterface {
|
|||||||
* println("integer is : "+ theInt)
|
* println("integer is : "+ theInt)
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
def times(chars: List[Char]): List[(Char, Int)] = ???
|
def times(chars: List[Char]): List[(Char, Int)] = {
|
||||||
|
chars.groupBy(x => x).map(t => (t._1, t._2.length)).iterator.toList
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of `Leaf` nodes for a given frequency table `freqs`.
|
* Returns a list of `Leaf` nodes for a given frequency table `freqs`.
|
||||||
@ -73,12 +81,13 @@ trait Huffman extends HuffmanInterface {
|
|||||||
* head of the list should have the smallest weight), where the weight
|
* head of the list should have the smallest weight), where the weight
|
||||||
* of a leaf is the frequency of the character.
|
* of a leaf is the frequency of the character.
|
||||||
*/
|
*/
|
||||||
def makeOrderedLeafList(freqs: List[(Char, Int)]): List[Leaf] = ???
|
def makeOrderedLeafList(freqs: List[(Char, Int)]): List[Leaf] =
|
||||||
|
freqs.sortBy(_._2).map(pair => new Leaf(pair._1, pair._2))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the list `trees` contains only one single code tree.
|
* Checks whether the list `trees` contains only one single code tree.
|
||||||
*/
|
*/
|
||||||
def singleton(trees: List[CodeTree]): Boolean = ???
|
def singleton(trees: List[CodeTree]): Boolean = trees.size == 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parameter `trees` of this function is a list of code trees ordered
|
* The parameter `trees` of this function is a list of code trees ordered
|
||||||
@ -92,7 +101,15 @@ trait Huffman extends HuffmanInterface {
|
|||||||
* If `trees` is a list of less than two elements, that list should be returned
|
* If `trees` is a list of less than two elements, that list should be returned
|
||||||
* unchanged.
|
* unchanged.
|
||||||
*/
|
*/
|
||||||
def combine(trees: List[CodeTree]): List[CodeTree] = ???
|
def combine(trees: List[CodeTree]): List[CodeTree] = {
|
||||||
|
val ordered = trees.sortBy(weight)
|
||||||
|
if (trees.isEmpty)
|
||||||
|
trees
|
||||||
|
else if (singleton(trees))
|
||||||
|
trees
|
||||||
|
else
|
||||||
|
makeCodeTree(ordered.head, ordered.tail.head) :: ordered.tail.tail
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function will be called in the following way:
|
* This function will be called in the following way:
|
||||||
@ -105,7 +122,11 @@ trait Huffman extends HuffmanInterface {
|
|||||||
* In such an invocation, `until` should call the two functions until the list of
|
* In such an invocation, `until` should call the two functions until the list of
|
||||||
* code trees contains only one single tree, and then return that singleton list.
|
* code trees contains only one single tree, and then return that singleton list.
|
||||||
*/
|
*/
|
||||||
def until(done: List[CodeTree] => Boolean, merge: List[CodeTree] => List[CodeTree])(trees: List[CodeTree]): List[CodeTree] = ???
|
def until(done: List[CodeTree] => Boolean, merge: List[CodeTree] => List[CodeTree])(trees: List[CodeTree]): List[CodeTree] =
|
||||||
|
if(done(trees))
|
||||||
|
trees
|
||||||
|
else
|
||||||
|
until(done, merge)(merge(trees))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function creates a code tree which is optimal to encode the text `chars`.
|
* This function creates a code tree which is optimal to encode the text `chars`.
|
||||||
@ -113,7 +134,8 @@ trait Huffman extends HuffmanInterface {
|
|||||||
* The parameter `chars` is an arbitrary text. This function extracts the character
|
* The parameter `chars` is an arbitrary text. This function extracts the character
|
||||||
* frequencies from that text and creates a code tree based on them.
|
* frequencies from that text and creates a code tree based on them.
|
||||||
*/
|
*/
|
||||||
def createCodeTree(chars: List[Char]): CodeTree = ???
|
def createCodeTree(chars: List[Char]): CodeTree =
|
||||||
|
until(singleton, combine)(makeOrderedLeafList(times(chars))).head
|
||||||
|
|
||||||
|
|
||||||
// Part 3: Decoding
|
// Part 3: Decoding
|
||||||
@ -124,7 +146,14 @@ trait Huffman extends HuffmanInterface {
|
|||||||
* This function decodes the bit sequence `bits` using the code tree `tree` and returns
|
* This function decodes the bit sequence `bits` using the code tree `tree` and returns
|
||||||
* the resulting list of characters.
|
* the resulting list of characters.
|
||||||
*/
|
*/
|
||||||
def decode(tree: CodeTree, bits: List[Bit]): List[Char] = ???
|
def decode(tree: CodeTree, bits: List[Bit]): List[Char] = {
|
||||||
|
def acc(rest: CodeTree, bits: List[Bit]): List[Char] =
|
||||||
|
rest match {
|
||||||
|
case Leaf (c, _) => if (bits.isEmpty) List(c) else c :: acc(tree, bits)
|
||||||
|
case Fork(l, r, _, _) => if (bits.head == 0) acc(l, bits.tail) else acc(r, bits.tail)
|
||||||
|
}
|
||||||
|
acc(tree, bits)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Huffman coding tree for the French language.
|
* A Huffman coding tree for the French language.
|
||||||
@ -142,8 +171,7 @@ trait Huffman extends HuffmanInterface {
|
|||||||
/**
|
/**
|
||||||
* Write a function that returns the decoded secret
|
* Write a function that returns the decoded secret
|
||||||
*/
|
*/
|
||||||
def decodedSecret: List[Char] = ???
|
def decodedSecret: List[Char] = decode(frenchCode, secret)
|
||||||
|
|
||||||
|
|
||||||
// Part 4a: Encoding using Huffman tree
|
// Part 4a: Encoding using Huffman tree
|
||||||
|
|
||||||
@ -151,7 +179,14 @@ trait Huffman extends HuffmanInterface {
|
|||||||
* This function encodes `text` using the code tree `tree`
|
* This function encodes `text` using the code tree `tree`
|
||||||
* into a sequence of bits.
|
* into a sequence of bits.
|
||||||
*/
|
*/
|
||||||
def encode(tree: CodeTree)(text: List[Char]): List[Bit] = ???
|
def encode(tree: CodeTree)(text: List[Char]): List[Bit] = {
|
||||||
|
def encodeChar(tree: CodeTree)(char: Char): List[Bit] = tree match {
|
||||||
|
case Leaf(_, _) => Nil
|
||||||
|
case Fork(l, r, _, _) => if (chars(l).contains(char)) 0 :: encodeChar(l)(char) else 1 :: encodeChar(r)(char)
|
||||||
|
}
|
||||||
|
|
||||||
|
text.flatMap(encodeChar(tree))
|
||||||
|
}
|
||||||
|
|
||||||
// Part 4b: Encoding using code table
|
// Part 4b: Encoding using code table
|
||||||
|
|
||||||
@ -161,7 +196,8 @@ trait Huffman extends HuffmanInterface {
|
|||||||
* This function returns the bit sequence that represents the character `char` in
|
* This function returns the bit sequence that represents the character `char` in
|
||||||
* the code table `table`.
|
* the code table `table`.
|
||||||
*/
|
*/
|
||||||
def codeBits(table: CodeTable)(char: Char): List[Bit] = ???
|
def codeBits(table: CodeTable)(char: Char): List[Bit] =
|
||||||
|
table.filter((codeChar) => codeChar._1 == char).head._2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a code tree, create a code table which contains, for every character in the
|
* Given a code tree, create a code table which contains, for every character in the
|
||||||
@ -171,22 +207,32 @@ trait Huffman extends HuffmanInterface {
|
|||||||
* a valid code tree that can be represented as a code table. Using the code tables of the
|
* a valid code tree that can be represented as a code table. Using the code tables of the
|
||||||
* sub-trees, think of how to build the code table for the entire tree.
|
* sub-trees, think of how to build the code table for the entire tree.
|
||||||
*/
|
*/
|
||||||
def convert(tree: CodeTree): CodeTable = ???
|
def convert(tree: CodeTree): CodeTable = tree match {
|
||||||
|
case Leaf(c, w) => List( (c, List()) )
|
||||||
|
case Fork(l, r, _, _) => mergeCodeTables(convert(l), convert(r))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function takes two code tables and merges them into one. Depending on how you
|
* This function takes two code tables and merges them into one. Depending on how you
|
||||||
* use it in the `convert` method above, this merge method might also do some transformations
|
* use it in the `convert` method above, this merge method might also do some transformations
|
||||||
* on the two parameter code tables.
|
* on the two parameter code tables.
|
||||||
*/
|
*/
|
||||||
def mergeCodeTables(a: CodeTable, b: CodeTable): CodeTable = ???
|
def mergeCodeTables(a: CodeTable, b: CodeTable): CodeTable = {
|
||||||
|
a.map(code => (code._1, 0 :: code._2)) ::: b.map(code => (code._1, 1 :: code._2))
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This function encodes `text` according to the code tree `tree`.
|
* This function encodes `text` according to the code tree `tree`.
|
||||||
*
|
*
|
||||||
* To speed up the encoding process, it first converts the code tree to a code table
|
* To speed up the encoding process, it first converts the code tree to a code table
|
||||||
* and then uses it to perform the actual encoding.
|
* and then uses it to perform the actual encoding.
|
||||||
*/
|
*/
|
||||||
def quickEncode(tree: CodeTree)(text: List[Char]): List[Bit] = ???
|
def quickEncode(tree: CodeTree)(text: List[Char]): List[Bit] = text.flatMap(codeBits(convert(tree)))
|
||||||
}
|
}
|
||||||
|
|
||||||
object Huffman extends Huffman
|
object Huffman extends Huffman
|
||||||
|
|
||||||
|
object Main extends App {
|
||||||
|
import Huffman._
|
||||||
|
|
||||||
|
println( decodedSecret )
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user