A group of N golfers wants to play in groups of G players for D days in such a way that no golfer plays more than once with any other golfer. For example, for N=20, G=4, D=5, the solution at Wolfram MathWorld is

```
 Mon:   ABCD    EFGH    IJKL    MNOP    QRST
 Tue:   AEIM    BJOQ    CHNT    DGLS    FKPR
 Wed:   AGKO    BIPT    CFMS    DHJR    ELNQ
 Thu:   AHLP    BKNS    CEOR    DFIQ    GJMT
 Fri:   AFJN    BLMR    CGPQ    DEKT    HIOS
```

Write a function that validates a proposed solution, a list of list of strings, as being a solution to the social golfer problem. Each character represents a golfer, and each string is a group of players. Rows represent days. The solution above would be encoded as:

```
 [
  ['ABCD', 'EFGH', 'IJKL', 'MNOP', 'QRST'],
  ['AEIM', 'BJOQ', 'CHNT', 'DGLS', 'FKPR'],
  ['AGKO', 'BIPT', 'CFMS', 'DHJR', 'ELNQ'],
  ['AHLP', 'BKNS', 'CEOR', 'DFIQ', 'GJMT'],
  ['AFJN', 'BLMR', 'CGPQ', 'DEKT', 'HIOS']
 ]
```

You need to make sure (1) that each golfer plays exactly once every day, (2) that the number and size of the groups is the same every day, and (3) that each player plays with every other player *at most* once.

So although each player must play every day, there can be particular pairs of players that never play together.

It is not necessary to consider the case where the number of golfers is zero; no tests will check for that. If you do wish to consider that case, note that you should accept as valid all possible solutions for zero golfers, who (vacuously) can indeed play in an unlimited number of groups of zero.

Source: codewars | Difficulty: MEDIUM
Tags: Fundamentals

Starter code: def valid(a):
	

Solutions:
def valid(a):
	d = {}
	day_length = len(a[0])
	group_size = len(a[0][0])
	golfers = {g for p in a[0] for g in p}
	for day in a:
		if len(day) != day_length:
			return False
		for group in day:
			if len(group) != group_size:
				return False
			for player in group:
				if player not in golfers:
					return False
				if player not in d:
					d[player] = set(group)
				elif len(d[player] & set(group)) > 1:
					return False
				else:
					d[player].add(group)
	return True


from itertools import permutations

def get_all_players(a):
	players_str = ''.join([''.join(day) for day in a])
	return set(list(players_str))

def all_players_play_everyday(a, players):
	for day in a:
		if not set(list(''.join(day))) == players:
			return False
	return True

def check_if_play_twice_together(a, players):
	all_2mers = list(permutations(players, 2))
	for day in a:
		for team in day:
			team_2mers = list(permutations(list(team), 2))
			for t in team_2mers:
				try:
					all_2mers.remove(t)
				except:
					return False
	return True

def valid(a):
	players = get_all_players(a)
	if len(players) < 2:
		return False
	if not all_players_play_everyday(a, players):
		return False
	return check_if_play_twice_together(a, players)


from itertools import combinations
from collections import Counter

def valid(schedule):
	(N, G) = (len(schedule[0]), len(schedule[0][0]))
	test1 = lambda s: all((len(set(''.join(groups))) == N * G for groups in s))
	test2 = lambda s: all((len(groups) == N and all((len(g) == G for g in groups)) for groups in s))
	test3 = lambda s: Counter((c for groups in s for g in groups for c in combinations(g, 2))).most_common(1)[0][1] < 2
	all_players = set(''.join(schedule[0]))
	test4 = lambda s: all((set(''.join(groups)) == all_players for groups in s))
	return test1(schedule) and test2(schedule) and test3(schedule) and test4(schedule)


differ = lambda l: len(set(l)) > 1

def valid(a):
	if differ((len(d) for d in a)) or differ((len(g) for d in a for g in d)) or differ((tuple(sorted(''.join(d))) for d in a)):
		return False
	played = {p: '' for p in ''.join(a[0])}
	for group in [g for d in a for g in d]:
		for player in group:
			played[player] += ''.join([p for p in group if p != player])
	return all([len(played[player]) == len(set((p for p in played[player]))) for player in played])


from collections import defaultdict

def valid(a):
	(X, G, memo) = (len(a[0]), len(a[0][0]), defaultdict(set))
	players = {g for group in a[0] for g in group}
	for row in a:
		if len(row) != X:
			return False
		for group in row:
			if len(group) != G:
				return False
			S = set(group)
			for g in group:
				if g not in players:
					return False
				l = len(memo[g])
				memo[g] |= S - {g}
				if l + G - 1 != len(memo[g]):
					return False
	return True


from itertools import combinations

def valid(a):
	players = sorted(''.join(a[0]))
	pairs = combinations(players, 2)
	group_size = len(a[0][0])
	for pair in pairs:
		count = 0
		for day in a:
			if sorted(''.join(day)) != players:
				return False
			for group in day:
				count += pair[0] in group and pair[1] in group
				if len(group) != group_size:
					return False
		if count > 1:
			return False
	return True


import itertools

def valid(schedule):
	golfers = set((golfer for day in schedule for group in day for golfer in group))
	days = [''.join(day) for day in schedule]
	groups = [set(group) for group in sum(schedule, [])]
	return all((day.count(golfer) == 1 for day in days for golfer in golfers)) and len(set((len(day) for day in schedule))) == 1 and (len(set((len(group) for group in groups))) == 1) and all((sum((pair <= group for group in groups)) <= 1 for pair in map(set, itertools.combinations(golfers, 2))))


def valid(a):
	golfers = {}
	for i in a:
		for j in i:
			for k in j:
				golfers[k] = []
	for days in a:
		for group in days:
			for person in golfers:
				if person in group:
					for people in group:
						if person != people:
							if people in golfers[person]:
								return False
							golfers[person] += people
	length = len(golfers['A'])
	for i in golfers:
		if len(golfers[i]) != length:
			return False
	return True


from itertools import combinations

def valid(s):
	all_char = sorted(list(set([k for i in s for j in i for k in j])))
	(c, c1, store) = ([], [], [])
	for i in s:
		c.append(all_char == sorted(''.join(i)))
		for j in i:
			c1.append(len(j) + len(i))
			for k in combinations(j, 2):
				if k in store:
					return False
				store.append(k)
	return all(c) and len(set(c1)) < 2


def valid(a):
	groups_per_day = len(a[0])
	all_groups = [set(x) for x in a[0]]
	golfers = ''.join(a[0])
	for day in a[1:]:
		if len(day) != groups_per_day:
			return False
		if set(''.join(day)) != set(golfers):
			return False
		for group in day:
			if [1 for g in all_groups if len(g & set(group)) > 1]:
				return False
			all_groups.append(set(group))
	return True