So, my first entry at the Scripting Games! I actually completed a number of the advanced scripts before looking at the beginner category and I must say I thought some of the advanced problems were easier (or at least less involved) than this one!

The problem was to find the number of pairs of cards in a five card hand. Two cards of the same rank make one pair; three cards of the same rank make three pairs (e.g. 2H, 2S, 2D -> 2H+2S, 2H+2D, 2S+2D); four cards of the same rank make 6 pairs.

Since the number of cards involved (5) and the size of the collections (pairs) is strictly limited it would be very easy to solve this problem using a simple lookup table – but that seemed like cheating to me, so I decided to calculate the combinations using the standard formula nCr=n!/r!(n-r)! With apologies to any statisticians in advance if my reasoning is wrong!

Notes on the script below…

Although not stated as a requirement in the problem description, the script allows multiple collections of pairs, so "King, King, Ace, Ace, Ace" would count four pairs total.

Recursive factorial functions are rightly taboo these days, but helped me grasp the concept of recursion years’ ago, so I stuck with the standard approach.

The script initially scans through the array of cards, splitting off the card’s rank and discarding the suit. Ranks are then counted in a simple hash table. For each resulting entry in the hash table the script checks for occurrences of collections of two or more cards of the same rank; when collections are found the total combinations are calculated and displayed. A grand total (the final answer required) is displayed at the end.

Five points in the pot!

Here’s the code:

1 function fac ([int] $n) {
2 # Classic recursive factorial function
3 if ($n -le 1) { return 1}
4 else {return $n * (fac ($n-1))}
5 }
6
7 function nCr ([int] $n, [int] $r) {
8 # Calculate combinations
9 # nCr=n!/r!(n-r)!
10 # Since, in this case, $r always = 2, we could just use a lookup
11 # to return the value for nCr where r=2, so
12 # nC2=0, 0, 1, 3, 6, 10, 15... (from Pascal triangle row 2)
13 # then: nC2[3] -> 3
14 # ...but that would spoil the fun:-)
15 return ((fac $n)/((fac $r)*(fac ($n-$r))))
16 }
17
18 $hand="Seven of Spades", `
19 "Five of Hearts", `
20 "Seven of Diamonds", `
21 "Seven of Clubs", `
22 "King of Clubs"
23
24 $hand; ""
25
26 $hash=@{}
27 $total=0
28
29 foreach ($card in $hand) {
30 $c, $null = $card.split() # Only interested in the rank, not the suit
31 $hash[$c]++
32 }
33
34 $hash.keys|?{$hash[$_] -ge 2}|%{ # Select cards when at least 2 of the same rank
35 $pairs=nCr $hash[$_] 2 # Calculate combinations of pairs
36 if ($pairs -gt 1) {$s="s"} else {$s=""} # ..if more than one pair, make plural
37 $total+=$pairs # Add up all collections of different pairs
38 "$($hash[$_]) $($_)s -> $pairs pair$s" # Display subtotal for this rank
39 }
40
41 "`nTotal Pairs: $total"