This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let (|RoyalFlush|_|) (hand : Hand) = | |
if (hand.Cards.[0].Rank) = Ace && (Consecutive hand.Cards) && (SameSuit hand.Cards) then | |
RoyalFlush |> Some | |
else | |
None |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// True if all cards in the sequence are the same suit. | |
let SameSuit cards = | |
( cards |> Seq.distinctBy (fun card -> card.Suit) |> Seq.length ) = 1 | |
/// True if all the cards in the sequence are consecutive by value. | |
/// Includes both the high-Ace and the low-Ace cases. | |
let Consecutive cards = | |
cards | |
|> Array.map (fun card -> card.Rank) | |
|> Array.sortBy (fun rank -> 0 - rank.SortValue) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// A hand of exactly five cards. | |
type Hand(cards : Card[]) = | |
do | |
if cards.Length <> 5 then | |
raise (ArgumentException("Invalid number of cards")) | |
/// The cards in the hand, sorted in descending order of rank. | |
member h.Cards = cards |> Array.sortBy (fun card -> 0 - card.Rank.SortValue) | |
static member FromString (s : string) = | |
let cards = | |
s.Split([|' '|]) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// A playing card. | |
type Card = { Rank : Rank; Suit : Suit } | |
with | |
static member FromString (s : String) = | |
let rank, suit = | |
match s.Length with | |
| 2 -> s.Substring(0, 1), s.[1] | |
// The 10 case has three characters | |
| 3 -> s.Substring(0, 2), s.[2] | |
| _ -> raise (ArgumentException("Invalid card string: ", s)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// A card rank. | |
type Rank = | |
| Ace | King | Queen | Jack | Value of int | |
static member FromString s = | |
match s with | |
| "A" -> Ace | "K" -> King | "Q" -> Queen | "J" -> Jack | |
| "10" -> Value(10) | |
| _ when s.Length = 1 && s.[0] >= '2' && s.[0] <= '9' -> Value(int(s.[0]) - int('0')) | |
| _ -> raise (ArgumentException(sprintf "Invalid rank string: %s" s)) | |
/// The value of the rank for comparison purposes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Suit = | |
| Club | Diamond | Heart | Spade | |
static member FromChar c = | |
match c with | |
| '♣' -> Club | '♦' -> Diamond | '♥' -> Heart | '♠' -> Spade | |
| _ -> raise (ArgumentException(sprintf "Invalid suit character: %c" c)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let rank1, rank2 = hand1.Cards.[0].Rank, hand2.Cards.[0].Rank |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Compare two hands, the first of which can Win, Draw or Lose against the second. | |
let CompareHands (hand1 : Hand) (hand2 : Hand) = | |
match hand1, hand2 with | |
| RoyalFlush, RoyalFlush -> | |
raise (ArgumentException("Impossible combination: two Royal Flushes")) | |
| RoyalFlush, _ -> Win | |
| _, RoyalFlush -> Lose | |
| StraightFlush, StraightFlush -> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// The possible outcomes when comparing two Poker hands. | |
type Outcome = Win | Draw | Lose | |
with | |
static member FromRanks (rank1 : Rank) (rank2 : Rank) = | |
let sortValue1, sortValue2 = rank1.SortValue, rank2.SortValue | |
if sortValue1 > sortValue2 then | |
Win | |
elif sortValue1 < sortValue2 then | |
Lose | |
else |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let (|FourOfAKind|_|) (hand : Hand) = | |
if (RankCounts hand.Cards).[0] = 4 then | |
FourOfAKind |> Some | |
else | |
None |