2

I'm representing cards in poker as letters (lower and uppercase) in order to store them efficiently. I basically now need a custom sorting function to allow calculations with them.

What is the fastest way to sort letters in Python using

['a', 'n', 'A', 'N', 'b', 'o', ....., 'Z']

as the ranks rather than

['A', 'B', 'C', 'D', 'E', 'F', ....., 'z']

which is the default?


Note, this sorting is derived from:

import string        
c = string.letters[:13]        
d = string.letters[13:26]        
h = string.letters[26:39]        
s = string.letters[39:]        

'a' = 2 of clubs
'n' = 2 of diamonds 
'A' = 2 of hearts
'N' = 2 of spades
etc
PascalVKooten
  • 20,643
  • 17
  • 103
  • 160
  • Why don't you just use a `tuple`? (suit, rank). Ie. `(0, 2)` for two of hearts, `(1, 2)` for two of spades. You can then use the default sort function. – GWW May 29 '14 at 18:24
  • let me guess: are you taking the class at udacity? – Mihai Zamfir May 29 '14 at 18:24
  • @MihaiZamfir Nope, no idea what that is. – PascalVKooten May 29 '14 at 18:26
  • @GWW It's for some competition and there are a few limitations. File size cannot be above 8mb, 750mb ram, maximum 5 seconds to load. This is basically the only way to do it thus far. – PascalVKooten May 29 '14 at 18:26
  • if you want to implement a poker game take the first class on this course (it is teached by the director of reasearch at Google. It is a brilliant class with an amaizing teacher): https://www.udacity.com/course/cs212 – Mihai Zamfir May 29 '14 at 18:28
  • @MihaiZamfir Thanks, I signed up, but I have covered all of these things myself already. Two weeks ago this might have been useful... – PascalVKooten May 29 '14 at 18:33
  • @MihaiZamfir More specifically, all the outcomes he is testing for I have already computed, which I now have stored in an efficient format in a file. – PascalVKooten May 29 '14 at 18:35
  • @PascalvKooten If I corectly remember , he uses a ranking function to sort the power of each hand. This might be useful to you – Mihai Zamfir May 29 '14 at 18:43
  • @MihaiZamfir I already have the "power", represented by an integer value. – PascalVKooten May 29 '14 at 18:56

2 Answers2

4

You can provide a key function to sorted, this function will be called for each element in the iterable and the return value will be used for the sorting instead of the elements value.

In this case it might look something like the following:

order = ['a', 'n', 'A', 'N', 'b', 'o', ....., 'Z']

sorted_list = sorted(some_list, key=order.index)

Here is a brief example to illustrate this:

>>> order = ['a', 'n', 'A', 'N']
>>> sorted(['A', 'n', 'N', 'a'], key=order.index)
['a', 'n', 'A', 'N']

Note that to make this more efficient you may want to use a dictionary lookup for your key function instead of order.index, for example:

order = ['a', 'n', 'A', 'N', 'b', 'o', ....., 'Z']
order_dict = {x: i for i, x in enumerate(order)}

sorted_list = sorted(some_list, key=order_dict.get)
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • This is the one. Is it going to be the same speed though as simply using the standard alphanumerical sorting? – PascalVKooten May 29 '14 at 18:22
  • 1
    It will be slower because the `key` function needs to be called for each element. Also `order.index` is not the most efficient way to do this, it would be better to construct a dictionary for your order, for example `{'a': 0, 'n': 1, 'A': 2, ...}` and then use `order.get` as the key function. – Andrew Clark May 29 '14 at 18:25
  • Right, indeed that makes sense. – PascalVKooten May 29 '14 at 18:28
  • I was just hoping there might be something to replace "alphanumeric" sorting at the lowest level such that `sorted(x)` results in the fastest possible sorting. – PascalVKooten May 29 '14 at 18:36
0

Store [edit: not store, use internally] them as numbers ordered by value and only convert to letters when displaying them.

Edit: if 1 byte values are required then you can have the cards in the range 1:52 as characters, then, again, convert to the proper letters when displaying and storing them.

hdante
  • 7,685
  • 3
  • 31
  • 36
  • Storing them as numbers is not possible for the size of the data reason. Besides, it is efficient to use 2*26 letters, you only need 1 character representation (width = 1), whereas you would need width=2 with a numerical representation for 52 unique cards. – PascalVKooten May 30 '14 at 08:34
  • I don't really believe there's a field size constraint for the problem you're solving, since you're not even using the most compressed form, but I'll answer as if it were legitimate. I believe I wrote incorrectly, I meant to use numbers as the program "internal representation", so that you can operate on them as numbers and convert to letters for the "external representation", both for storing and for displaying it. I'll fix the answer to mean that. Additionally, the numbers may be 1 byte wide. Just store them as characters (not with their poker meaning, but with their value). – hdante May 30 '14 at 15:27