【題目】給定年份,月份,在控制台輸出該月的月曆
比如,2023年9月的月曆:
很明顯,這個問題的要點是:對給定的年、月,需要知道這個月有多少天,還需要知道它的1號是星期幾。
可以參考以前關於日期問題的演算法。
---
-判斷某個年份是否為閏年
b閏年 :
:int
-> bool
b閏年 year | year `mod` 400==
0= true
| year `mod` 100==
0= false
| year `mod` 4==
0= true
| otherwise = false--
--從公元2023年1月開始,逐月的天數無限表
monthdays :
: [int]
monthdays = concat [ [31
,f x,31,
30,31,
30,31,
31,30,
31,30,
31] | x<
-[1900..] ]
where f x =
if b閏年 x then
29else28-
---從2023年1月1日 到 y年m月之前過去的天數
days :
:int
->
int-
>
intdays y m =
let n =
(y-1900)*
12+ m -
1in sum $ take n monthdays--
-已知2023年1月1日是星期1,求之後的 y年 m月 1日是星期幾
monthweek :
:int
->
int-
>
intmonthweek y m = days y m `mod` 7--
-單行按每行n個元素折成多行
foldline :
:int
-> [a] -
> [[a]]
foldline n xs
| length xs <= n = [xs]
| otherwise = take n xs : foldline n (drop n xs)--
-把乙個串前邊添空格,補到指定的長度為止
fillspace :
:int
->
string
->
string
fillspace n s
| length s >= n = s
| otherwise = ' ' : fillspace (n-
1) s--
--已知 y年 m月,求當月的月曆表
calendar :
:int
->
int-
> [string]
calendar y m =
let passmon =
(y-1900)*
12+ m -
1 thismon = monthdays !! passmon
weekbegin = monthweek y m
t = replicate weekbegin " "
++ map show [1..thismon]
t2 = foldline 7 t
t3 = map (map (fillspace 2
)) t2
t4 = map unwords t3
in"mo tu we th fr sa su"
: t4
main :
: io (
)main = putstr $ unlines $ calendar 2019
9
這裡算日期的基點取了 2023年1月1日,而不是公元元年。
星期的說法本就是後來的事。用今天的星期推公元元年星期是不准的。原因複雜。
我們現行的曆法是:格里高利教皇曆法。
2023年9月,英國議會決定把原來的愷撒曆法改為現行的格里高利曆法(200多年前就修定好了,卻沒人執行),因為這兩個曆法當前日期差11天,議會決定當年9月3日到到9月13日刪去。也就是說9月2日後,直接是9月14日。
所以在日期轉換,算星期等問題上,如果日期在2023年9月之前,要小心處理了。
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...