#!/usr/bin/python3 import datetime # comb() is much faster #def combinations(s, size): # if (len(s) < size): # return # if (size == 0): # yield [] # return # for r in combinations(s[1:], size - 1): # yield [s[0]] + r # for r in combinations(s[1:], size): # yield r def comb(items, n): for i in range(len(items)): v = items[i:i+1] if n == 1: yield v else: rest = items[i+1:] for c in comb(rest, n-1): yield v + c class Card: def __init__(self, number, suit): self.number = number self.suit = suit def __repr__(self): return self.__str__() def __str__(self): return "%s%s" % (self.number, self.suit) def __unicode__(self): return "%s%s" % (self.number, self.suit) suits = ['P','R','G','B'] def generateTargetDeck(): deck = [] for x in range(0,10): deck.append(Card(x, 'W')) for s in suits: deck.append(Card(x, s)) if (x != 0 and x != 9): deck.append(Card(x, s)) return deck class TargetAlgo: def __init__(self, name): self.name = name self.count = 0 def getSuitDistribution(self, cards): dist = {'W': 0, 'P': 0, 'R': 0, 'G': 0, 'B': 0} for card in cards: dist[card.suit] += 1 return dist def calculate(self, cards): pass def report(self): print("%s: %d" % (self.name, self.count)) class Flush3Algo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'flush 3 cards specific suit') def calculate(self, cards): dist = self.getSuitDistribution(cards) if (dist['W'] + dist['P'] >= 3): self.count += 1 class Flush4Algo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'flush 4 cards any suit') def calculate(self, cards): dist = self.getSuitDistribution(cards) if (dist['W'] + dist['P'] >= 4 or dist['W'] + dist['R'] >= 4 or dist['W'] + dist['G'] >= 4 or dist['W'] + dist['B'] >= 4): self.count += 1 class Flush5Algo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'flush 5 cards any suit') def calculate(self, cards): dist = self.getSuitDistribution(cards) if (dist['W'] + dist['P'] >= 5 or dist['W'] + dist['R'] >= 5 or dist['W'] + dist['G'] >= 5 or dist['W'] + dist['B'] >= 5): self.count += 1 class StraightFlush3SpecAlgo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'straight flush 3 cards specific suit') def calculate(self, cards): # Only look at cards that could be purple. possibleCards = [card for card in cards if card.suit == 'P' or card.suit == 'W'] nums = [card.number for card in possibleCards] nums.sort() for num in nums: if (num+1 in nums) and (num+2 in nums): self.count += 1 return class Straight5Algo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'straight 5 cards') def calculate(self, cards): nums = [card.number for card in cards] nums.sort() for num in nums: if (num+1 in nums) and (num+2 in nums) and (num+3 in nums) and (num+4 in nums): self.count += 1 return class Straight4With6Algo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'straight 4 cards including a 6') def calculate(self, cards): nums = [card.number for card in cards] nums.sort() for num in nums: if (num >= 3 and num <= 6) and (num+1 in nums) and (num+2 in nums) and (num+3 in nums): self.count += 1 return class Straight3With2Algo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'straight 3 cards including a 2') def calculate(self, cards): nums = [card.number for card in cards] for num in nums: if (num >= 0 and num <= 2) and (num+1 in nums) and (num+2 in nums): self.count += 1 return class Straight3With4Algo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'straight 3 cards including a 4') def calculate(self, cards): nums = [card.number for card in cards] for num in nums: if (num >= 2 and num <= 4) and (num+1 in nums) and (num+2 in nums): self.count += 1 return class FullHouseAlgo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'full house') def calculate(self, cards): nums = [card.number for card in cards] dict = {} for num in nums: if num not in dict: dict[num] = 1 else: dict[num] += 1 has3OrMore = 0 has2OrMore = 0 for x in dict: if (dict[x] >= 3): has3OrMore += 1 has2OrMore += 1 elif (dict[x] >= 2): has2OrMore += 1 if (has3OrMore >= 1 and has2OrMore >= 2): self.count += 1 class Odd5Algo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, '5 odd cards') def calculate(self, cards): nums = [card.number for card in cards] if (len([x for x in nums if x % 2 == 1]) >= 5): self.count += 1 class TwoPairAlgo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'two pair') def calculate(self, cards): nums = [card.number for card in cards] dict = {} for num in nums: if num not in dict: dict[num] = 1 else: dict[num] += 1 has2OrMore = 0 for x in dict: if (dict[x] >= 2): has2OrMore += 1 if (has2OrMore >= 2): self.count += 1 class ThreeOfAKindAlgo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, '3 of a kind') def calculate(self, cards): nums = [card.number for card in cards] dict = {} for num in nums: if num not in dict: dict[num] = 1 else: dict[num] += 1 has3OrMore = 0 for x in dict: if (dict[x] >= 3): has3OrMore += 1 if (has3OrMore >= 1): self.count += 1 class TotalLessEqual4(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'total <= 4') def calculate(self, cards): nums = [card.number for card in cards] nums.sort() if (nums[0] + nums[1] + nums[2] <= 4): self.count += 1 class SkipStraightAlgo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'skip straight') def calculate(self, cards): nums = [card.number for card in cards] for num in nums: if (num+2 in nums) and (num+4 in nums) and (num+6 in nums): self.count += 1 return def canMakeMixedStraightHelper(ourSuits, doneSuits): if len(doneSuits) == 4: return True if len(ourSuits) == 0: return False # Try something from the first suit. curSuitSet = ourSuits[0] ourSuits = ourSuits[1:] while (len(curSuitSet) > 0): curSuit = curSuitSet.pop() if (curSuit not in doneSuits): doneSuits.add(curSuit) if (canMakeMixedStraightHelper(ourSuits, doneSuits)): return True doneSuits.remove(curSuit) return False def canMakeMixedStraight(ourSuits): return canMakeMixedStraightHelper(ourSuits, set()) class MixedStraightAlgo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'mixed straight') def calculate(self, cards): nums = [card.number for card in cards] for num in nums: if (num+1 in nums) and (num+2 in nums) and (num+3 in nums): # Check if they're all different suits (or wilds) ourSuits = [set(), set(), set(), set()] for i in range(4): curSuits = [card.suit for card in cards] for suit in curSuits: if (suit == 'W'): ourSuits[i].add('P') ourSuits[i].add('R') ourSuits[i].add('G') ourSuits[i].add('B') else: ourSuits[i].add(suit) # Ugh, we have to try a lot of crap here. if (canMakeMixedStraight(ourSuits)): self.count += 1 class StraightFlush3AnyAlgo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'straight flush 3 cards any suit') def calculate(self, cards): # Only look at cards that could be purple. for suit in suits: possibleCards = [card for card in cards if card.suit == suit or card.suit == 'W'] nums = [card.number for card in possibleCards] for num in nums: if (num+1 in nums) and (num+2 in nums): self.count += 1 return class StraightFlush4AnyAlgo(TargetAlgo): def __init__(self): TargetAlgo.__init__(self, 'straight flush 4 cards any suit') def calculate(self, cards): # Only look at cards that could be purple. for suit in suits: possibleCards = [card for card in cards if card.suit == suit or card.suit == 'W'] nums = [card.number for card in possibleCards] for num in nums: if (num+1 in nums) and (num+2 in nums) and (num+3 in nums): self.count += 1 return if (__name__ == '__main__'): startTime = datetime.datetime.now() deck = generateTargetDeck() count = 0 algosToRun = [StraightFlush3AnyAlgo(), StraightFlush4AnyAlgo()] for x in comb(deck,6): count = count + 1 for algo in algosToRun: algo.calculate(x) print("Total iterations: %d" % count) for algo in algosToRun: algo.report() endTime = datetime.datetime.now() print("Time taken: %s" % (str(endTime - startTime)))