Quantcast
Channel: 懒得折腾
Viewing all articles
Browse latest Browse all 764

Programming Languages Programming Assignment 2

$
0
0

Code

(* 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 *)
fun all_except_option (str : string, xs : string list) = 
   let
     fun isInside (xs : string list) = 
        case xs of 
           [] => false
         | x::xs' => if same_string(str,x) then true
                     else isInside(xs') 
     fun all_except_option_help (xs : string list, ys: string list) = 
         case xs of
           [] => ys
          | x::xs' => if same_string(str, x) then all_except_option_help (xs', ys)
                                            else all_except_option_help (xs', ys@[x])
   in
     case isInside(xs) of 
       false => NONE
      | true  => SOME(all_except_option_help(xs, []))  
   end
fun get_substitutions1 (strlistlist : string list list, s : string ) = 
  case strlistlist of 
     [] => []
   | strlist::strlistlist' => let
                                 val res = all_except_option (s, strlist)
                              in
                                 case res of
                                    NONE => get_substitutions1 (strlistlist', s)
                                  | SOME reslist  => reslist @ get_substitutions1 (strlistlist', s) 
                              end
 fun get_substitutions2 (strlistlist : string list list, s : string ) = 
    let fun  get_substitutions2_helper (strlistlist : string list list, acc : string list) = 
           case strlistlist of 
              [] => acc
	    | strlist::strlistlist' => let
                                 val res = all_except_option (s, strlist)
                              in
                                 case res of
                                    NONE => get_substitutions2_helper (strlistlist', acc)
                                  | SOME reslist  => get_substitutions2_helper (strlistlist', acc@reslist) 
                              end
    in
        get_substitutions2_helper (strlistlist, [])
    end
 fun similar_names (strlistlist : string list list, fullname : {first:string, middle:string, last:string} ) =
    let val {first=x, middle=y, last=z} = fullname
        val firstnamelist = get_substitutions2 (strlistlist, x)
        fun similar_names_helper (firstnamelist : string list, fullnamelist : {first:string, last:string, middle:string} list) = 
            case firstnamelist of
                [] => fullnamelist
		   | firstname::firstnamelist' => similar_names_helper(firstnamelist', fullnamelist @ [ {first = firstname, last = z, middle = y}])
    in
        similar_names_helper(firstnamelist, [{first = x, last = z, middle = y}])
    end

(* you may assume that Num is always used with values 2, 3, ..., 9
   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 *)
fun card_color (c : card ) = 
   let val (s, r) = c
   in
      case s of
         Spades => Black
       | Clubs  => Black
       | Diamonds => Red
       | Hearts  => Red   
   end
fun card_value (c : card ) = 
   let val (s, r) = c
   in
      case r of
         Ace => 11
       | Jack  => 10
       | Queen => 10
       | King  => 10
       | Num(num) => num   
   end

fun remove_card (cs : card list, c: card, e) =  
   let
     fun isInside (xs : card list) = 
        case xs of 
           [] => false
         | x::xs' => if x = c then true
                     else isInside(xs') 
     fun remove_card_helper (xs : card list, result : card list) = 
        case xs of
           [] => result
          | x::xs' => if (c = x) then result @ xs' else remove_card_helper(xs', result @ [x])   
  in
    if (isInside(cs)) then remove_card_helper (cs, [])
                      else raise e
  end
fun all_same_color (cs : card list) =  
    case cs of
       [] => true
     | _::[] => true
     | head :: (neck :: rest) => ((card_color(head) = card_color(neck)) andalso all_same_color(neck :: rest))
fun sum_cards (cs : card list) = 
    let fun sum_cards_helper (cs : card list, acc : int) = 
          case cs of
             [] => acc
           | c::cs' => sum_cards_helper(cs', acc + card_value(c))
    in
       sum_cards_helper(cs, 0)
    end  
fun score (cs : card list, goal : int) = 
    let
       val s = sum_cards (cs)
       val pScore = if (s > goal) then 3*(s - goal) else (goal - s)
       val result = if (all_same_color(cs)) then (pScore div 2) else pScore     
    in
        result
    end

fun officiate (cardlist : card list, movelist : move list, goal : int) = 
    let
      fun officiate_helper (cardlist : card list, movelist : move list, heldcards : card list) =
          case movelist of
             [] => heldcards
	    | move::movelist' => case move of 
                                    Draw => ( case cardlist of
                                               [] => heldcards
					       | card::cardlist'  => if (sum_cards (card :: heldcards) > goal) 
                                                                     then card :: heldcards 
                                                                     else officiate_helper(cardlist', movelist', card :: heldcards)
                                             )
			            | Discard c => remove_card(heldcards, c, IllegalMove)
    in
        score(officiate_helper (cardlist, movelist, []), goal)
    end

Test Cases

(* Dan Grossman, Coursera PL, HW2 Provided Tests *)

(* These are just two tests for problem 2; you will want more.

   Naturally these tests and your tests will use bindings defined 
   in your solution, in particular the officiate function, 
   so they will not type-check if officiate is not defined.
 *)

fun provided_test1 () = (* correct behavior: raise IllegalMove *)
    let val cards = [(Clubs,Jack),(Spades,Num(8))]
	val moves = [Draw,Discard(Hearts,Jack)]
    in
	officiate(cards,moves,42)
    end

fun provided_test2 () = (* correct behavior: return 3 *)
    let val cards = [(Clubs,Ace),(Spades,Ace),(Clubs,Ace),(Spades,Ace)]
	val moves = [Draw,Draw,Draw,Draw,Draw]
    in
 	officiate(cards,moves,42)
    end
 val  all_except_option_test = all_except_option("a", ["b","c","d","e","f"]);
 val get_substitutions1_test = get_substitutions2([["Fred","Fredrick"],["Elizabeth","Betty"],["Freddie","Fred","F"]],"Fred");
 val get_substitutions1_test = get_substitutions2([["Fred","Fredrick"],["Jeff","Jeffrey"],["Geoff","Jeff","Jeffrey"]],"Jeff");
 val similar_names_test = similar_names([["Fred","Fredrick"],["Elizabeth","Betty"],["Freddie","Fred","F"]],{first="Fred", middle="W", last="Smith"});
 val card_color_test = card_color((Clubs,Jack));
 val card_value_test = card_value((Clubs,Jack));
 val cards = [(Clubs,Jack),(Spades,Num(8))]
 val remove_card_test = remove_card ([(Clubs,Jack),(Spades,Num(8))], (Spades,Num(7)), IllegalMove);
 val all_same_color_test = all_same_color([(Clubs,Jack),(Spades,Num(8))]);
 val sum_cards_test = sum_cards([(Clubs,Jack),(Spades,Num(8))]);
 val score_test = score([(Clubs,Jack),(Spades,Num(8))], 10);
 


Viewing all articles
Browse latest Browse all 764

Trending Articles