0

I'm writing a gin card game that deals with sets and melds of cards. A set is 3 or 4 cards with the same rank (i.e. 9c,9d,9h). A meld is a run of cards of the same rank (i.e. 8c,9c,10c). I want to sort a combined list of melds and sets.

Cards are represented like so:

class Card:
  def __init__(self, rank, suit):
    self.rank = rank
    self.suit = suit

Cards are stored in CardGroups like so:

class CardGroup:
  def __init__(self, card_list):
    self.cards = []
    for c in card_list:
      self.cards.append(c)

Here's an example with the hand 2c,2h,2d,4h,5d,5s,5c,6c,7c,8c:

The melds in this hand all deal with clubs: (5c,6c,7c) and (6c,7c,8c). The sets are (2c,2d,2h) and (5c,5d,5s).

The resulting combined list might combine like so (melds, then sets):

unsorted_list = [ CardGroup([Card(5,'c'), Card(6,'c'), Card(7,'c')], 
                  CardGroup([Card(6,'c'), Card(7,'c'), Card(8,'c')],
                  CardGroup([Card(2,'c'), Card(2,'d'), Card(2,'h')], 
                  CardGroup([Card(5,'c'), Card(5,'d'), Card(5,'s')] ]

The resulting combined list should exist like so (card by card comparison):

sorted_list   = [ CardGroup([Card(2,'c'), Card(2,'d'), Card(2,'h')], 
                  CardGroup([Card(5,'c'), Card(5,'d'), Card(5,'s')],
                  CardGroup([Card(5,'c'), Card(6,'c'), Card(7,'c')], 
                  CardGroup([Card(6,'c'), Card(7,'c'), Card(8,'c')] ]

Note that the second and third CardGroup both start with 5c. It is important that these are sorted correctly. In the case that we have a 4-set like 2c,3c,4c,5c we also implicitly have a 3-set of 2c,3c,4c. When sorting these two, we want the 3-set to come before the 4-set.

Things I've Tried:

unsorted_list.sort(key=lambda x: x.cards)
unsorted_list.sort(key=lambda x: x.cards[0])
unsorted_list.sort(key=lambda x: tuple(x.cards))

Thank you for the help!

Edit: Using a comparison operator was suggested as an answer. Here are the unit tests for such a solution:

Class TestCard:
    def test___cmp__(self):
        card1 = Card(5, 'd')
        card2 = Card(6, 'c')
        card3 = Card(6, 's')

        self.assertLessEqual(card1.__cmp__(card2), -1)
        self.assertLessEqual(card1.__cmp__(card3), -1)
        self.assertEqual(card1.__cmp__(card1), 0)

        self.assertGreaterEqual(card2.__cmp__(card1), 1)
        self.assertLessEqual(card2.__cmp__(card3), -1)

        self.assertGreaterEqual(card3.__cmp__(card1), 1)
        self.assertGreaterEqual(card3.__cmp__(card2), 1)
1
  • Probably better to define comparison operations in your classes. Example Commented Mar 20, 2015 at 6:48

1 Answer 1

1

I believe this might help:

class Card:
  # ...
  def __cmp__(self, other):
    r = self.rank.__cmp__(other.rank)
    if not r:
      return self.suit.__cmp__(other.suit)
    return r

class CardGroup:
  # ...
  def __cmp__(self, other):
    return cmp(self.cards, other.cards)

Now you should be able to use just unsorted_list.sort().

Sign up to request clarification or add additional context in comments.

1 Comment

Beautiful! Thank you @Amadan. I'll write my own and compare it against yours. Cheers.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.