--------------------------------------------------------------------
-- CO 2008 Functional Programming
-- Created: September 2006, University of Leicester, UK
--------------------------------------------------------------------
-- Student Name
-- Student Number
--------------------------------------------------------------------
module Worksheet3 where
-- An example of a function on natural numbers defined recursively
fact :: Int -> Int
fact 0 = 1
fact 1 = 1
fact (n+1) = (n+1)*(fact n)
fact _ = error "Number is negative"
----------------------------------------------------------------------
---- Exercise 1
---------------------------------------------------------------------
-- Adding the first n natural numbers
-- When the number is negative, give an error.
-- Recall: when testing the function with a negative number
-- the negative number should be written between brackets,
-- addup (-3) and not addup -3
addup :: Int -> Int
addup n
| n<0 = error "please enter a positive integer"
| n==0 = 0
| n==1 = 1
| n>1 = n + (addup n-1)
-- Adding the first n Fibonnaci numbers (recall Lecture 8 for their
-- definition fib: Int -> Int)
addFibup :: Int -> Int
addFibup 0 = 0
addFibup 1 = 1
addFibup 2 = 1
addFibup 3 = 2
addFibup (n+2) =(addFibup (n+1))+(addFibup (n))
----------------------------------------------------------------------
---- Exercise 2
---------------------------------------------------------------------
-- A function that gives a line of n stars
-- When the number is negative, give an error.
starline :: Int -> String
starline 0 = ""
starline (n+1) = "*"++starline n
starline _ = error "Number Invalid"
-- A function that given n and m gives a list
-- of n lines of m stars,
-- When the number n is negative, give an error
rectangle :: Int -> Int -> String
rectangle 0 m = "\n"
rectangle (n+1) m = "\n"++(starline m)++ rectangle n m
rectangle _ _ = error "Number is negative"
-- A function that prints a rectangle
printRectangle:: Int -> Int -> IO()
printRectangle m n = putStr (rectangle m n)
-- A function that gives the square
-- When the number is negative, give an error
square :: Int -> String
square n = rectangle n n
-- A function that prints a square
printSquare:: Int -> IO()
printSquare n = putStr (square n)
-- An example of a recursive function on lists
-- Note the use of patterns [], (x:[]) and (x:xs)
-- Instead of (x:[]) you could write [x]
myLast :: [Int] -> Int
myLast [] = error "Empty list"
myLast (x:[]) = x
myLast (x:xs) = myLast xs
----------------------------------------------------------------------
---- Exercise 3
---------------------------------------------------------------------
-- A function that converts a binary number to decimal system
-- Return an error in case some integer in the list is not 0 or 1.
binToDec :: [Int] -> Int
binToDec a
| a==[] = 0
| head(reverse a) == 0 = 2*binToDec(reverse(tail(reverse a)))
| head(reverse a) == 1 = 2*binToDec(reverse(tail(reverse a)))+1
| otherwise = error "please enter an array of binary digits"
----------------------------------------------------------------------
---- Exercise 4
---------------------------------------------------------------------
-- A function that removes the nth element in a string
-- Return an error in case the number is negative or is larger
-- than the length of the string
remove :: Int -> [a] -> [a]
remove a b
| a > length b = error "number too big"
| a <=0 = error "please enter a positive number"
| otherwise = take (a-1) b ++ drop a b
----------------------------------------------------------------------
---- Exercise 5
---------------------------------------------------------------------
-- A function that given two strings tests if the first one is
-- a prefix of the second one.
prefix :: String -> String -> Bool
prefix a b
| take (length a) b == a = True
| otherwise = False
----------------------------------------------------------------------
---- Exercise 6
---------------------------------------------------------------------
-- A function that given two strings tests if the first one is
-- a suffix of the second one.
suffix :: String -> String -> Bool
suffix a b = prefix (reverse a) (reverse b)
----------------------------------------------------------------------
---- Exercise 7
---------------------------------------------------------------------
-- Plurals in italian
type Word = String
italplural :: Word -> Word
italplural a
| head(reverse a) == 'o' = reverse ("i" ++ tail (reverse a))
| head(reverse a) == 'e' = reverse ("i" ++ tail (reverse a))
| head(reverse a) == 'a' = reverse ("e" ++ tail (reverse a))
| otherwise = a
----------------------------------------------------------------------
---- Exercise 8
---------------------------------------------------------------------
-- Higher order insertion sort
-- Hint: first write a function hoins that inserts an element
-- in the right place
-- hoins :: Ord b => (a -> b) -> a -> [a] -> [a]
-- The function hoInsertionSort sorts a list
-- hoInsertionSort :: Ord b => (a -> b) -> [a] -> [a]
hoins :: Ord b => (a -> b) -> a -> [a] -> [a]
hoins fun item [] = item:[]
hoins fun item (x:xs)
| fun item <= fun x = (item:x:xs)
| otherwise = x:(hoins fun item xs)
hoInsertionSort :: Ord b => (a -> b) -> [a] -> [a]
hoInsertionSort fun [] = []
hoInsertionSort fun (x:xs) = hoins fun x (hoInsertionSort fun xs)
----------------------------------------------------------------------
---- Exercise 9
---------------------------------------------------------------------
-- Sorting an address book
type Name = String
type Address = String
type Phonenumber = Int
type Person = (Name, Address)
type Phonebook = [Person]
toname :: Person -> String
toname (a,b) = a
sortbook :: Phonebook -> Phonebook
sortbook a = hoInsertionSort toname a
mybook :: Phonebook
mybook = [("Di", "Welford rd 234"),
("Jo", "London rd 12"),
("Dave","Queens rd 78")]