Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

datatype suit = Clubs | Diamonds | Hearts | Spades datatype rank = Jack | Queen

ID: 3598943 • Letter: D

Question

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

6. Write a function card_value, which takes a card and returns its value (numbered cards have their number as the value, aces are 11, everything else is 10).

7. Write a function remove_card, which takes a list of cards cs, a card c, and an exception e. It returns a list that has all the elements of cs except c. If c is in the list more than once, remove only the first one. If c is not in the list, raise the exception e. You can compare cards with =.

8. Write a function all_same_color, which takes a list of cards and returns true if all the cards in the list are the same color.

9. Write a function sum_cards, which takes a list of cards and returns the sum of their values.

Explanation / Answer

datatype suit = Clubs | Diamonds | Hearts | Spades;
datatype rank = Jack | Queen | King | Ace | Num of int;
type card = rank * suit;

datatype color = Red | Black;
datatype move = Discard of card | Draw;

exception IllegalMove;

(* put your solutions for problem 2 here *)
fun card_color (c : card) =
case c of
      (_, Clubs)    => Black
    | (_, Diamonds) => Red
    | (_, Hearts)   => Red
    | (_, Spades)   => Black;

fun card_value (c : card) =
case c of
      (Num i, _) => i
    | (Ace, _)      => 11
    | _             => 10;

fun remove_card (cs : card list, c : card, e) =
let
      fun helper (target : card, tested : card list, remainded : card list) =
        if target = c
        then tested @ remainded
        else case remainded of
                 [] => raise e
               | x::remainded' => helper (x, target::tested, remainded')
in
      case cs of
          [] => raise e
        | x::cs' => helper (x, [], cs')
end;

fun all_same_color (cs : card list) =
case cs of
      [] => true
    | _::[] => true
    | head::(next::rest) => (card_color(head) = card_color(next)) andalso all_same_color (next::rest);

fun sum_cards (cs : card list) =
let
      fun sum_all (cs : card list, produce : int) =
        case cs of
            [] => produce
          | c::cs' => sum_all (cs', produce+card_value(c))
in
      sum_all (cs, 0)
end;

(* tests for the five functions *)
val a = (Ace, Clubs);
val b = (Num 9, Hearts);
val c = (King, Diamonds);
val d = (Jack, Spades);

(* tests for (a) and (b) *)
val color_a = card_color a;
val value_a = card_value a;
val color_b = card_color b;
val value_b = card_value b;
val color_c = card_color c;
val value_c = card_value c;
val color_d = card_color d;
val value_d = card_value d;

(* test for (c) *)
val cs = [a, b, c, d, (Num 7, Clubs), (Num 2, Diamonds), (Num 4, Spades)];
val remove_a = remove_card (cs, a, IllegalMove);
(* val remove_none = remove_card (cs, (Hearts, Queen), Illegalmove); *)

(* test for (d) *)
val same_color_no = all_same_color [a, b, c, d];
val same_color_yes = all_same_color [b, c, (Num 2, Diamonds), (Queen, Hearts)];

(* test for (e) *)
val sum_test = sum_cards [a, b, c, d];

fun score (cs : card list, goal : int) =
let
      val sum = sum_cards cs
      val preliminary_score = if sum > goal
                              then 3 * (sum - goal)
                              else goal - sum
in
      if all_same_color cs
      then
          let
              val q = preliminary_score div 2
          in
              if preliminary_score mod 2 = 1
              then q + 1
              else q
          end
      else preliminary_score
end;

fun officiate (cs : card list, processing : move list, goal : int) =
let
      fun helper_state (card_list, processing_list, held_cards) =
        case processing_list of
            [] => score (held_cards, goal)
          | p::plist' => case p of
                           Discard c => helper_state (card_list, plist', remove_card(held_cards, c, IllegalMove))
                         | Draw => case card_list of
                                      [] => score (held_cards, goal)
                                    | c::cs' => if sum_cards (c::held_cards) > goal
                                               then score (held_cards, goal)
                                               else helper_state (cs', plist', c::held_cards)
in
      helper_state (cs, processing, [])
end;