Almost all of these problems ask you to write a recursive function. 1.) Write a recursive function makeList :: Int -> a -> [a] that consumes an integer n and an item x and returns a list of length n, each element of which is the item x (if n is negative, return the empty list). 2.) (a) Write a recursive function copy :: [a] -> [a] that returns a copy of its list argument. (b) Write a recursive function copyNum :: (Num a, Ord a) => [a] -> [a] that returns a copy of its list argument except that every negative number should be replaced with 0. 3.) Write a recursive function count :: Eq a => a -> [a] -> Int that counts the number of times its first argument appears in its list argument. 4.) Write a recursive function remove :: Eq a => a -> [a] -> [a] that removes all occurrences of its first argument from its list argument. 5.) (a) Write a recursive function everyOther :: [a] -> [a] that removes every other element of its list argument, starting with the first element. (b) What does this function do? mystery :: [a] -> [a] mystery [] = [] mystery (x:xs) = x : everyOther xs 6.) (a) Write a recursive function dropNth :: Int -> [a] -> [a] that removes the n'th element from the input list (the 0'th element is the first element). If n is negative, or greater than the length of the list, don't drop anything. (b) Write a recursive function addNth :: Int -> a -> [a] -> [a] that returns a list which has all the elements from the input list but it has the given input element as the new list's n'th element (the 0'th element is the first element). The new list will be one longer than the input list. If n is negative, put the input element at the beginning of the new list. If n is greater than the length of the input list, put the input element at the end of the new list. (c) Consider addNth as a curried function. Which would be a better way to define it, as addNth :: Int -> a -> [a] -> [a] or as addNth :: a -> Int -> [a] -> [a] Give a reason for your choice. (Hint: How might you use addNth as a partially applied function?) (d) Write a recursive function replaceNth :: Int -> a -> [a] -> [a] that returns a list which has all the elements from the input list except it has the given input element as the new list's n'th element (the 0'th element is the first element). The new list will be the same length as the input list. If n is negative, or greater than the length of the input list, then don't replace any element of the input list. (e) Consider the memory allocation used in your implementations of dropNth, addNth, and replaceNth. For example, what exactly does your implementation do in these cases? dropNth 5 [0..1000] dropNth 995 [0..1000] addNth 5 0 [0..1000] addNth 995 0 [0..1000] addNth (-1) 0 [0..1000] addNth 1001 0 [0..1000] 7.) (a) Write a function between :: Int -> Int -> [a] -> [a] that consumes two integers n and m and returns the sub list of the input list starting at the n'th element and ending at the m'th element (inclusive). Write this function two ways. First, using Haskell's take and drop functions. Second, write it recursively without using take and drop. Analyze the runtime performance of the two version of between. Is there a significant difference between them? (b) Write a function excise :: Int -> Int -> [a] -> [a] that consumes two integers n and m and returns a list made of the first n-1 elements of the input list followed by the elements from the input list starting at index m+1. Write this function two ways. First, using Haskell's take and drop functions. Second, write it recursively without using take and drop. (Hint: You will probably need a recursive helper function.) Analyze the runtime performance of the two version of excise. Is there a significant difference between them? 8.) Write a recursive function repeats :: Eq a => [a] -> Bool that returns true if and only if the input list has two equal elements next to each other. 9.) Write a recursive function swap :: [(a,b)] -> [(b,a)] that consumes a list of pairs and returns a list of pairs with each input pair's order being swapped. Note: A version of this was used as an example in class but it was written using pattern matching and a list comprehension. Here you should write it as a recursive function. 10.) (a) Write a recursive function lookup' :: Eq a => a -> [(a,b)] -> b that consumes an element x and returns the second item from the first pair that contains x as its first item. If no pair contains x as its first item, return an error. (b) Write a recursive function lookup'' :: Eq a => a -> [(a,b)] -> [b] that consumes an element x and returns a list of each second item from each pair that contains x as its first item. 11.) (a) Write a recursive function merge :: Ord a => [a] -> [a] -> [a] which consumes two sorted lists and returns the sorted list that results from merging the two input lists. (Your function can assume that the input lists are sorted. It doesn't need to verify this.) (b) Write a recursive function split :: [a] -> ([a], [a]) which consumes a list and splits the list int two "halves". The return value is a pair of lists, each being about half the elements from the input list. The easiest way to do this is to have split put every other element from the input list, starting from the first element, into the first output list and put every other element from the input list, starting from the second element, into the second output list. (c) Check that the function mergesort :: Ord a => [a] -> [a] mergesort [ ] = [ ] mergesort [x] = [x] mergesort xs = merge (mergesort ys) (mergesort zs) where (ys,zs) = split xs really does sort a list. 12.) Write a recursive function union :: Eq a => [a] -> [a] -> [a] that mimics the union of sets. This function should consume two lists, that are each assumed to not contain any duplicate elements, and it should produce a list that "merges" the two input lists into a list that contains all the elements from the two input lists but without any duplication. The order of elements in the output list does not matter. Here are a couple of examples (your results need not have the same order). union "cats" "dogs" ==> "datcogs" union [0,4,3,6,1,9] [1,5,3,8] ==> [9,8,6,5,4,3,1,0] 13.) (a) Write a recursive function prefix :: Eq a => [a] -> [a] -> Bool that returns true if the first list is the prefix of the second list. That is, the items from the first list appear as the initial segment of the second list. The empty list should be considered a prefix of every list. (b) Explain why this is not a particularly good way to implement the prefix function from part (a). prefix xs ys = (xs == (take (length xs) ys)) 14.) Write a recursive function subList :: Eq a => [a] -> [a] -> Bool that returns true if the first list is a sub list of the second list. That is, all the items from the first list appear consecutively, somewhere the second list. The empty list should be considered a sub list of every list. (Hint: Use prefix from the previous problem.) 15.) Write a recursive function subSeq :: Eq a => [a] -> [a] -> Bool that returns true if the first list is a sub sequence of the second list. That is, all the items from the first list appear sequentially (but not necessarily consecutively) in the second list. The empty list should be considered a sub sequence of every list. Here is an example. subSequence [2, 4, 6] [1, 2, 3, 4, 5, 6, 7] ==> True 16.) Write a recursive function everyNth :: Int -> [a] -> [a] that consumes a positive integer n and a list and returns a list containing every n'th item from the input list. (Hint: Write a helper function or make use of drop.) 17.) Write a recursive function removeNths :: Int -> [a] -> [a] that consumes an integer n and removes from the input list every n'th item of the input list. (Hint: Write a helper function or make use of take.) 18.) Write an operator !!! (!!!) :: [a] -> Int -> a which acts like Haskell's !! operator except that it also indexes from the right hand end of the list when given a negative index. So [1, 2, 3, 4, 5, 6, 7] !!! (-2) should return 6 (so index -1 is the last element of the list). (Hint: Write !!! in terms of !!.) 19.) Write a recursive function zip3' :: [a] -> [b] -> [c] -> [(a,b,c)] that zips together three lists. Write this without using zip. 20.) Write your own implementations, inits' and tails', of Haskell's inits and tails functions. https://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:inits https://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:tails 21.) The zip function has type zip :: [a] -> [b] -> [(a,b)] and the unzip function has type unzip :: [(a,b)] -> ([a],[b]) The unzip function does not give you back what you started with when you called the zip function. Notice that zip takes as input two lists but unzip gives you back a pair of lists and a pair of lists is not the same thing as two lists. Write a recursive function un_unzip :: ([a],[b]) -> [(a,b)] that takes in a pair of lists and zips the two lists into a list of pairs. If z is a list of pairs, then un_unzip (unzip z) should return exactly z, (un_unzip (unzip z) == z) ==> True If w is a pair of lists, should unzip (un_unzip w) return w? 22.) Write a recursive function flatten :: [[a]] -> [a] that consumes a list of lists and creates a list containing all the items from the original list's nested lists in the same order that they appeared in the original list. Here is an example. flatten [[3,2,1],[1,2,3],[7],[],[5,6]] ==> [3,2,1,1,2,3,7,5,6] In the Haskell library, flatten is called concat. concat [[3,2,1],[1,2,3],[7],[],[5,6]] ==> [3,2,1,1,2,3,7,5,6] 23.) (a) Write a recursive function heads' :: [[a]] -> [[a]] that consumes a list of lists and returns a list of lists where each non empty nested list of the original list is shortened to just its first element in the output list and empty nested lists are empty lists in the output list. Here is an example. heads' [[3,2,1],[1,2,3],[7],[],[5,6]] ==> [[3],[1],[7],[],[5]] (b) Write a recursive function heads :: [[a]] -> [a] that consumes a list of lists and returns a list of the first element from each of the nested input lists. Empty nested lists are ignored in the output list. Here is an example. heads [[3,2,1],[1,2,3],[7],[],[5,6]] ==> [3,1,7,5] 24.) Write a recursive function tails :: [[a]] -> [[a]] that consumes a list of lists and returns a list of the tail list from each of the nested input lists. Empty nested lists are ignored in the output list. Here is an example. tails [[3,2,1],[1,2,3],[7],[],[5,6]] ==> [[2,1],[2,3],[],[6]] 25.) (a) Write a recursive function plist :: Int -> [a] -> [a] that consumes an integer n and a list and returns a list that repeats the input list n times. The name "plist" is an abbreviation of "periodic list". Here is an example. plist 5 [1,2,3] ==> [1,2,3,1,2,3,1,2,3,1,2,3,1,2,3] (b) This part is similar to the previous part. Write a function plist' :: Int -> [a] -> [a] that consumes an integer n and a list and returns a list of length n that repeats the elements from the input list n times. The name "plist" is (again) an abbreviation of "periodic list". Here is an example. plist' 17 [1,2,3] ==> [1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2] 26.) Write a recursive function atLeast :: (Eq a) ==> Integer -> a -> [a] -> Bool that consumes a non-negative integer n, an item x, and a list xs and determines if x appears at least n times in xs. 27.) Write a recursive function dot :: (Num a) => [a] -> [a] -> a that takes the dot product of two lists. To take the dot product of two lists, we multiply entries in corresponding positions (first with first, second with second, and so on) and sum the results. dot :: (Num a) => [a] -> [a] -> a 28.) Write a recursive function palindrome :: (Eq a) => [a] -> Bool that determines if a list is a palindrome. A list is a palindrome if it is either (1) the empty list, or (2) a single item list, or (3) a list x:(P++[x]), where P is a palindrome list. 29.) Write a recursive function sumProd :: (Num a) => [a] -> (a, a) which consumes a list of numbers and returns a pair containing the sum and product of the numbers from the list. Your solution should traverse the input list only one time, so sumProd xs = (sum xs, product xs) is not an appropriate solution since it traverses the input list two times, once to compute sum xs and another time to compute product xs. 30.) Write a recursive function transposeP :: [(a, b)] -> ([a], [b]) that takes a list of pairs and returns a pair of lists. 31.) Write a recursive function transpose :: [[a]] -> [[a]] that transposes the rows of the input list into columns in the output list. (To put this another way, the rows of the output list are the columns from the input list.) So the first list in the output list is the list of every first element from the nested input lists. The second list in the output list is the list of every second element from the nested input lists, etc. Here is an example, transpose [[1,2,3],[4,5,6],[7,8,9]] ==> [[1,4,7],[2,5,8],[3,6,9]] If the input list is a "ragged list", where not all of the nested lists have the same length, then the short lists do not contribute any items to the output rows that exceed their length. Here is another example, transpose [[1,2],[3,4,5],[],[6]] ==> [[1,3,6],[2,4],[5]] HINT: Use heads and tails from problems 23 and 24. 32.) (a) Define a recursive function shorterA :: [a] -> [b] -> Bool that returns True if the first list contains fewer elements than the second list. Do not use Haskell's length function. Make sure your version returns the following results. shorterA [1,2] [1..] ==> True shorterA [1..] [3,4] ==> False shorterA [1,2] [3,4] ==> False (b) Define a function shorterB :: [a] -> [a] -> [a] that returns the shorter of the two lists. Return the first list if they have the same length. Do not use Haskell's length function. Make sure your version returns the following results. shorterB [1,2] [1..] ==> [1,2] shorterB [1..] [3,4] ==> [3,4] shorterB [1,2] [3,4] ==> [1,2]