《Haskell函數式編程入門》練習

遞歸函數

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) 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章