Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
fp:lab05 [2021/04/08 18:08] pdmatei |
fp:lab05 [2022/03/31 08:53] (current) pdmatei |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== 5. Processing using higher-order functions ===== | + | ===== 5. Functional data representation ===== |
- | The following is an input test. You can add more examples to it: | + | ==== 5.1. Nats === |
- | <code haskell> | + | |
- | l = ["matei@gmail.com", "mihai@gmail.com", "tEst@mail.com", "email@email.com", "short@ax.ro"] | + | |
- | </code> | + | |
- | Use ''map'', ''foldr''/''foldl'', instead of recursive functions. Wherever possible, use functional composition and closures. | + | Consider the following toy implementation of the type ''Nat'' which encodes natural numbers. |
- | 5.1. Replace uppercases with lowercases from emails. (Do **not** use recursion). To be able to use character functions from the library, add ''import Data.Char'' at the beginning of the program. Use the Internet to find the appropriate character function. | + | <code scala> |
- | + | trait Nat {} | |
- | <code haskell> | + | case object Zero extends Nat {} |
- | rem_upper l = | + | case class Succ(n: Nat) extends Nat {} |
</code> | </code> | ||
- | 5.2. Write a function which removes emails longer than a given size. | + | For instance, ''3'' will be encoded as the value: ''Succ(Succ(Succ(Zero)))''. |
- | Use anonymous functions in your implementation, then think about how you can replace them by a functional composition of more basic functions. **Hint:** Write your code in steps. Start with the basic idea, then think about how you can write it better and cleaner. | + | |
- | <code haskell> | + | **5.1.1.** Write a function which implements addition over Nats: |
- | longer :: Int -> [String] -> [String] | + | <code scala> |
- | longer x = | + | def add(n: Nat, m: Nat): Nat = ??? |
</code> | </code> | ||
- | 5.3. Count the number of emails longer than 12 characters. Use a fold, anonymous functions and functional composition. | + | **5.1.2.** Write a function which converts a ''Nat'' to an ''Int'': |
- | <code haskell> | + | <code scala> |
- | howmany l = | + | def toInt(n: Nat): Int = ??? |
</code> | </code> | ||
- | 5.4. Split the list between first names and email domains. What ingredients (auxiliary functions) are necessary? Use either a fold or a tail-recursive function in your implementation. Example: ''names_emails ["matei@email.com"] = [ ["matei", "email.com"] ]''. | + | **5.1.3.** Write a function which converts an ''Int'' to a ''Nat''. |
- | <code haskell> | + | <code scala> |
- | names_emails :: [String] -> [[String]] | + | def fromInt(i: Int): Nat |
- | names_emails l = | + | |
</code> | </code> | ||
- | 5.5. Identify the list of the employed domain names (e.g. ''gmail.com''). Remove duplicates. Use no recursion and no additional prelude function apart from ''head'' and ''tail''. **Hint** think about the sequence of basic operations you want to perform and assemble them using functional composition. | + | ==== 5.2. Binary Search Trees === |
- | <code haskell> | + | |
- | domains :: [String] -> [String] | + | |
- | domains = | + | |
- | </code> | + | |
- | (!) 5.6. In some previous exercise you have, most likely, implemented a split function using ''foldr''. Implement one with ''foldl''. **Hint:** use an example together with the ''foldl'' implementation to figure out what the accumulator should do. | + | In a [[https://en.wikipedia.org/wiki/Binary_search_tree| binary search tree (BST)]], the key of the current node, is always: |
+ | * **smaller** or equal than **all** keys in the **right** sub-tree. | ||
+ | * **larger** or equal than **all** keys in the **left** sub-tree. | ||
- | <code haskell> | + | Consider a binary search tree with keys as integers, encoded as follows: |
- | splitl :: String -> [String] | + | <code scala> |
- | splitl = | + | trait ITree {} |
+ | case object Empty extends ITree | ||
+ | case class INode(key: Int, left: ITree, right: ITree) extends ITree | ||
</code> | </code> | ||
- | 5.7. Write a function which extracts the domains from emails, without the dot part. (e.g. ''gmail''). Generalise the previous function ''splitl'' to ''splitBy:: Char -> String -> [String]'', and use it each time necessary, in your implementation. **Hint**: Wherever you want to mix pattern matching with guards, start with the patterns first. | + | **5.2.1.** Create the tree shown below: |
+ | <code scala> | ||
+ | val tree = ??? | ||
+ | /* | ||
+ | 5 | ||
+ | / \ | ||
+ | 2 7 | ||
+ | / \ \ | ||
+ | 1 3 9 | ||
+ | */ | ||
+ | </code> | ||
+ | |||
+ | **5.2.2.** Implement the method ''size'' which determines the number of non-empty nodes from the BST. | ||
+ | |||
+ | **5.2.3.** Define the method ''contains'', which checks if a given integer is a member of the BST. | ||
+ | |||
+ | **5.2.4.** Implement the method ''ins'' which inserts a new integer in the BST. **Note:** the insertion must return a new BST (the //binary search tree// property mentioned above must hold after insertion). | ||
+ | |||
+ | **5.2.5.** Implement a method ''flatten'' which converts a BST into a list of integers. You must carefully choose the flattening method in such a way as to obtain **a sorted list** from the BST. Hint: you may use the list concatenation operator '':::'' (triple colons; example usage: ''List(1,2,3):::List(4,5)''. | ||
+ | |||
+ | **5.2.6.** Implement a method ''depth'' which returns the maximal depth of a BST. Hint: use the method: ''_.max(_)''. | ||
+ | |||
+ | **(!) 5.2.8.** Implement a method ''minimum'' which returns the smallest integer from a BST. (If the tree is empty, we return -1). Hint: use the example above, to guide your implementation. | ||
+ | |||
+ | **5.2.9.** Implement a similar method ''maximum''. | ||
- | <code haskell> | + | **(!) 5.2.10.** Implement a method ''successor(k)'' which returns **the smallest** integer from the BST, which is **larger** than ''k''. Use the following examples for your implementation: |
- | domain :: [String] -> [String] | + | <code> |
- | domain = | + | 5 t.successor(2) = 5 |
+ | / \ t.successor(5) = 6 | ||
+ | 2 7 t.successor(7) = 8 | ||
+ | / \ | ||
+ | 6 8 | ||
</code> | </code> | ||
+ | ** (!!) 5.2.11.** Implement a method ''remove(k)'' which removes element ''k'' from the BST. |