# dealing out 5 hands of cards, each containing 5 cards

Submitted by metaperl on Sun, 09/04/2005 - 10:22pm.

I helped someone out in `#haskell`

with the problem stated in the subject by writing the code below. I'm a bit rusty (and never was very good) at Haskell, so any pointers on how to improve the code I supplied to him are appreciated.

```
```cards = [1..52]

dropAmount = [ d*5 | d <- [0 .. 4 ] ]

hand cards = map (\d -> (take 5 $ drop d cards)) dropAmount

- metaperl's blog
- Login to post comments

Choose whatever you can read and understand.

I think I like this one best:

`hand = take 5 . List.unfoldr (\l -> Just (take 5 l, drop 5 l))`

This works too:

`hand cards = take 5 $ map (take 5 . (`drop` cards)) [0,5..]`

Making dtlin's first solution even more succint (and probably less readable to beginners), use the Prelude function splitAt, which combines take and drop. So:

hands = take 5 . List.unfoldr (Just . splitAt 5)

I came up with two approaches, although I agree that whatever you (or he) find most readable is best. I generalized the problem slightly to dealing

`N`

hands of`M`

cards out of a deck.Here was my first solution:

dealHands :: Int -> Int -> [a] -> [[a]]

dealHands handSize numHands deck = take numHands $ allHands handSize deck

where allHands handSize deck =

let (hand, deck') = splitAt handSize deck

fullHand = length hand == handSize

remaining = allHands handSize deck'

in if fullHand

then hand:remaining

else []

And the second (which can be made much more succinct):

dealHands :: Int -> Int -> [a] -> [[a]]

dealHands handSize numHands deck =

let

-- Decks with the top handSize cards successively removed

decks = iterate (drop handSize) deck

-- The top handSize cards from each of the above decks

potentialHands = map (take handSize) decks

-- All hands of handSize from the deck, down to a hand with not

-- enough cards (the deck is exhausted)

allHands = takeWhile fullHand potentialHands

in -- Get the top numHands hands from all possible hands

take numHands allHands

where

-- Return whether this hand has a sufficient number of cards

fullHand hand = length hand == handSize

Hmm,

`hand = take 5 . map (take 5) . iterate (drop 5)`

(stolen from the above) is possibly more elegant than`hand = take 5 . List.unfoldr (Just . splitAt 5)`

. Very nice.And I think that the

`fullHand`

checks are silly... I'd be perfectly happy with`dealHands 2 2 [1] == [[1], []]`

.