You are on page 1of 3

Prof.aa Dr. J. Giesl Notes: Please solve these exercises in groups of two!

Functional Programming SS12 Exercise Sheet 4 (due 16.05.2012) M. Brockschmidt, F. Emmes

The solutions must be handed in directly before (very latest: at the beginning of ) the exercise course on Wednesday, 16.05.2012, 11:45, in lecture hall AH 2. Alternatively you can drop your solutions into a box which is located right next to Prof. Giesls oce (until the exercise course starts). Please write the names and immatriculation numbers of all (two) students on your solution. Also please staple the individual sheets! Exercises marked with V3B are only relevant for students attending the V3B (Bachelor Informatik, Master Mathematik) version of the lecture. Exercises marked with V3M are relevant for all other students. Unmarked exercises are relevant for all students. Exercises marked with a star are voluntary bonus challenge exercises with advanced diculty. The points reachable in these exercises do not count towards the total number of reachable exercise points, so you may ignore them without any disadvantage. However, the bonus points count towards your point total, so you can work on them instead of working on the (more boring) standard exercises.

Exercise 1 (V3B List Comprehensions):

(1 + 2 + 2 = 5 points)

In this exercise you should learn how to use the Haskell list comprehension syntax. a) In Haskell, there is a pre-dened function replicate :: Int -> a -> [a]. When called with the arguments n 0 and e, it returns a list of length n which contains only elements with value e. For example replicate 3 c returns the string "ccc". Implement the function repl :: Int -> a -> [a], which should do the same as the function replicate, but dene it using only one dening equation and only a list comprehension as its right-hand side. You may use the shorthand notation [a..b], which returns a list of all integers from a to b, but you may not use replicate in your implementation of repl. b) Write a function allStrings :: [Char] -> Int -> [String], such that allStrings s n returns a list of all non-empty strings consisting only of characters from the list s and which have at most length n. The order in which the strings are returned is not important. For example allStrings "ab" 2 might return ["a","aa","ab","b","ba","bb"]. You may use up to two dening equations, but one right-hand side must be a list comprehension. c) Write a function palindromes :: [String] -> [String], that gets a list of strings, and returns a list of all strings s = w1 w2 , where w1 and w2 are strings contained in and s is a palindrome (i.e., s is the same as s reversed). For example palindromes ["say", "on", "not", "to", "as"] yields ["sayas","noton","tonot"]. Use only one dening equation and only a list comprehension as its right-hand side. Hints: You may use the pre-dened function reverse :: [a] -> [a].

Exercise 2 (Lazy Programming):


a) Consider the following denition of the function minsort: minsort minsort minsort where :: [ Int ] -> [ Int ] [] = [] xs = m : minsort rest m = minimum xs rest = filter (/= m ) xs

(2 + 2 = 4 points)

Functional Programming SS12 Exercise Sheet 4 (due 16.05.2012) Here, minimum is the predened function computing the minimum of a list. We now dene minimum xs = head (minsort xs). The functions minimum and filter (/= m) both have linear complexity in the length of the input list. What is the complexity of the function minimum? b) Implement the innite list rands :: [Int] of pseudo-random numbers following the linear congruential method. For that, we need parameters m (the modulus ), a (the multiplier ), and c (the increment ). Then, for any given number rn , the next pseudo-random number can be computed using the formula rn+1 = ((a rn ) + c) % m.1 Use m = 216 , a = 25713 and c = 13849 and 42 as rst random number. Furthermore, dene a function randSum :: rst k elements of rands. Int -> Int such that randSum k yields the sum of the

Exercise 3 (V3B Cyclic data):

(4 points)

Implement a method posSublistSums :: [Int] -> [Int] such that the call posSublistSums xs returns a list res whose n-th entry is the sum of the rst n positive numbers in xs. Your solution should work in linear time (w.r.t. the length of the input list) by using a cyclic data object. Hints: Consider that the n-th element of the result res is the sum of the (n 1)-th element of res and the n-th positive number in xs. You may use the predened function zipWith: zipWith :: ( a -> b -> c ) -> [ a ] -> [ b ] -> [ c ] zipWith f ( x : xs ) ( y : ys ) = f x y : zipWith f xs ys zipWith _ _ _ = [] This function can be used to combine two lists element-wise, i.e., zipWith f [x1 , x2 , . . .] [y1 , y2 , . . .] yields the list [(f x1 y1 ), (f x2 y2 ), . . .]. Pre-dened functions such as map, foldr, sum, zipWith, filter work in linear time (w.r.t. the list length) provided that their higher-order parameters work in constant time.

Challenge Exercise 4 (Lazy Programming):

(5* points)

In this exercise, we want to implement a function repMin that takes a list xs and returns a list of the same length containing only the minimal element of xs. For example, repMin [2,1,3] should yield [1,1,1]. The straighforward implementation would look like this: repMin xs = map (\ _ -> min ) xs where min = minimum xs However, this requires two iterations over the list: rst, minimum searches for the minimal element, and then the map call replaces all elements. Using lazy programming, it is possible to nd the minimum and replace all elements in one iteration. Implement a function repMin :: (Ord a) => [a] -> [a] that does this and briey explain why your solution works as described. Hints: Use a helper function repMin :: (Ord a) => [a] -> b -> (a, [b]) that takes a list xs and a replacement value r and returns a pair where the rst element is the minimal value of xs and the second element is a list of the same length as xs, but where all elements are r. Implement repMin by calling repMin such that the minimal value returned by repMin also appears as input argument to repMin.

1 Here,

% describes the modulo operation, i.e, the remainder of division of one number by another.

Functional Programming SS12 Exercise Sheet 4 (due 16.05.2012)

Exercise 5 (V3M Input and Output):

(2 + 4 + 3 = 9 points)

In this exercise, we will implement a small interactive arithmetic trainer. We use the following simple data type to represent the actual arithmetic problems: data ArithProblem = Add Int Int | Mul Int Int This type and several auxiliary functions are in the le TrainerBase.hs, which you can download from our website. You can use it in your solution by writing import TrainerBase at the top of your program. An example run of the complete program could look like this: How many problems do you want ? 4 What is 2*7? 14 Your answer is correct ! What is 4*9? 35 Your answer is not correct ! What is 1+9? 11 Your answer is not correct ! What is 9*5? 45 Your answer is correct ! You got 2 answers right and 2 ones wrong . a) First, implement a function askProblem :: ArithProblem -> IO Bool. Evaluating askProblem p should then print the problem and query the user for an answer. It should then read the answer and report to the user whether the result is correct. Furthermore, it should return True in case of a correct answer and False otherwise. Hints: ArithProblem is a member of the type class Show. Thus, there is a function show :: ArithProblem -> String that returns a String representation of a given problem. For example, show (Mul 2 7) returns "2*7". The function getLine :: line from the user. IO String is similar to getChar :: IO Char, but reads a complete

The function read :: (Read a) => String -> a can be used to convert a String into types that are in the type class Read. For example, let x = "42" in read x :: Int converts the String "42" into the Int 42. TrainerBase provides a function getSol :: for a given arithmetic problem. ArithProblem -> Int that computes the solution

b) Implement a function askN :: Int -> IO (Int, Int) such that askN n asks the user for solutions to n randomly generated arithmetic problems and returns the numbers of right and wrong answers. To get a randomly generated ArithProblem, you can use the function randomProblem :: IO ArithProblem from TrainerBase.hs. Use the function askProblem from a) to communicate with the user. c) Implement the function main :: IO () that asks the user for the number n of problems that should be generated, calls askN with n and then reports the total number of right and wrong answers.