在haskell中生成给定月份和年份的日历

时间:2015-01-03 01:50:40

标签: haskell functional-programming

我一周以来一直在学习haskell,面临着不同的问题。这次我必须从给定的月份和年份创建日历。我差不多完成了,但问题是我从开始那天起就无法开始填写。

我的解决方案是

getDaysInMonth year month=(nDays,sDay) 
                          where nDays = gregorianMonthLength year month
                                sDay= digitToInt(last(showWeekDate (fromGregorian year month 01)))
year=2013
month=10
months=["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"]
mnth=months!!(month-1)
monthDate = getDaysInMonth year month
startAt=snd(monthDate)
totalDays = fst(monthDate)
printLine = "\n"++concat ["+---\t" | r <- [1..7]]
check x | x>totalDays=""
        | x<=totalDays=show x
genDays n m="\n "++concat[check(x)++"\t|"|x<-[n..m]]
genD 6=""
genD sP=genDays ((sP-1)*7+1) (sP*7) ++genD (sP+1)
generateCalendar=printLine++"\n "++
                        concat [[r]++"\t|" | r <- mnth]++printLine++
                        "\n Sun\t|Mon\t|Tue\t|Wed\t|Thu\t|Fri\t|Sat"++printLine++
                        genD 1
main=do
     putStrLn generateCalendar

此程序的输出如下

+---+---+---+---+---+---+---    
 O  |C  |T  |O  |B  |E  |R  |
+---+---+---+---+---+---+---    
 Sun|Mon|Tue|Wed|Thu|Fri|Sat
+---+---+---+---+---+---+---    
 1  |2  |3  |4  |5  |6  |7  |
 8  |9  |10 |11 |12 |13 |14 |
 15 |16 |17 |18 |19 |20 |21 |
 22 |23 |24 |25 |26 |27 |28 |
 29 |30 |31 |   |   |   |   |

所以问题是十月份应该从星期一开始。我认为解决方案的实施有点乱,但我该如何解决这个问题呢?

提前致谢

2 个答案:

答案 0 :(得分:3)

更多&#34;功能性&#34;解决这个问题的方法是:

  1. 创建一个包含35个字符串的列表,每个字符串都是空字符串或(字符串化)数字。
  2. 将列表分成每个7个元素的块(所以你得到五个块)
  3. 对于每个块,将元素渲染为日历中的一行。
  4. 例如,对于2013年10月,35个字符串的列表将是:

    cells = [ "", "", "", "1", "2", "3", ..., "31", "", "" ]
    

    可以使用此辅助函数创建块:

    chunksOf7 (a:b:c:d:e:f:g:rest) = [ [a,b,c,d,e,f,g] ] ++ chunksOf7 rest
    chunksOf7 xs = xs
    

    (有更好的方法来定义chunksOf7,但这就足够了。)

    渲染一块:

    renderChunk cells =  (concat $ map renderCell cells) ++ "\n"
    renderCell c = pad 3 c ++ "|"
    pad n str = str ++ (replicate (n-(length str)) ' ')
    

    pad n str将字符串str填入右侧空格,直到总长度为nreplicate n a会创建一个值a重复n次的列表。

    并将它们放在一起(一旦你有cells列表):

    renderCalendarBody cells =  concat (map renderChunk chunks)
      where chunks = chunksOf7 cells
    

    现在,给定一年零一个月,您只需编写一个函数来定义cells是什么。 单元格列表将包含:

    • 一些领先的空字符串
    • 接着是1到30(或31或本月的最后一天)
    • 后跟一些尾随空字符串

    即:

    cellsForYearAndMonth y m = (replicate n1 "")
                                  ++ [ show d | d <- [1..lastday] ]
                                  ++ (replicate n2 "")
      where lastday = ...
            n1 = ... number of leading empty strings ...
            n2 = ... number of trailing empty strings ...
    

答案 1 :(得分:0)

谢谢@ user5402。最后我得到了工作版

import Data.Time.Calendar
import Data.Time.Calendar.WeekDate
import Data.Char
year=2014
month=2
months=["JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"]
mnth=months!!(month-1)
monthDate = getDaysInMonth year month
startAt=snd(monthDate)
totalDays = fst(monthDate)

getDaysInMonth year month=(nDays,sDay) 
                      where nDays = gregorianMonthLength year month
                            sDay= digitToInt(last(showWeekDate (fromGregorian year month 01)))
cells = (replicate n1 "")
                          ++ [ show d | d <- [1..lastday] ]
                          ++ (replicate n2 "")
          where lastday = totalDays
                n1=(startAt-1)
                n2=(7-(totalDays-(29-startAt)))
chunksOf7 []=[]
chunksOf7 (a:b:c:d:e:f:g:rest) = [ [a,b,c,d,e,f,g] ] ++ chunksOf7 rest

pad n str = str ++ (replicate (n-(length str)) ' ')
renderCell c = pad 3 c ++ "|"
renderChunk cells =  (concat $ map renderCell cells) ++ "\n"

printLine = "\n"++concat ["+---" | r <- [1..7]]++"\n"
monthLine=concat [[r]++" |" | r <- mnth]
dayLine="Sun|Mon|Tue|Wed|Thu|Fri|Sat"
heading=concat[printLine,"Year: ",show year,printLine,monthLine,printLine,dayLine,printLine]

renderCalendarBody cells =  heading++concat (map renderChunk chunks)
  where chunks = chunksOf7 cells

main= do putStrLn $ renderCalendarBody cells