Code golf: dealing a hand of cards
The Problem
Last night at pdx.rb, Markus Roberts gave us a code golf exercise on dealing hands of a given size from a deck of cards.
|
|
The Solution
My team checked with Markus to make sure it was okay if we clobbered the original array, then came up with this approach:
|
|
To fully explain: deal
can take an arbitrary number of arguments, which will be available in the method definition as an array called hand_sizes
. We turn each member of hand_sizes
into an actual hand of that size using Array’s pop
, which removes n elements from the end of the array and returns those removed elements. pop
is destructive, so the original array gets shorter every time we execute map
’s block. Once we’ve popped off hands of the sizes we need, the array itself (self
) is now everything that wasn’t dealt into a hand. The splat makes it so that we can concisely build the five-element array we need. (A simpler example if what the splat is doing isn’t obvious: [*[1,2,3], 4]
gives you [1,2,3,4]
.)
But since this is code golf, we had to make it as short as possible:
|
|
That’s as good as our team got, but as it turns out you can do two characters better:
|
|
What I Learned
I knew it was possible to leave out the parentheses around the arguments in a method definition (though I never do it), but I had no idea that it was valid Ruby to put the splat right up against the method name without any space. I was very surprised to discover that def deal*t
isn’t a parse error.
I wasn’t certain whether I could use a splat in [*four_element_list, fifth_element]
to get the five element list I wanted, and was pleased to discover that splats can indeed be used in this way.
I had forgotten that Array#pop
could be called with an argument. I almost always use it without an argument, which pops just one element (and returns that element rather than a one-element list of that element like pop(1)
would).