[Haskell] 一些簡單題
阿新 • • 發佈:2019-01-22
- 二分查詢,找出列表裡是否存在給定的x
顯然,列表必須是有序的(這就包括了元素是可比較的,也就是都屬於Ord型別類)。
binarySearch :: (Ord a) => a -> [a] -> Bool
binarySearch x list | x < mid = binarySearch x front
| x > mid = binarySearch x behind
| x == mid = True
| otherwise = False
where (front, mid : behind) = (splitAt (div (length list) 2) list)
- 二分查詢,找出列表裡所有的x
binarySearch :: (Ord a) => a -> [a] -> [a]
binarySearch x list | x < mid = binarySearch x front
| x > mid = binarySearch x behind
| x == mid = concat [[x], binarySearch x front, binarySearch x behind]
| otherwise = []
where (front, mid : behind) = splitAt (div (length list) 2) list
感覺寫的有點醜。。。
- Hanoi塔
hanoi :: (Int, Int, Int, Int) -> [(Int, Int)]
-- hanoi (num, from, to, via) -> [(from, to)]
hanoi (num, from, to, via) = hanoi (num - 1, from, via, to) + [(from, to)] + hanoi (num - 1, via, to, from)
-- hanoi num = 2 * hanoi (num - 1) + 1
hanoi塔很簡單,hanoi函式表示最小的num個金片,從from柱子順序不變地移動到to柱子,via柱子用來中轉的移動情況。由於是最小的num個金片,所以3個柱子的已有金片並不會導致金片無法放置的情況,所以可以忽略三個柱子原有的其他金片。然後如果要移動n個金片,就要先把n-1個金片先移開(即移動到via柱上),再移動第n個金片到to柱子上,再將之前的n-1個金片再移動到to柱子上,為了滿足小的金片一定在上的條件。
那麼對於n-1個金片,第一次移動,從from柱子移動到目前的via柱子,經過to柱子。第二次移動,從via柱子移動到to柱子,經過from柱子,這就是引數的由來。
- 歸併排序
其實我覺得歸併排序是最簡單的O(nlogn) 排序演算法了。。。
merge x [] = x
merge [] x = x
merge (a:la) (b:lb) | a < b = a : merge la (b:lb)
| otherwise = b : merge (a:la) lb
mergeSort list | length list <= 1 = list
| otherwise = merge (mergeSort l1) (mergeSort l2)
where (l1, l2) = splitAt (div (length list) 2) list
-- squareRoot iteration root
squareRoot 0 c = c
squareRoot n c = x0 - (x0 ^ 2 - c) / (2 * x0) where x0 = squareRoot (n - 1) c
令函式
則該函式的零點為我們要的答案,利用牛頓迭代法找函式零點:
每一次求出x,x將越來越逼近方程的根。
變形上述方程:
- 漢明數列
對於漢明數集合X ,有
1)1∈X
2)∀x∈X,2x,3x,5x∈X
寫一個函式,返回這個集合所有元素組成的有序序列。
divide x y
| mod x y == 0 = divide (div x y) y
| otherwise = x
ham = filter (\x -> divide (divide (divide x 2) 3) 5 == 1) [1..]
- 求
π
我們有計算公式:
π=4(12−13⋅(12)3+15⋅(12)5+⋯)+4(13−13⋅(13)3+15⋅(13)5+⋯)
那麼兩個無限項數列可以用下面的函式表示
series base = [(1 / (fromIntegral x)) * (base ^ fromIntegral x) * (-1) ^ div (fromIntegral x) 2 | x <- [1,3..]]
其中base為被乘方的數,在這裡取
然後就知道了:
num = 2000000 -- compute times.
mypi = (sum $ take num $ series (1/2)) * 4 + 4 * (sum $ take num $ series (1/3))
- 求素數因子
primeFactors n =
case factors of
[] -> [n]
_ -> factors ++ primeFactors (n `div` head factors)
where factors = take 1 $ filter (\x -> (n `mod` x) == 0) [2 .. floor $ sqrt $ fromIntegral n]
- 矩陣轉置
這是我的寫法
transpose :: [[a]] -> [[a]]
transpose [xs] = [[x]|x<-xs]
transpose (xs:xss) = zipWith (++) (transpose [xs]) (transpose xss)
下面是書上的寫法
transpose :: [[a]] -> [[a]]
transpose [] = []
transpose ([]:xss) = transpose xss
transpose ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (xs : [t | (_:t) <- xss])
- 快速冪
-- quickPower (*) 2 8 = 256
quickPower f a n
| n == 1 = a
| odd n = let m = quickPower f a (div n 2) in f (f m m) a
| otherwise = let m = quickPower f a (div n 2) in f m m