hw2
hw2
1. Objectives
The main objective of this assignment is to reach the mastery with list recursion to the
point where you can implement useful functions for manipulating text.
Along the way, you should also strive to achieve good understanding of the following
concepts:
2. Working with non-recursive and recursive type constructors, and knowing what
their data constructors and eliminators are. These include
3. List recursion. Understanding the logic that goes into coding the recursive case of
a list-processing function. (The results of the recursive calls are modified to yield
the correct output when list is consed with a new element being put at the head.)
1
2. Practice problems
1. Write a function minList :: [Integer] -> Integer which returns the minimum
element of a list. If the list is empty, you should return 0.
You should have a separate base case for when the list has exactly one element!
2. Write a function addAbs :: [Integer] -> Integer which adds together the ab-
solute value of all the elements of a list.
addAbs [1,-2,3,-4] = 10
addAbs [1,10,-100] = 111
3. Write a function existsOdd :: [Integer] -> Bool which returns True if there
exists an odd element in the list, and returns False otherwise.
4. Write a function findOdd :: [Integer] -> Maybe Integer which returns Just x
if there is some x in the input that is odd, and returns Nothing otherwise.
5. Write a function removeEmpty :: [String] -> [String] which takes a list of
strings and removes all empty strings from the list.
removeEmpty ["Hello","","there","","","world",""] = ["Hello","there","world"]
7. Write a function makeGreeting :: Maybe String -> String which takes a string
name wrapped in a Maybe type, and outputs ”Hello, name!”.
If no name is provided, it should output ”Hello!”
makeGreeting (Just "Jesse") = "Hello, Jesse!"
makeGreeting Nothing = "Hello!"
8. Write a function catMaybes :: [Maybe a] -> [a] which collects all non-Nothing
values in the given list and puts them into a list of type [a].
catMaybes [Nothing, Just 1, Just 5, Nothing, Nothing, Just 2] = [1,5,2]
10. Write a function isPrefix :: (Eq a) => [a] -> [a] -> Bool and returns true
if the first list is a prefix of the second list, and returns False otherwise.
isPrefix "hey" "hello" = False
isPrefix [1,2] [1,2,3,4,5] = True
2
3. Homework assignment
Bubblesort
The bubblesort algorithm works by exchanging adjacent elements that are out of order
until all the elements are in the right order.
1. Write a function bubble :: Ord a => [a] -> [a] which recursively goes through
the list and interchanges every element that is followed by a smaller element.
bubble [1,3,2] = [1,2,3]
bubble [1,3,5,4,3,2] = [1,3,4,3,2,5]
2. Write a function bubbleSort :: Ord a => [a] -> [a] which repeatedly applies
the bubble operator to the given list until it has no effect. (So that calling bubble
results in the same list.)
1. Write a function isSubstring :: String -> String -> Bool which returns true
if the first argument is a substring of the second
isSubstring "aba" "abcba" = False
isSubstring "bc" "abcba" = True
Hint. Use a helper function isPrefix defined in section 2 (the practice set),
together with recursive descent through the tail of the list.
2. Write a function genPrefix :: String -> [String] which generates all non-
empty prefixes of the given string and puts them in a list.
genPrefix "" = []
genPrefix "hey" = ["h","he","hey"]
Hint. First, write a helper function that generates all the tails of the given list, so
that e.g., genTails "hey" = ["hey","ey","y"]. This can be done with straight-
forward recursion. Then use this function in combination with reverse to define
genPrefix.
3. Write a function genSubstrings :: String -> [String] which generates all the
substrings of a given string and puts them in a list.
genSubstrings "abcd" = ["","a","ab","b","abc","bc","c","abcd","bcd","cd","d"]
You may list the substrings in a different order, but your list should avoid any
duplicate entries.
Hint. Use genPrefix as a helper function.
3
4. Write a function replacePrefix :: (String,String) -> String -> String which
takes a pair (old,new) of strings, another string str, and replaces the prefix old
of str with the string new.
The function can have undefined behavior if old is not a prefix of str.
replacePrefix ("be","spe") "bear" = "spear"
Hint. There is a simple solution to this question using the drop function.
5. Write a function replaceString :: (String,String) -> String -> String which
replaces the first occurrence of a substring with a new string:
replaceString ("morning","evening") "Good morning!" = "Good evening!"
A simple cypher
A substitution cypher is a simple encoding technique where each character in the input
text is mapped to another character according to some fixed permutation of the alphabet.
We can represent such a permutation by a lookup table — a list of key–value pairs.
1. Write a function lookUp :: Char -> [(Char,Char)] -> Char so that calling
lookUp x perm searches the list perm for the pair (x,y) whose first coordinate
is the given character x. It should then output the second coordinate y.
lookUp 'C' [('A','X'),('B','Y'),('C','Z'),('D','W')] = 'Z'
2. Write a function encode :: [(Char,Char)] -> String -> String which takes
a lookup table and a string and replaces every character by the value it is mapped
to by the given table.
encode [('A','X'),('B','Y'),('C','Z'),('D','W')] "BABA" = "YXYX"
(How could you implement the decode function?)
3. Write a function makeTable :: String -> String -> [(Char,Char)] which takes
two strings and creates a table by pairing up their characters at the same position.
makeTable "ABCD" "XYZW" = [('A','X'),('B','Y'),('C','Z'),('D','W')]
Once you implemented the functions above, you can make a Caesar cypher by rotating
the English alphabet by a fixed number of letters:
caesar :: Int -> [(Char,Char)]|
caesar n = (' ',' ') : makeTable abc (drop n (cycle abc)) where abc = ['A'..'Z']