Claudio Cherubino's blog Life of a Googler

20Feb/082

The 2008 Winter Scripting Games: Pairing Off

Since 2005 Microsoft sponsors an annual scripting competition called Winter Scripting Games, whose competitors are given a series of exercises to be solved with VBShell, Powershell or Perl scripts.

I confess that I only discovered this competition a couple of days ago, and I think that some of the proposed exercises can be useful to practice F# as I'm doing with Project Euler.

There are two Divisions (Beginner and Advanced) with 10 problems each, and today we'll try to solve the first exercise of the Beginner division, called Pairing Off:

In this event we’ll be working with a standard deck of playing cards. A standard deck consists of four suits: Hearts, Spades, Clubs, and Diamonds. Within each suit are the numbers two through ten, plus a Jack, a Queen, a King, and an Ace.

Given a random set of five cards, your task is to find out how many pairs are in that set. In other words, if your five cards are the 2 of hearts, the 4 of spades, the 4 of clubs, the queen of diamonds and the queen of spades, you have 2 pairs: 2 fours and 2 queens. As another example, you might have a 3 of clubs, a 3 of diamonds, a 3 of hearts, a 10 of spades and an ace of hearts. In that case you have 3 pairs: 3 of clubs and 3 of diamonds; 3 of diamonds and 3 of hearts; and 3 of clubs and 3 of hearts.

Let's write the F# solution and then we'll comment it line by line:

#light
open System

let deck =
    [| for y in ["Hearts"; "Spades"; "Clubs"; "Diamonds"]
      for x in [1 .. 13] -> (x,y) |]

let swap a i j =
    let t = a.[i]
    a.[i] <- a.[j]
    a.[j] <- t

let shuffle a =
    let rand = new Random()
    Array.iteri (fun i _ -> swap a i (rand.Next(Array.length a))) a

let rec pairs elem list =
    match list with
    | [] -> 0
    | x::xs when (fst x) = elem -> 1 + pairs elem xs
    | x::xs -> pairs elem xs

let rec count_pairs hand =
    match hand with
    | [] -> 0
    | x::xs -> pairs (fst x) xs + count_pairs xs

do shuffle deck
let hand = deck |> Seq.to_array |> Seq.take 5

let answer = hand |> count_pairs

First of all we need to simulate a deck of cards, with four suits and 13 cards for each suit, and this is done at line 4 thanks to array comprehension.

We need now to shuffle the deck, in order to randomly get five different cards every time we run the application. To do so, we defined the shuffle function at line 13, which swaps the elements of an array in-place, i.e. without returning a new object.

In fact the shuffle function is of type array -> unit, and unit is a special type that means "no value".

When this function is applied to our deck, it iterates each element and swaps it with a random selected one from the same array, using the swap function defined at line 8.

Since the shuffle function doesn't return anything, to call it we have a special syntax: instead of "let" we have to use the "do" keyword, as in line 28.

We are now able to create a card deck and shuffle it, the next step will be writing a function to count the number of pairs contained in a hand of cards.

To accomplish this task we have two functions, called count_pairs and pairs. The idea is to take the first card and check how many couples can be formed with the cards next to it.

The count_pairs function simply applies the pairs function to each element of the hand array, and the pairs function counts how many times the numeric part of the given card is equal to the number contained in the other cards.

To get our answer we just create a random hand of five cards and then apply the pairs_count function to it.

Nice, isn't it? Please let me know if you liked this article and you'd like to read some other on this topic, I'll be glad to write more.

Comments (2) Trackbacks (0)
  1. Claudio,

    nice post, just found your blog today, now a fav…keep the posts coming –jp

  2. Hi Jonathan,
    thanks for your kind words.
    Don’t worry, I’ll keep posting! :)


Leave a comment

(required)

No trackbacks yet.