Search code examples
haskellquickcheck

Quickcheck card generator


Ok, so I hacked this :

prop = forAll genCards $ \cards -> collect (go cards == True) $ isFlush cards == go cards

go cards = (length . nub .  map (\w -> last w)) cards == 1

genCard :: Gen String
genCard = elements[ "1C", "2C", "3C", "4C", "5C", "6C", "7C", "9C", "KC", "QC", "JC", "1H", "2H", "3H", "4H", "5H", "6H", "7H", "9H", "KH", "QH", "JH", "1S", "2S", "3S", "4S", "5S", "6S", "7S", "9S", "KS", "QS", "JS", "1D", "2D", "3D", "4D", "5D", "6D", "7D", "9D", "KD", "QD", "JD"] 

genCards :: Gen [String]
genCards = do
  replicateM 5 genCard

However there has to be a better way, but I could not figure out how to combine a generator for numbers + one for suits, and a way to ensure there are more flushes generated (it is ~0.4% by random chance according to collect).


Solution

  • To generate a card:

    genVal = elements "123456789JQK"
    genSuit = elements "CHSD"
    
    genCard = do
        val <- genVal
        suit <- genSuit
        return [val, suit]
    

    To generate a flush:

    genFlush = do
        vals <- replicateM 5 genVal
        suit <- genSuit
        return [[val, suit] | val <- vals]
    

    My genFlush, like your genCards, does not guarantee that the cards generated in this way are distinct. You can select a given probability for a flush vs. a normal hand with frequency; e.g. for 60% flushes:

    genHandThatIsProbablyAFlush = frequency
        [ (3, genFlush)
        , (2, genCards)
        ]