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
Nhands ofMcards 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 thanhand = take 5 . List.unfoldr (Just . splitAt 5). Very nice.And I think that the
fullHandchecks are silly... I'd be perfectly happy withdealHands 2 2 [1] == [[1], []].