Last active
May 4, 2020 10:57
-
-
Save qxf2/7cd17fa5c28a1650d45c7ad2d69c2282 to your computer and use it in GitHub Desktop.
This script is an example of how to pick groups of 'r' people randomly from within a larger sample of N people such that no single person appears in two groups.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This script is an example of how to pick groups of 'r' people randomly from within a larger sample of N people such that no single person appears in two groups. | |
I find this script useful when I have to divide my employees into groups randomly | |
""" | |
import argparse | |
import itertools | |
import random | |
#Note: Listing employees just to keep the example short | |
#You would (ideally) get a list of employees from some central datastore | |
#UPDATE EMPLOYEES TO SUIT YOUR CONTEXT | |
EMPLOYEES = ['Wilhelm', 'Emmanuel', 'Jose', 'Alexander', 'Max', 'Mikhail', 'Vassily', 'Tal', 'Tigran', 'Boris', 'Bobby', 'Anatoly', 'Gary', 'Vladimir', 'Anand', 'Magnus'] | |
def check_no_overlap(my_tuple, reference_list): | |
""" | |
Verify if at least one member of a tuple overlpas with the members in a list of tuples | |
:return result_flag: boolean | |
""" | |
result_flag = True | |
for reference_tuple in reference_list: | |
result_flag &= set(my_tuple).isdisjoint(set(reference_tuple)) | |
if result_flag is False: | |
break | |
return result_flag | |
def get_groups(group_size): | |
""" | |
Return groups of size group_size | |
:return groups: list of tuples | |
""" | |
unique_groups = [] | |
expected_num_groups = int(len(EMPLOYEES)/group_size) | |
#We shuffle the combinations to keep the order fresh everytime | |
random.shuffle(EMPLOYEES) | |
if group_size >= len(EMPLOYEES): | |
unique_groups.append(tuple(EMPLOYEES)) | |
else: | |
#all_combos is a list of all group_size combinations | |
all_combos = list(itertools.combinations(EMPLOYEES, group_size)) | |
#Our next step is to make the groups disjoint | |
#'disjoint' = One employee cannot appear in two groups | |
for combo in all_combos: | |
if check_no_overlap(combo, unique_groups): | |
unique_groups.append(combo) | |
#A small optimization is to stop checking combos once we reach the expected number of groups | |
if len(unique_groups) == expected_num_groups: | |
break | |
return unique_groups | |
#----START OF SCRIPT | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser() | |
parser.add_argument('--size', dest = 'size', type = int, default = 2, help = 'Size of the group you want') | |
args = parser.parse_args() | |
if args.size < 1: | |
parser.error(f'Invalid argument --size {args.size}. Group size should be an positive integer.') | |
groups = get_groups(args.size) | |
if len(groups): | |
print('Groups chosen are:') | |
for i, group in enumerate(groups): | |
print(f'{i}. {group}') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment