• Bonus set solution by sirpengi
  • 5 years, 9 months ago
  • Download | Raw
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,]
	return list(itertools.chain(*ret))

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])
			self.value = value
			self.suit = suit

	def __eq__(self, other):
		return (self.value == other.value)

	def __lt__(self, other):
		return self.value < other.value
	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)

	def s_to_value(s):
			v = int(s)
		except (TypeError, ValueError):
			v = {"T":10, "J":11, "Q":12, "K":13, "A":14}.get(s)
		return v

	def s_to_suit(s):
		return s

	def minv(self):
		return 1 if self.value == 14 else self.value

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

	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:
				if _c.value >= 5:

		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

		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:
					v = _c.value
					return [8, v]

		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)

		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)]

		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)

		if (has_straight):
			v = max(i.minv for i in run_starts)
			if v == 14:
				v = 1
			return [4, v]

		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)
				# 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):
			for _c in itertools.combinations(self.community, 3):
				for _p in itertools.combinations(p, 2):
					ret.append(cardset(i, chain(_p, _c)))

		results = list(reversed(sorted(ret)))
		best = results[0]
		if debug:
			print [(r.playern, r.result) for r in results]
		return sorted(set([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__()
	j = 0
	while 1:
		j += 1
		if debug:
			print "========", j, "============"
			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:

if __name__ == "__main__":
	if len(sys.argv) > 1:
		print "You need to pass in a file yo"


lzm bas adv bon 200
sirpengi bas adv bon 200
sixthgear bas adv bon 190
mserrano bas adv bon 190
robbinsr bas adv bon 190
synx bas adv bon 50

What do?

  1. Write your program according to the problem description
  2. Download the basic input set. The timer will start.
  3. Feed the input file to your program and save the output.
  4. Upload the output file along with your source code. If it is correct, you will receive points. If not you may try again until the timer expires.
  5. If the timer expires. You may try again, but a new input file will be generated.
  6. Repeat fot each set.

Note: The input sets use unix line endings (\n) and the verifier expects them as well.

Come Chat!

Join channel ##proggit on freenode.


Having issues with the the site? Let us know.