haskell 基礎題解(40)

2021-09-26 08:23:09 字數 1388 閱讀 9939

【題目】已知某次通話的開始時間,線束時間,怎樣計算通話時長?(假設通話不會超過24小時,但有可能跨午夜)

比如: 12:40:15 到 12:41:18 通話 63秒,而23:59:57 到 00:00:01 僅通話了4秒。

這個問題與【問題39】有個共同的小竅門:欲求 a, b 的差,可以找乙個原點 x,問題變成:

a −b

=(a−

x)−(

b−x)

a-b= (a-x)-(b-x)

a−b=(a

−x)−

(b−x

)顯然,選午夜時刻即 0:0:0 是最便於計算的。

以下 haskell 碼:

-----通話時長

duration :: (

int,

int,

int)

->

(int

,int

,int)-

>

intduration (h1,m1,s1)

(h2,m2,s2)

=(delta (h2,m2,s2)

- delta (h1,m1,s1)

+ dayseconds)

`mod` dayseconds

where

dayseconds =24*

60*60 delta (h, m, s)=60

*60* h +

60* m + s

main :: io (

)main =

doprint $ duration (19,

28,17)

(19,29

,4)print $ duration (23,

59,58)

(0,3

,12)

其中, (a - b + a) % a 這種演算法是很常用的處理技巧。這是害怕 a 比 b 小時產生負值。那麼 a 比 b 大呢? 那就白加了唄,反正最後還取模的,加多少個 a 都不妨。

mod加了反引號,當中綴運算子用,比其字首形式更具可讀性。但要注意,此運算子的優先順序是可以單獨定義的。haskell 把它定義的比 + - 更高優先。

這個對基點求差的思路很具有普遍意義。很多問題中能用上。

有個著名的最大連續和問題,求 乙個給定的整數序列中(有正有負),其所有子串行(連續一段)和的最大值。這不用對所有的位置組合 [a,b] 求和,只要算出從開始到每個位置的和,再利用 [a,

b]=s

uma−

sumb

[a,b] = sum_a - sum_b

[a,b]=

suma

​−su

mb​ 即可。

haskell 基礎題解(06)

題目 如果乙個數的所有真因子 不包含它自身的因子 之和恰等於其自身,則該數為完全數,也稱為完美數 perfect number 完全數有許多奇妙的性質。但它們很稀少,你來求前幾個吧。最小的乙個是 6,因為 6 1 2 3 這個完全數的定義已經很清楚了,如果沒有什麼妙法,就地毯式搜尋也可以。下法就是 ...

haskell 基礎題解(07)

題目 11 1 1 2 1 1 3 3 1 1 4 6 4 1 這個陣勢叫楊輝三角,國外叫帕斯卡三角。前一行的數字中,每兩個相鄰的數字相加就得到下一行的數字。左右兩邊的數永遠是 1 寫個程式,輸出前幾行的楊輝三角。import data.list intersperse yang hui int y...

haskell基礎題解(14)

題目 用自然數蛇形填充乙個 n 階的方陣。當n 5時,形如 這個問題用 haskell 解決時與 題目13 差別甚微。實際上,從函式式的思考習慣看,只要讓有些行作成後反轉一下就可以了。上 ju n f x x 0.n 1 where f row even row take n row n 1.odd...