Commits

Shu Zong Chen  committed 861a05a

blah

  • Participants

Comments (0)

Files changed (2)

+import os
+import sys
+import itertools
+from collections import Counter
+from functools import total_ordering
+
+debug = False
+
+def maxs(itr, n):
+	for i in sorted(itr, reverse=True):
+		if n < 1:
+			raise StopIteration
+		yield i
+		n = n - 1
+
+def chain(*args):
+	ret = []
+	for i in args:
+		if not hasattr(i, "__iter__"):
+			i = [i,]
+		ret.append(i)
+	return list(itertools.chain(*ret))
+
+@total_ordering
+class card(object):
+	def __init__(self, s=None, suit=None, value=None):
+		if s is not None:
+			self.s = s
+			self.value = card.s_to_value(s[0])
+			self.suit = card.s_to_suit(s[1])
+		else:
+			self.value = value
+			self.suit = suit
+
+	def __eq__(self, other):
+		return (self.value == other.value)
+
+	def __lt__(self, other):
+		return self.value < other.value
+	
+	@property
+	def hash(self):
+		return "{}{}".format(self.value, self.suit)
+
+	def __repr__(self):
+		return self.hash
+
+	def next_card(self):
+		v = self.value + 1
+		s = self.suit
+		if v == 15:
+			v = 2
+		return card(suit=s, value=v)
+
+	def clone(self):
+		return card(suit=self.suit, value=self.value)
+
+	@staticmethod
+	def s_to_value(s):
+		try:
+			v = int(s)
+		except (TypeError, ValueError):
+			v = {"T":10, "J":11, "Q":12, "K":13, "A":14}.get(s)
+		return v
+
+	@staticmethod
+	def s_to_suit(s):
+		return s
+
+	@property
+	def minv(self):
+		return 1 if self.value == 14 else self.value
+
+@total_ordering
+class cardset(object):
+	def __init__(self, playern, cards):
+		self.playern = playern
+		self.cards = sorted(cards)
+		self.card_hashes = set(c.hash for c in cards)
+		self.v_hashes = set(c.value for c in cards)
+		self._result = None
+
+	@property
+	def result(self):
+		if self._result == None:
+			self._result = self.get_result()
+		return self._result
+
+	def get_result(self):
+		value_counts = Counter()
+		suit_counts = Counter()
+		run_starts = []
+		for c in self.cards:
+			value_counts[c.value] += 1
+			suit_counts[c.suit] += 1
+			_c = c.clone()
+			for _ in range(4):
+				_c = _c.next_card()
+				if _c.value not in self.v_hashes:
+					break
+			else:
+				if _c.value >= 5:
+					run_starts.append(c)
+
+		max_same_suit = max(suit_counts.values())
+		max_same_value = max(value_counts.values())
+		has_flush = max(suit_counts.values()) > 4
+		has_straight = len(run_starts) > 0
+
+		# STRAIGHT FLUSH
+		if (has_flush and has_straight):
+			for i in run_starts:
+				_c = i
+				for c in range(4):
+					_c = _c.next_card()
+					if _c.hash not in self.card_hashes:
+						break
+				else:
+					v = _c.value
+					return [8, v]
+
+		# FOUR OF A KIND
+		if (max_same_value >= 4):
+			fourk = [k for k, v in value_counts.items() if v == 4]
+			v = max(fourk)
+			sub = max(i for i in self.v_hashes if i != v)
+			return chain(7, v, sub)
+
+		# FULL HOUSE
+		if (max_same_value >= 3):
+			majors = [k for k, v in value_counts.items() if v == 3]
+			minors = [k for k, v in value_counts.items() if v == 2]
+			if len(majors) > 1:
+				return chain(6, list(maxs(majors, 2)))
+			if len(majors) and len(minors):
+				return [6, max(majors), max(minors)]
+
+		# FLUSH
+		if (has_flush):
+			suits = [k for k, v in suit_counts.items() if v == max_same_suit]
+			# only one possible flush suit
+			suit = suits[0]
+			cards = sorted([c.value for c in self.cards if c.suit == suit], reverse=True)
+			return chain(5, cards)
+
+		# STRAIGHT
+		if (has_straight):
+			v = max(i.minv for i in run_starts)
+			if v == 14:
+				v = 1
+			return [4, v]
+
+		# THREE OF A KIND
+		if max_same_value >= 3:
+			trips = [k for k,v in value_counts.items() if v == 3]
+			v = max(trips)
+			subs = list(maxs([c.value for c in reversed(self.cards) if c.value != v], 2))
+			return chain(3, v, subs)
+
+		if max_same_value >= 2:
+			pairs = [k for k,v in value_counts.items() if v == 2]
+			if len(pairs) > 1:
+				# TWO PAIR
+				twop = sorted(list(maxs(pairs, 2)), reverse=True)
+				sub = max(c.value for c in self.cards if c.value not in twop)
+				return chain(2, twop, sub)
+			else:
+				# ONE PAIR
+				v = max(pairs)
+				subs = list(maxs([c.value for c in self.cards if c.value != v], 3))
+				return chain(1, v, subs)
+
+		subs = list(maxs([c.value for c in self.cards], 5))
+		return chain(0, subs)
+	
+	def __eq__(self, other):
+		a = tuple(self.result)
+		b = tuple(other.result)
+		return a == b
+
+	def __lt__(self, other):
+		a = tuple(self.result)
+		b = tuple(other.result)
+		return a < b
+
+class gamestate(object):
+	def __init__(self, community, players):
+		self.community = community
+		self.players = players
+
+	def who_won(self):
+		ret = []
+		for i, p in enumerate(self.players):
+			ret.append(cardset(i, chain(p, self.community)))
+		results = list(reversed(sorted(ret)))
+		best = results[0]
+		if debug:
+			print [(r.playern, r.result) for r in results]
+		return sorted([cs.playern for cs in results if cs.result == best.result])
+
+def run(fn):
+	with open(fn) as fh:
+		data = fh.readlines()
+	i = data.__iter__()
+	i.next()
+	j = 0
+	while 1:
+		j += 1
+		if debug:
+			print "========", j, "============"
+		try:
+			num_players = int(i.next())
+			community = [card(s) for s in i.next().split()]
+			players = []
+			for p in range(num_players):
+				players.append([card(s) for s in i.next().split()])
+			if debug:
+				print community
+				print players
+			gs = gamestate(community, players)
+			res = gs.who_won()
+			print " ".join([str(_) for _ in res])
+		except StopIteration:
+			break
+
+if __name__ == "__main__":
+	if len(sys.argv) > 1:
+		run(sys.argv[1])
+	else:
+		print "You need to pass in a file yo"
+3
+4
+4h 2s 4s 7d 8d
+Tc 4d
+As 3h
+Qd 4c
+9h Qc
+3
+Kd 9s 4d Jd 2h
+Jh Js
+As 5c
+7d 4s
+4
+9s 7s Jd 7d Qs
+Qh 9c
+5h 7h
+5s 9h
+4h 7c
+4
+9s 7s Jd 7d Qs
+5h 7h
+Qh Qc
+5s 9h
+4h 7c