dauði
dauði

Reputation: 59

Is there a way to reduce duplication here?

I am creating a prisoner's dilemma simulation and I have two functions that are counting cooperations and defections done by the two players and outputting them as a tuple. I see a lot of similarities and would like some guidance on how to consolidate the two functions into another function that the two can call upon so I am not reusing code. I am very new in OCaml so I am struggling to find a way to do this!

Here is the necessary information:

type action = bool ;;
type play = action * action ;;
type history = play list 

let rec count_defections (history : history) : (int * int) = 
  match history with
  | [] -> (0, 0)
  | play :: rest ->
    match play with
    | (player1, player2) ->
      match count_defections rest with
      | (d1, d2) ->
        if (player1, player2) = (false, false) then (d1 + 1, d2 + 1)
        else if (player1, player2) = (false, true) then (d1 + 1, d2)
        else if (player1, player2) = (true, false) then (d1, d2 + 1)
        else (d1, d2) ;;

let rec count_cooperations (history : history) : (int * int) = 
  match history with
  | [] -> (0, 0)
  | play :: rest ->
    match play with
    | (player1, player2) ->
      match count_cooperations rest with
      | (d1, d2) ->
        if (player1, player2) = (true, true) then (d1 + 1, d2 + 1)
        else if (player1, player2) = (true, false) then (d1 + 1, d2)
        else if (player1, player2) = (false, true) then (d1, d2 + 1)
        else (d1, d2) ;;

My first thoughts were:

let count_common (history : history) : (int * int) =
  match history with
  | [] -> (0, 0)
  | play :: rest ->
    match play with
    | (player1, player2) ->
      match .....

But I don't really understand how to do the rest.

Upvotes: 1

Views: 113

Answers (1)

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66803

Here's a function that counts the two parts of a pair separately, counting elements that equal a given value.

let count_val_in_pairs value pairs =
    List.fold_left
        (fun (cta, ctb) (a, b) ->
            ((if a = value then cta + 1 else cta),
             (if b = value then ctb + 1 else ctb)))
        (0, 0)
        pairs

Your count_defections is this:

let count_defections history =
    count_val_in_pairs false history

Your count_cooperations is this:

let count_cooperations history =
    count_val_in_pairs true history

Upvotes: 3

Related Questions