module _19 open common //1 Jan 1900 was a Monday. //Thirty days has September, //April, June and November. //All the rest have thirty-one, //Saving February alone, //Which has twenty-eight, rain or shine. //And on leap years, twenty-nine. //A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400. type day = Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday let dayNum d = match d with | Sunday -> 0 | Monday -> 1 | Tuesday -> 2 | Wednesday -> 3 | Thursday -> 4 | Friday -> 5 | Saturday -> 6 let numDay n = match n with | 0 -> Sunday | 1 -> Monday | 2 -> Tuesday | 3 -> Wednesday | 4 -> Thursday | 5 -> Friday | 6 -> Saturday | _ -> raise(System.ArgumentException("No!")) type date = { Year : int; Month : int } let isLeapYear y = y % 4 = 0 && (y % 100 <> 0 || y % 400 = 0) let getDaysInMonth d = let thirtyMonths = [|9;4;6;11|]; match d with | date when date.Month = 2 && isLeapYear date.Year -> 29 | date when date.Month = 2 -> 28 | date when Array.exists ((=) date.Month) thirtyMonths -> 30 | _ -> 31 let getNextFirstDay d daysInMonth = (daysInMonth + (dayNum d)) % 7 |> numDay let firstSaturdays = //getNextFirstDay Thursday 30 crossMapList [1900..1999] [1..12] |> Seq.map (fun (y, m) -> { Year = y; Month = m }) |> Seq.scan (fun (day:day) ym -> getNextFirstDay day (getDaysInMonth ym)) Monday |> Seq.filter ((=) Sunday) |> Seq.length