By on 5/7/2009 11:38 AM ()

Hi,

Something like the following, obviously I haven't checked it particuarly thoroughly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
 

#light

type Suit = | Heart | Club | Spade | Diamond

type Card = 
    | Numbered of Suit*int
    | King of Suit
    | Queen of Suit
    | Jack of Suit


/// get relative value of card
/// 1 < 2 < .. < 10 < J < Q < K
let card_sort_value = function
    | Numbered (_,v) -> v
    | Jack _ -> 11       
    | Queen _ -> 12        
    | King _ -> 13

/// compare cards usng their relative value
let compare_card c1 c2 = 
    compare (card_sort_value c1) (card_sort_value c2)

/// get the next card by relative value, suit is irrelevant                  
let next_card = function
    | Numbered(s,v) when (v < 10) -> Some (Numbered(s,v+1))
    | Numbered(s,v) -> Some (Jack s)
    | Jack s -> Some (Queen s)
    | Queen s -> Some (King s)
    | King s -> None

let are_successive (c1,c2) =
    match (next_card c1) with
    | Some cn -> (compare_card c2 cn) = 0 
    | None -> false
    
/// determine if 5 card sequence have successive values        
let is_straight ls = 
    ls |> Seq.sort_by card_sort_value
       |> Seq.pairwise
       |> Seq.map are_successive
       |> Seq.fold (&&)  true


/// get all 5 card sequences and check for straights               
let get_straights (s: seq<Card>) =
    s |> Seq.windowed 5
      |> Seq.filter (is_straight) 

let print_suit = function
    | Heart -> "Heart's"
    | Club -> "Club's"
    | Spade -> "Spade's"
    | Diamond -> "Diamond's"
    
let print_card = function
    | Numbered(s,v) -> System.String.Format("{0} of {1}",v,print_suit s)
    | Jack(s) -> System.String.Format("Jack of {0}",print_suit s)  
    | Queen(s) -> System.String.Format("Queen of {0}",print_suit s)    
    | King(s) -> System.String.Format("King of {0}",print_suit s)  
    
fsi.AddPrinter(print_suit)        
fsi.AddPrinter(print_card)

Try this out with an example sequence: 6 Heart, J Spade, 9 Diamond, Q Spade, 10 Heart, K Club, 3 Heart. We should pick up the middle 5 as a straight.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 

seq [ Numbered (Heart,6) ; Jack Spade; Numbered(Diamond,9); Queen Spade; Numbered(Heart,10); King Club; Numbered(Heart,3)];;

val it : seq<Card>
= [6 of Heart's; Jack of Spade's; 9 of Diamond's; Queen of Spade's;
   10 of Heart's; King of Club's; 3 of Heart's]   


get_straights it;;

val it : seq<Card []>
= seq
    [[|Jack of Spade's; 9 of Diamond's; Queen of Spade's; 10 of Heart's;
       King of Club's|]]

For longer sequences, you can randomly draw from an 'infinite shoe' with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let deck = 
    Array.concat 
        [|
            [| for i in 1..10 -> Numbered(Heart, i)|];
            [| Jack Heart; Queen Heart; King Heart |];            
            [| for i in 1..10 -> Numbered(Club, i)|];
            [| Jack Club; Queen Club; King Club |];            
            [| for i in 1..10 -> Numbered(Diamond, i)|];
            [| Jack Diamond; Queen Diamond; King Diamond |];            
            [| for i in 1..10 -> Numbered(Spade, i)|];
            [| Jack Spade; Queen Spade; King Spade |];
        |]            
            
       
let get_card n = 
    if n > deck.Length then failwith "Card number must be between 0-51"
    else Array.get deck n

Then you can generate random sequences, eg:

1
2
3
let rng = ref (System.Random(1))
let my_sequence = seq [for i in 0..100000 -> get_card ((!rng).Next(51))]
let my_straights = get_straights my_sequence

Evaluating my_straights gives:

1
2
3
4
5
6
7
8
9
10
11
12
 

val it : seq<Card []>
= seq
    [[|7 of Diamond's; 9 of Club's; 5 of Diamond's; 8 of Club's; 6 of Club's|];
     [|10 of Club's; 9 of Diamond's; Jack of Heart's; King of Heart's;
       Queen of Heart's|];
     [|Jack of Heart's; King of Heart's; Queen of Heart's; 9 of Diamond's;
       10 of Spade's|];
     [|King of Heart's; Queen of Heart's; 9 of Diamond's; 10 of Spade's;
       Jack of Spade's|]; ...]

which seems to work.

Regards,

Michael

By on 5/7/2009 9:00 AM ()

Thank you guys so much. I have a lot to learn :)

By on 5/7/2009 11:54 AM ()
By on 5/7/2009 12:42 PM ()

you can do this

I assume CardValue returns an integer

1
2
3
4
5
6
7
let rec fiveSucc = function
  | n1::n2::n3::n4::n5::ns when (n2=n1+1 && n3=n2+1 && n4=n3+1 && n5=n4+1) -> true
  | n::ns -> fiveSucc ns
  | _ -> false

let ContainsStraight cards = 
   cards |> List.map CardModule.CardValue |> List.sort compare |> fiveSucc
By on 5/7/2009 8:57 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper