programming language part a 第三周作业
终于赶在deadline之前把它做完了
(* Dan Grossman, Coursera PL, HW2 Provided Code *) (* if you use this function to compare two strings (returns true if the same string), then you avoid several of the functions in problem 1 having polymorphic types that may be confusing *) fun same_string(s1 : string, s2 : string) = s1 = s2 (* put your solutions for problem 1 here *) (* you may assume that Num is always used with values 2, 3, ..., 10 though it will not really come up *) datatype suit = Clubs | Diamonds | Hearts | Spades datatype rank = Jack | Queen | King | Ace | Num of int type card = suit * rank datatype color = Red | Black datatype move = Discard of card | Draw exception IllegalMove (* put your solutions for problem 2 here *) (*1*) fun all_except_option(str,strlist) = let fun contain [] = false | contain (x::xs) = same_string(str,x) orelse contain xs fun collection (sl,acc) = case sl of [] => acc | x::xs => if same_string(str,x) then collection(xs,acc) else collection(xs,x::acc) in if contain strlist then SOME (collection(strlist,[])) else NONE end fun get_substitutions1(sub,s) = case sub of [] => [] | head::tail => let val result = all_except_option(s,head) in case result of NONE => get_substitutions1(tail,s) | SOME sl => sl @ get_substitutions1(tail,s) end fun get_substitutions2(sub,s) = let fun helper(sub,s,acc) = case sub of [] => acc | head::tail => let val result = all_except_option(s,head) in case result of NONE => helper(tail,s,acc) | SOME sl => helper(tail,s,sl@acc) end in helper(sub,s,[]) end fun similar_names (sub,{first=f,middle=m,last=l}) = let val result = get_substitutions2(sub,f) fun generator (reslist,acc) = case reslist of [] => acc | head::tail => generator(tail,{first=head,middle=m,last=l}::acc) in {first=f,middle=m,last=l}::generator(result,[]) end (*2*) fun card_color ca = case ca of (Clubs,_) => Black | (Spades,_) => Black | (Hearts,_) => Red | (Diamnods,_) => Red fun card_value (_,ra) = case ra of Num n => n | Ace => 11 | _ => 10 fun remove_card (cs,c,e) = let fun contain [] = false | contain (x::xs) = (x = c) orelse contain xs fun collection (cl,acc,cnt) = case cl of [] => acc | x::xs => if ((x = c) andalso (cnt = 0)) then collection(xs,acc,cnt+1) else collection(xs,x::acc,cnt) in if (contain cs) then collection(cs,[],0) else raise e end fun all_same_color cs = case cs of [] => true | head::[] => true | head::mid::tl => ((card_color head) = (card_color mid)) andalso (all_same_color (mid::tl)) fun sum_cards cs = let fun helper (cl,acc) = case cl of [] => acc | head::tail => helper(tail,acc+ card_value(head)) in helper(cs,0) end fun score (held,goal) = let val sum = sum_cards held val pre = if sum > goal then 3*(sum - goal) else goal - sum val rescore = if all_same_color(held) then pre div 2 else pre in rescore end fun officiate (cl,ml,goal) = let fun helper state = (*the first parameter is cardlist ,the second is movelist,the third heldlist*) case state of (_,[],held) => score(held,goal) | (cardlist,(Discard ca)::tail,held) => helper(cardlist,tail,remove_card(held,ca,IllegalMove)) | ([],(Draw)::tail,held) => score(held,goal) | (h1::t1,(Draw)::tail,held) => if sum_cards(h1::held) > goal then score(h1::held,goal) else helper(t1,tail,h1::held) in helper(cl,ml,[]) end
这一周主要的知识就是
pattern matching
tail recursion,tail position 一般递归优化成尾递归
case expression
用 nested pattern matching 去写 elegant的代码
以及用_来匹配不在意的位置
上述作业里面已经全部都涉及到了
sicp里面也讲过,sicp还教怎么实现
Yosoro