Example code - Data structures

From 22113
Jump to navigation Jump to search

Files used in example

TA_list.txt
student_list.txt

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