Most football fans love it for the goals and excitement. Well, this Kata doesn't.
You are to handle the referee's little notebook and count the players who were sent off for fouls and misbehavior.

The rules:
Two teams, named "A" and "B" have 11 players each; players on each team are numbered from 1 to 11.
Any player may be sent off the field by being given a red card.
A player can also receive a yellow warning card, which is fine, but if he receives another yellow card, he is sent off immediately (no need for a red card in that case). 
If one of the teams has less than 7 players remaining, the game is stopped immediately by the referee, and the team with less than 7 players loses. 

A `card` is a string with the team's letter ('A' or 'B'), player's number, and card's color ('Y' or 'R') - all concatenated and capitalized.
e.g the card `'B7Y'` means player #7 from team B received a yellow card.

The task: Given a list of cards (could be empty), return the number of remaining players on each team at the end of the game (as a tuple of 2 integers, team "A" first).
If the game was terminated by the referee for insufficient number of players, you are to stop the game immediately, and ignore any further possible cards.

Note for the random tests: If a player that has already been sent off receives another card - ignore it.

Source: codewars | Difficulty: EASY
Tags: Fundamentals

Data structures

Starter code: def men_still_standing(cards):
	

Solutions:
def men_still_standing(cards):
	A = {k: 0 for k in range(1, 12)}
	B = A.copy()
	for card in cards:
		team = A if card[0] == 'A' else B
		player = int(card[1:-1])
		color = card[-1]
		if player not in team:
			continue
		team[player] += 1 if color == 'Y' else 2
		if team[player] >= 2:
			del team[player]
		if len(team) < 7:
			break
	return (len(A), len(B))


class Player:

	def __init__(self):
		self.red_cards = 0
		self.yellow_cards = 0

	@property
	def excluded(self):
		return self.red_cards or self.yellow_cards > 1

	def receive_red(self):
		self.red_cards += 1

	def receive_yellow(self):
		self.yellow_cards += 1

class Team:

	def __init__(self, size):
		self.size = size
		self.players = {number: Player() for number in range(1, size + 1)}

	@property
	def count(self):
		return sum((not player.excluded for player in list(self.players.values())))

	def give_red(self, number):
		self.players[number].receive_red()

	def give_yellow(self, number):
		self.players[number].receive_yellow()

def men_still_standing(cards):
	teams = {'A': Team(11), 'B': Team(11)}
	actions = {'R': Team.give_red, 'Y': Team.give_yellow}
	import re
	pattern = '(A|B)([0-9]+)(R|Y)'
	for card in cards:
		match = re.match(pattern, card)
		(team, player, color) = match.group(1, 2, 3)
		actions[color](teams[team], int(player))
		if any((team.count < 7 for team in list(teams.values()))):
			break
	return tuple((team.count for team in list(teams.values())))


def men_still_standing(cards):
	teams = {'A': dict.fromkeys(range(1, 12), 2), 'B': dict.fromkeys(range(1, 12), 2)}
	for card in cards:
		(t, number, color) = (card[:1], int(card[1:-1]), card[-1:])
		team = teams[t]
		if number not in team:
			continue
		team[number] -= 2 if color == 'R' else 1
		if team[number] <= 0:
			del team[number]
			if len(team) < 7:
				break
	return (len(teams['A']), len(teams['B']))


def men_still_standing(cards):
	(players, Y, R) = ({'A': 11, 'B': 11}, set(), set())
	for c in cards:
		if c[:-1] not in R:
			players[c[0]] -= c[-1] == 'R' or c[:-1] in Y
		if 6 in players.values():
			break
		(R if c[-1] == 'R' or c[:-1] in Y else Y).add(c[:-1])
	return (players['A'], players['B'])


def men_still_standing(cards):
	print(cards)
	playersA = {}
	playersB = {}
	countA = 11
	countB = 11
	for i in range(1, 12):
		playersA[i] = 2
		playersB[i] = 2
	for foul in cards:
		team = foul[0]
		countA = 11
		countB = 11
		if len(foul) == 4:
			number = int(foul[1:3])
			cardColor = foul[3]
		else:
			number = int(foul[1])
			cardColor = foul[2]
		if cardColor == 'R':
			cardValue = 2
		else:
			cardValue = 1
		if team == 'A':
			playersA[number] -= cardValue
		else:
			playersB[number] -= cardValue
		for value in list(playersA.values()):
			if value <= 0:
				countA -= 1
		for value in list(playersB.values()):
			if value <= 0:
				countB -= 1
		if countA < 7 or countB < 7:
			return (countA, countB)
	return (countA, countB)


def men_still_standing(cards):
	a = {'n': 11}
	b = {'n': 11}
	for x in cards:
		jg(a if x[0] == 'A' else b, x)
		if a['n'] < 7 or b['n'] < 7:
			break
	return (a['n'], b['n'])

def jg(t, x):
	o = t.get(x[1:-1])
	if o == 1:
		t[x[1:-1]] = -1
		t['n'] -= 1
	elif o == None:
		if x[-1] == 'R':
			t[x[1:-1]] = -1
			t['n'] -= 1
		if x[-1] == 'Y':
			t[x[1:-1]] = 1


def men_still_standing(cards):
	sent_off_A = set()
	sent_off_B = set()
	for (i, card) in enumerate(cards):
		if card.endswith('R'):
			sent_off_B.add(card[1:-1]) if card[0] == 'B' else sent_off_A.add(card[1:-1])
		elif card.endswith('Y') and cards[:i].count(card) > 0:
			sent_off_B.add(card[1:-1]) if card[0] == 'B' else sent_off_A.add(card[1:-1])
		if len(sent_off_A) == 5 or len(sent_off_B) == 5:
			break
	return (11 - len(sent_off_A), 11 - len(sent_off_B))


def men_still_standing(cards):
	res = {'A': [11] + [0] * 11, 'B': [11] + [0] * 11}
	for c in cards:
		(team, num, card) = (c[0], int(c[1:-1]), c[-1])
		if res[team][num] < 2:
			res[team][num] += 1 if card == 'Y' else 2
			if res[team][num] > 1:
				res[team][0] -= 1
			if res[team][0] < 7:
				break
	return (res['A'][0], res['B'][0])


def men_still_standing(cards):
	players = [[2] * 11, [2] * 11]
	AB = {'A': 0, 'B': 1}
	penalty = {'Y': 1, 'R': 2}
	for card in cards:
		(team, number, color) = (card[0], int(card[1:-1]), card[-1])
		players[AB[team]][number - 1] -= penalty[color]
		if sum((i > 0 for i in players[AB[team]])) < 7:
			break
	return tuple((sum((i > 0 for i in x)) for x in players))


def men_still_standing(cards):
	players = [11, 11]
	dic = {}
	for string in cards:
		player = string[:-1]
		if player in dic:
			if dic[player][1] != 'out':
				dic[player][0] = 1
		elif string[len(string) - 1] == 'Y':
			dic[player] = [0, 'in']
		else:
			dic[player] = [1, 'in']
		if dic[player][0] == 1 and dic[player][1] is 'in':
			if player[0] == 'A':
				players[0] -= 1
			else:
				players[1] -= 1
			dic[player][1] = 'out'
		if players[0] < 7 or players[1] < 7:
			return tuple(players)
	return tuple(players)


def men_still_standing(cards):
	teams = {'A': [True, True, True, True, True, True, True, True, True, True, True], 'B': [True, True, True, True, True, True, True, True, True, True, True]}
	for card in cards:
		team = card[0]
		color = card[-1]
		player = int(card[1:-1]) - 1
		if color == 'R' or teams[team][player] == 'Y':
			teams[team][player] = False
		elif color == 'Y' and teams[team][player] != False:
			teams[team][player] = 'Y'
		if len([1 for (_, team) in list(teams.items()) if players_up(team) >= 7]) < 2:
			break
	return (players_up(teams['A']), players_up(teams['B']))

def players_up(players):
	return len([1 for player in players if player != False])


find = lambda d1, d2: (sum((1 for j in d1.values() if len(j) < 2 and 'R' not in j)), sum((1 for j in d2.values() if len(j) < 2 and 'R' not in j)))

def men_still_standing(a):
	d1 = {i: [] for i in range(1, 12)}
	d2 = __import__('copy').deepcopy(d1)
	for i in a:
		[d1, d2][i[0] == 'B'][int(i[1:-1])].append(i[-1])
		r = find(d1, d2)
		if any((j < 7 for j in r)):
			return r
	return find(d1, d2)


from collections import defaultdict

def men_still_standing(cards):
	book = [defaultdict(int), defaultdict(int)]
	f = lambda book: sum((-1 for b in book.values() if b > 1), 11)
	cnt = [11, 11]
	for c in cards:
		(team, num, card) = (c[0] == 'B', c[1:-1], c[-1])
		book[team][num] += (1, 2)[card == 'R']
		cnt = list(map(f, book))
		if min(cnt) < 7:
			break
	return tuple(cnt)


def men_still_standing(cards):
	A = {str(i): 0 for i in range(1, 12)}
	B = A.copy()
	for card in cards:
		if 11 - sum((1 for i in A.values() if i >= 2)) <= 6 or 11 - sum((1 for i in B.values() if i >= 2)) <= 6:
			break
		if card[-1] == 'Y':
			eval(card[0])[card[1:-1]] += 1
		elif card[-1] == 'R':
			eval(card[0])[card[1:-1]] += 2
	return (max(11 - sum((1 for i in A.values() if i >= 2)), 6), max(11 - sum((1 for i in B.values() if i >= 2)), 6))


def men_still_standing(cards):
	red = []
	yellow = []
	still_playing = {'A': 11, 'B': 11}
	for card in cards:
		if still_playing['A'] < 7 or still_playing['B'] < 7:
			break
		if card[-1:] == 'Y' and card[:-1] not in red:
			if card[:-1] not in yellow:
				yellow.append(card[:-1])
			elif card[:-1] in yellow:
				red.append(card[:-1])
				still_playing[card[:1]] -= 1
		elif card[-1:] == 'R' and card[:-1] not in red:
			red.append(card[:-1])
			still_playing[card[:1]] -= 1
	return (still_playing['A'], still_playing['B'])


def men_still_standing(cards):
	team_a = {i + 1: 0 for i in range(11)}
	team_b = team_a.copy()
	teams_dict = {'A': team_a, 'B': team_b}
	gone_players = {'A': [], 'B': []}
	for booking in cards:
		team = teams_dict[booking[0]]
		player = int(booking[1:-1])
		if player in gone_players[booking[0]]:
			continue
		if booking[-1] == 'R':
			team[player] += 1
		else:
			team[player] += 0.5
		if team[player] >= 1:
			gone_players[booking[0]].append(player)
		if len(gone_players[booking[0]]) > 4:
			break
	return tuple([11 - len(gone_players['A']), 11 - len(gone_players['B'])])


def men_still_standing(cards):
	A_sentoff = set()
	B_sentoff = set()
	for (index, card) in enumerate(cards):
		if card[-1] == 'R':
			A_sentoff.add(card[1:-1]) if card[0] == 'A' else B_sentoff.add(card[1:-1])
		elif card[-1] == 'Y' and cards[:index].count(card) > 0:
			A_sentoff.add(card[1:-1]) if card[0] == 'A' else B_sentoff.add(card[1:-1])
		if len(A_sentoff) == 5 or len(B_sentoff) == 5:
			break
	a_remaining = 11 - len(A_sentoff)
	b_remaining = 11 - len(B_sentoff)
	return (a_remaining, b_remaining)


def men_still_standing(cards):
	if cards == []:
		return (11, 11)
	(a, b) = ([1] * 11, [1] * 11)
	(dicA, dicB) = ({}, {})
	for i in cards:
		if i[-1] == 'Y':
			if i[:-1] in dicA:
				a[dicA[i[:-1]] - 1] = 0
			elif i[:-1] in dicB:
				b[dicB[i[:-1]] - 1] = 0
			elif i[0] == 'A':
				dicA[i[:-1]] = int(i[1:-1])
			else:
				dicB[i[:-1]] = int(i[1:-1])
		elif i[-1] == 'R':
			if i[0] == 'A':
				a[int(i[1:-1]) - 1] = 0
			elif i[0] == 'B':
				b[int(i[1:-1]) - 1] = 0
		if sum(a) == 6 or sum(b) == 6:
			return (sum(a), sum(b))
	return (sum(a), sum(b))


def men_still_standing(cards):
	print(cards)
	Team_A = 11
	Team_B = 11
	Yellows = []
	Reds = []
	for event in cards:
		if Team_A == 6 or Team_B == 6:
			return (Team_A, Team_B)
		else:
			print(event)
			if event[-1] == 'R' and event[0:len(event) - 1] not in Reds:
				print('Red card event')
				Reds.append(event[0:len(event) - 1])
				print('Red Cards', Reds)
				if event[0] == 'A':
					Team_A -= 1
					print('Team A remaining = ', str(Team_A))
				else:
					Team_B -= 1
					print('Team B remaining = ', str(Team_B))
			elif event[-1] == 'Y' and event[0:len(event) - 1] in Yellows and (event[0:len(event) - 1] not in Reds):
				print('2nd Yellow Card event, Player sent off', Reds)
				Reds.append(event[0:len(event) - 1])
				if event[0] == 'A':
					Team_A -= 1
					print('Team A remaining = ', str(Team_A))
				else:
					Team_B -= 1
					print('Team B remaining = ', str(Team_B))
			elif event[-1] == 'Y':
				if event[0:len(event) - 1] in Reds:
					print('Player already sent off')
				else:
					Yellows.append(event[0:len(event) - 1])
					print('Yellow card issued to', Yellows)
			else:
				print('player already sent off!')
	print(Team_A, Team_B)
	return (Team_A, Team_B)