import Data.Char (ord, toUpper)
import Prelude hiding (zipWith)
-- since we have our own definition of zipWith in this file the previous
-- line hides the definition of zipWith from Prelude to avoid nameclashes
{- Exercise 11.1 -}
index 0 (x:xs) = x
index n (x:xs) = index (n-1) xs
zipWith f [] _ = []
zipWith f _ [] = []
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
ones = 1 : ones
nats = 0 : zipWith (+) nats ones
get n = index n nats
{- Exercise 11.2 -}
greatest :: [Integer] -> Integer
greatest xs = undefined
average :: [Double] -> Double
average xs = undefined
to_upper_str xs = undefined
{- Exercise 11.3 -}
f :: Fractional t => t -> [t] -> t
f a [] = a
f a (x:xs) = g (a + x/3) xs
g :: Fractional t => t -> [t] -> t
g b [] = b
g b (x:xs) = f (b + x*x) (x:xs)
-- rewrite f and g to f' and g', using neither f, nor g, nor any form of mutual recursion
f' :: Fractional t => t -> [t] -> t
f' = undefined
g' :: Fractional t => t -> [t] -> t
g' = undefined
c :: String -> Int
c [] = 1
c xs = sum . map ord $ d xs
d :: String -> String
d [] = []
d (x:xs) = replicate (c xs) x ++ xs
-- rewrite c and d to c' and d', using neither c, nor d, nor any form of mutual recursion
c' :: String -> Int
c' = undefined
d' :: String -> String
d' = undefined
{- Exercise 11.4 -}
merge :: Ord a => [a] -> [a] -> [a]
merge xs ys = undefined
fp_nums :: [Integer]
fp_nums = undefined
{- TESTS -}
testGreatest = and $ map f [[32,53,543,123,123], [23], [-12,90], [0,-1,-2]]
where f x = maximum x == greatest x
testAverage = and $ map f [[32.3,53,543,123,123], [23], [-12,90], [0,-1.2,-2]]
where f x = a x == average x
a x = sum x / fromIntegral (length x)
testUpper = and $ map f ["Innsbruck", "Axams", "muenCHEN", []]
where f x = map toUpper x == to_upper_str x
testF = and $ map g [(1, [3,23]), (321, [23,31])]
where g (x,y) = f x y == f' x y
testG = and $ map f [(1, [3,23]), (321, [23,31])]
where f (x,y) = g x y == g' x y
testC = and $ map f ["Inn", "Axa", "mue", []]
where f x = c x == c' x
testD = and $ map f ["Inn", "Axa", "mue", []]
where f x = d x == d' x
testMerge = and $ map f [([1,3], [2,4], [1,2,3,4])
,([1,18,200], [19,150,200,300], [1,18,19,150,200,300])
,([], [300], [300])
,([300], [], [300])]
where f (x,y,z) = merge x y == z
testNums = take 7 fp_nums == [1,2,3,4,5,6,8] && fp_nums !! 19 == 36
testAll = and [testGreatest,testAverage,testUpper,testF,testG,testC
,testD,testMerge,testNums]