遞歸函數
1.Data.List中有一個函數爲delete,它可以刪除列表中的元素,即它的類型爲delete::Eq a=>a->[a]->[a]。定義一個delete函數從列表中刪去所有列表中出現的給定的元素。
例如:
> delete 2 [4,2,4,6,2]
[4,4,6]
2.請用與take類似的方法定義Prelude中的drop函數。
module Test (
delete',
drop'
)
where
delete' :: Eq a => a -> [a] -> [a]
delete' _ [] = []
delete' n (x:xs) = if n == x then delete' n xs else x : delete' n xs
drop' :: Int -> [a] -> [a]
drop' _ [] = []
drop' n (_:xs) = drop' (n-1) xs
3.定義一個函數,將十進制轉換爲二進制,結果可以用只含有1與0的字符串來表示。
module Test (
dec2bin
)
where
ls = "01"
dec2bin' :: Int -> String
dec2bin' n | n < 0 = error "not support yet!"
| n == 0 = ""
| otherwise = ls !! (n `mod` 2) : dec2bin' (n `div` 2)
dec2bin :: Int -> String
dec2bin 0 = "0"
dec2bin n = reverse $ dec2bin' n
4.定義一個二分查找函數,給定一個元素,如果該元素不在這個有序的列表中,那麼返回[];如果在,那麼返回一個包括這個元素的列表。
注意:這個元素在列表中可能有多個,需要將它們全部返回,例如
>search 4 [1,2,2,3,4,4,4,5,6,7,8]
[4,4,4]
module Test (
search
)
where
search' :: (Ord a) => a -> [(a, Int)] -> Int
search' a [] = -1
search' a xs | fst m < a = search' a behind
| fst m > a = search' a front
| otherwise = snd m
where
(front, m:behind) = splitAt pos xs
pos = length xs `div` 2
search :: (Ord a) => a -> [a] -> [a]
search a xs | pos >= 0 = left ++ [xs!!pos] ++ right
| otherwise = []
where
left = reverse $ takeWhile (==a) $ reverse front
right = takeWhile (==a) behind
(front, m:behind) = splitAt pos xs
pos = search' a (zip xs [0..length xs])
5.有一列數被稱爲漢明數(Hamming Number),它是這樣定義的:1屬於該序列,然後,如果h是一個漢明數,那麼2h、3h、5h都是漢明數。你可以沒有重複並且升序地生成所有的漢明數嗎?
提示:首先定義一個函數merge,這個merge與歸併排序中的merge相似,但是會將重複的數字去掉,然後再像定義nature那麼定義名爲ham的函數,將map (*2) ham、map (*3) ham與map (*5) ham使用第一步定義的merge函數融合起來。
這個數列的前15項如下:
>take 15 ham
[1,2,3,4,5,6,8,9,10,12,15,16,18,20,24]
module Test (
ham
)
where
merge :: (Ord a) => [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys) | x > y = y:merge (x:xs) ys
| x < y = x:merge xs (y:ys)
| otherwise = x:merge xs ys
ham :: [Integer]
ham = 1 : merge (merge (map (*2) ham) (map (*3) ham)) (map (*5) ham)