Example code - Data structures
Files used in example
Assigning students to TA's, Take 1
This is a python3 program written by a TA. It was done in a hurry, without much regard to the teaching principles. The purpose of the program is to read a list of students and a list of TA's and randomly assign students to TA's for grading.
Some TA's can take on fewer students than others, so there can be a quota. This must be taken into consideration. This is arranged by adding a number after the TA's name in the tab-separated TA file. Also, students may sign up later or leave the course, so the program must be flexible enough to handle that. That can happen for the TA's too. In both cases it is enough to either delete/add the TA/student or make a comment # in front of the name.
The basic idea is to start from the top of the list of students and assign the student to the next TA in the TA list. When the bottom of the TA list is reached, start from the top once more, until all students are assigned. If a TA's quota is filled, that TA is excluded. Since we don't want the same student assigned to the same TA all the time, the student list is randomly shuffled using the random library. Since we want the load to be equal for TA's (first TA in the list will always get most students, last will get least), the TA list is shuffled, too.
The important data structure is TA_dict which is a dict of dict of list,
TA_dict = { 'Peter': { 'max': 10, 'assigned': ['Student A', 'Student F', 'Student K'] }, 'TA 1': { 'max': 5, 'assigned': ['Student B', 'Student G', 'Student L'] }, 'TA 2': { 'max': 10, 'assigned': ['Student C', 'Student H', 'Student M'] }, 'TA 3': { 'max': 5, 'assigned': ['Student D', 'Student I', 'Student N'] }, 'TA 4': { 'max': 10, 'assigned': ['Student E', 'Student J', 'Student O'] } }
#!/usr/bin/python3 import sys, random helpmessage = "usage:\nassign_TA.py\tlist of TAs\tlist of students\n\nThe list of TAs may contain a maximum of students to assign to the particular TA. This should be separated from the TA's name by tab.\n" #display help if requested or run without arguments if len(sys.argv) < 3 or sys.argv[1] == '-h' or sys.argv[-1] == '--help': sys.exit(helpmessage) else: TA_file = sys.argv[1] student_file = sys.argv[2] TA_dict = {} TA_index = [] #list to serve as an index to the dict of dicts since dictionary keys are unordered. TA_IN = open(TA_file,'rt', encoding='utf8') for line in TA_IN: line = line.rstrip().split('\t') #if there is a second column this is the max value of students for that TA if len(line) > 1: #create a dict for this TA TA_dict[line[0]] = {} TA_dict[line[0]]['max'] = int(line[1]) TA_dict[line[0]]['Students'] = [] TA_index.append(line[0]) else: TA_dict[line[0]] = {} TA_dict[line[0]]['max'] = 10 TA_dict[line[0]]['Students'] = [] TA_index.append(line[0]) TA_IN.close() #read and save list of students st_IN = open(student_file, 'rt', encoding='utf8') st_list = [] for line in st_IN: if line[0] != '#': st_list.append(line.rstrip()) st_IN.close() #mix things up a bit random.shuffle(st_list) random.shuffle(TA_index) j = 0 #go through the randomized student list and assign each to a TA for name in st_list: #check if we've reached the end of the TA list if j == len(TA_index): j = 0 #check if TA j has already hit the maximum of students. If yes, check the next and so on. while len(TA_dict[TA_index[j]]['Students']) == TA_dict[TA_index[j]]['max']: j += 1 #if we've run through the whole list without exiting the loop there are more students than expected. if j >= len(TA_index): sys.exit('Error: Every TA has reached their specified student limit!') #now append TA_dict[TA_index[j]]['Students'].append(name) #finally increment j j += 1 for TA in TA_index: print(TA, ': ', sep='', end='') print('; '.join(TA_dict[TA]['Students']))