When I first started APL in August 2012, I was pointed in the direction of the annual International APL Problem Solving Competition run by Dyalog. I used it as method to practice what I had learnt. While I looked at the problems I saw one based on the poker game Texas hold ’em. It revolved around calculating the value of a hand with a series of tasks about calculating stats and determining best hands in different circumstances. I decided to take a step back and look at dealing with a deck of cards.
The Task
The first thing to do was initialise a deck of cards. So I set the card values and the suits:
CardValues←'2' '3' '4' '5' '6' '7' '8' '9' '10' 'J' 'Q' 'K' 'A'
Suits←'H' 'D' 'S' 'C'
I then needed to combine the two in a way that would give me a full suit of each (a full set of card values for each suit). Using the catenate function (,
) we can join arrays together (e.g ‘a’,’b’
returns ab
). When used with outer product (∘.
) like this ∘.,
it will catenate each possible combination of two vectors.
The comma symbol, when used monadically (meaning with only the right argument) means ravel, which flattens complex structures into a vector (i.e if table
is a 2 by 2 matrix of the numbers 1-4, then using ravel on it like this ,table
gives us 1 2 3 4
a flattened version of table
).
Putting this all together gives us:
Deck←,CardValues∘.,Suits
Deck
is then a flat vector of 52 items, each of which is a different card. Now we have all the available cards from a standard 52 card deck. I am also using reshape (⍴
) to display the contents of the variable Deck
in a 13 row by 4 column matrix to make it more readable.
13 4⍴Deck
2H 2D 2S 2C
3H 3D 3S 3C
4H 4D 4S 4C
5H 5D 5S 5C
6H 6D 6S 6C
7H 7D 7S 7C
8H 8D 8S 8C
9H 9D 9S 9C
10H 10D 10S 10C
JH JD JS JC
QH QD QS QC
KH KD KS KC
AH AD AS AC
The rho (⍴
) symbol when used dyadically (meaning with two arguments; a left and a right argument) as above will reshape an array (right argument) by the dimensions (left argument).
To then deal a hand of cards from the Deck
I used the query symbol (?
) which when used dyadically means deal. Deal picks a random selection of numbers from 1 to the number specified as the right argument (i.e 1?10
returns 1 random number between 1 and 10). Using the Deal
function against the length of the Deck
(⍴Deck
this returns the shape/length of the right argument when used monadically) then using the result to index ([x]
i.e 'abcdef'[3]
returns c
) into the Deck
and assign (←
assign right argument into left argument) the result into the variable Hand
.
Hand←Deck[2?⍴Deck]
We then want to remove the cards we have already dealt from Deck
. The without function (~
) removes the right argument from the left (e.g. 'abcdef'~'bce'
returns 'adf'
). We can use this function as an operand in a modified assignment to remove the Hand
from the Deck
.
Deck~←Hand
I wrote this code when I had only been doing APL for a month or so. It was a very interesting and educational task to undertake and I learnt a lot of new techniques. Is there anything that I could have done better? Are there any interesting alternatives to what I wrote?
If you would like to find out more about the competition or the problem I have mentioned (the 2012 competition under previous years near the bottom of the page) see Dyalog’s International Problem Solving Competition.