这次回顾HW1,主要是Standard ML的基本语法。

课程主页:

https://www.coursera.org/learn/programming-languages/home

B站搬运:

https://www.bilibili.com/video/BV1dL411j7L7

参考资料:

https://www.coursera.org/learn/programming-languages-part-b/discussions/weeks/1/threads/qdnA6f5EEeaJEAqoFc7ZZA

代码

(* problem 1 *)
fun is_older(date1: int*int*int, date2: int*int*int) =
    if (#1 date1) < (#1 date2)
    then true
    else 
        if (#1 date1) = (#1 date2)
        then 
            if (#2 date1) < (#2 date2)
            then true
            else 
                if (#2 date1) = (#2 date2)
                then
                    if (#3 date1) < (#3 date2)
                    then true
                    else false
                else false
        else false

(* problem 2 *)
fun number_in_month(dates: (int*int*int) list, month: int) =
    if null dates
    then 0
    else
        let val month1 = (#2 (hd dates))
            val cnt = number_in_month((tl dates), month)
        in
            if month1 = month
            then 1 + cnt
            else cnt
        end

(* problem 3 *)
fun number_in_months(dates: (int*int*int) list, months: int list) =
    if null months
    then 0
    else
        if null dates
        then 0
        else number_in_month(dates, (hd months)) + number_in_months(dates, (tl months))

(* problem 4 *)
fun dates_in_month(dates: (int*int*int) list, month: int) =
    if null dates
    then []
    else
        let val month1 = (#2 (hd dates))
            val result = dates_in_month((tl dates), month)
        in
            if month1 = month
            then (hd dates)::result
            else result
        end

(* problem 5 *)
fun dates_in_months(dates: (int*int*int) list, months: int list) =
    if null months
    then []
    else
        if null dates
        then []
        else dates_in_month(dates, (hd months))@dates_in_months(dates, (tl months))

(* problem 6 *)
fun get_nth(strings: string list, n: int) = 
    if null strings
    then ""
    else
        if n = 1
        then (hd strings)
        else get_nth((tl strings), n - 1)

(* problem 7 *)
fun date_to_string(date: int*int*int) = 
    let
      val str_months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
      val year = #1 date
      val month = #2 date
      val day = #3 date
    in
      get_nth(str_months, month) ^ " " ^ Int.toString(day) ^ ", " ^ Int.toString(year)
    end

(* problem 8 *)
fun number_before_reaching_sum(sum: int, arr: int list) = 
    let
        (* partial_sum < sum, partial_sum + (hd partial_arr) >= sum *)
        fun helper(partial_sum: int, partial_arr: int list, n: int) = 
            if partial_sum >= sum
            then 0
            else
                if null partial_arr
                then 0
                else
                    let
                        val partial_sum1 = partial_sum + (hd partial_arr)
                    in
                        if partial_sum1 >= sum
                        then n
                        else
                            helper(partial_sum1, (tl partial_arr), n + 1)
                    end
    in
        if (hd arr) >= sum
        then 0
        else helper(0, arr, 0)
    end

(* problem 9 *)
fun what_month(day) = 
    let
      val months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    in
      number_before_reaching_sum(day, months) + 1
    end

(* problem 10 *)
fun month_range(day1: int, day2: int) = 
    if day1 > day2
    then []
    else
        what_month(day1)::month_range(day1 + 1, day2)

(* problem 11 *)
fun oldest(dates: (int*int*int) list) =
    let
      fun helper(date: (int*int*int), remain_dates: (int*int*int) list) = 
        if null remain_dates
        then date
        else 
            let
              val date1 = (hd remain_dates)
            in
              if is_older(date, date1)
              then helper(date, (tl remain_dates))
              else helper(date1, (tl remain_dates))
            end
    in
      if null dates
      then NONE
      else SOME (helper((hd dates), (tl dates)))
    end

(* problem 12 *)
fun remove_dup_month(months: int list) = 
    if null months
    then []
    else
        let
            fun contain(n: int, arr: int list) = 
                if null arr
                then false
                else
                    if n = (hd arr)
                    then true
                    else contain(n, (tl arr))
            fun helper(month: int, cur_month: int list) = 
                if month > 12
                then []
                else
                    let
                        val res = helper(month + 1, cur_month)
                    in
                        if contain(month, cur_month)
                        then month::res
                        else res
                    end
        in
            helper(1, months)
        end

fun number_in_months_challenge(dates: (int*int*int) list, months: int list) =
    let
      val months_no_dup = remove_dup_month(months)
    in
      number_in_months(dates, months_no_dup)
    end

(* problem 13 *)
fun dates_in_months_challenge(dates: (int*int*int) list, months: int list) =
    let
      val months_no_dup = remove_dup_month(months)
    in
      dates_in_months(dates, months_no_dup)
    end

fun reasonable_date(date: int*int*int) =
    let
        fun is_leap(year: int) = 
            if (year mod 400) = 0
            then true
            else 
                if ((year mod 100) <> 0) andalso ((year mod 4) = 0)
                then true
                else false
        fun get_month_day(months: int list, n: int) = 
            if null months
            then 0
            else
                if n = 1
                then (hd months)
                else get_month_day((tl months), n - 1)
        fun helper(date: int*int*int) = 
            let
                val year = #1 date
                val month = #2 date
                val day = #3 date
                val months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
            in
                if year = 0
                then
                    false
                else
                    if (month < 1) orelse (month > 12)
                    then false
                    else
                        if month = 2
                        then
                            if is_leap(year)
                            then 
                            if day <= (get_month_day(months, month) + 1)
                                then true
                                else false
                            else
                                if day <= get_month_day(months, month)
                                then true
                                else false
                        else
                            if (day <= get_month_day(months, month))
                            then true
                            else false
            end
    in
        helper(date)
    end

测试

(* Homework1 Simple Test *)
(* These are basic test cases. Passing these tests does not guarantee that your code will pass the actual homework grader *)
(* To run the test, add a new line to the top of this file: use "homeworkname.sml"; *)
(* All the tests should evaluate to true. For example, the REPL should say: val test1 = true : bool *)
use "hw1.sml";

val test1_1 = is_older ((1,2,3),(2,3,4)) = true
val test1_2 = is_older ((1,2,3),(1,3,4)) = true
val test1_3 = is_older ((3,2,3),(2,3,4)) = false
val test1_4 = is_older ((1,2,3),(1,3,4)) = true
val test1_5 = is_older ((1,2,3),(1,2,4)) = true
val test1_6 = is_older ((1,2,5),(1,2,4)) = false
val test1_7 = is_older ((1,2,5),(1,2,5)) = false

val test2_1 = number_in_month ([(2012,2,28),(2013,12,1)],2) = 1
val test2_2 = number_in_month ([],2) = 0
val test2_3 = number_in_month ([(2012,2,28),(2013,12,1)],3) = 0

val test3_1 = number_in_months ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[2,3,4]) = 3
val test3_2 = number_in_months ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[]) = 0
val test3_3 = number_in_months ([],[2,3,4]) = 0

val test4_1 = dates_in_month ([(2012,2,28),(2013,12,1)],2) = [(2012,2,28)]
val test4_2 = dates_in_month ([(2012,2,28),(2013,12,1)],3) = []
val test4_3 = dates_in_month ([],3) = []

val test5_1 = dates_in_months ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[2,3,4]) = [(2012,2,28),(2011,3,31),(2011,4,28)]
val test5_2 = dates_in_months ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[]) = []
val test5_3 = dates_in_months ([],[2,3,4]) = []

val test6_1 = get_nth (["hi", "there", "how", "are", "you"], 2) = "there"
val test6_2 = get_nth ([], 2) = ""
val test6_3 = get_nth (["hi", "there", "how", "are", "you"], 100) = ""

val test7_1 = date_to_string (2013, 6, 1) = "June 1, 2013"
val test7_2 = date_to_string (2021, 12, 31) = "December 31, 2021"

val test8_1 = number_before_reaching_sum (10, [1,2,3,4,5]) = 3
val test8_2 = number_before_reaching_sum (10, [11,2,3,4,5]) = 0

val test9_1 = what_month 31 = 1
val test9_2 = what_month 59 = 2
val test9_3 = what_month 90 = 3
val test9_4 = what_month 120 = 4
val test9_5 = what_month 151 = 5
val test9_6 = what_month 181 = 6
val test9_7 = what_month 212 = 7
val test9_8 = what_month 243 = 8
val test9_9 = what_month 273 = 9
val test9_10 = what_month 304 = 10
val test9_11 = what_month 334 = 11
val test9_12 = what_month 365 = 12
val test9_13 = what_month 70 = 3

val test10_1 = month_range (31, 34) = [1,2,2,2]
val test10_2 = month_range (35, 34) = []

val test11 = oldest([(2012,2,28),(2011,3,31),(2011,4,28)]) = SOME (2011,3,31)

val test12_1 = number_in_months_challenge ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[2,3,4]) = 3
val test12_2 = number_in_months_challenge ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[]) = 0
val test12_3 = number_in_months_challenge ([],[2,3,4]) = 0
val test12_4 = number_in_months_challenge ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[2,2,2,3,3,4]) = 3
val test12_5 = number_in_months_challenge ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[]) = 0
val test12_6 = number_in_months_challenge ([],[2,3,3,4]) = 0
val test12_7 = dates_in_months_challenge ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[2,3,4]) = [(2012,2,28),(2011,3,31),(2011,4,28)]
val test12_8 = dates_in_months_challenge ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[]) = []
val test12_9 = dates_in_months_challenge ([],[2,3,4]) = []
val test12_10 = dates_in_months_challenge ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[2,3,3,2,4]) = [(2012,2,28),(2011,3,31),(2011,4,28)]
val test12_11 = dates_in_months_challenge ([(2012,2,28),(2013,12,1),(2011,3,31),(2011,4,28)],[]) = []
val test12_12 = dates_in_months_challenge ([],[4,2,3,4,4]) = []
val test12_13 = remove_dup_month ([2,2,2,3,3,4]) = [2,3,4]

val test13_1 = reasonable_date (1900,2,29) = false
val test13_2 = reasonable_date (1904,2,29) = true
val test13_3 = reasonable_date (1904,0,29) = false
val test13_4 = reasonable_date (2021,13,29) = false
val test13_5 = reasonable_date (2021,12,31) = true
val test13_6 = reasonable_date (0,2,3) = false