Skip to content

Instantly share code, notes, and snippets.

@xavdid
Created August 22, 2017 04:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xavdid/9757b7a689cf101e906349e39a000a3f to your computer and use it in GitHub Desktop.
Save xavdid/9757b7a689cf101e906349e39a000a3f to your computer and use it in GitHub Desktop.
"""
get permutations of schedules and assign students to them
"""
import csv
from itertools import permutations
from random import choice
MAX_CLASS_SIZE = 27
CLASSES = [
'Geometry - Mr. Perkins (C222)',
'W. History - Ms. Kaufman (C220)',
'English 2 - Ms. Martinez (C218)',
'Maritime - Mr. Moriarty (C224)',
'Chemistry - Mr. Kowshik (D211)'
]
def flatten(l):
"""
from: https://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python
this exists because i'm lazy
"""
flat_list = []
for sublist in l:
if isinstance(sublist, list) or isinstance(sublist, tuple):
for item in sublist:
flat_list.append(item)
else:
flat_list.append(sublist)
return flat_list
def main():
schedules = list(permutations(CLASSES))
# fill our class counts
counts = []
for i in xrange(5):
counts.append({c: 0 for c in CLASSES})
students = []
with open('MA10.csv', 'rb') as FILE:
reader = csv.reader(FILE)
reader.next() # skip the header
for row in reader:
students.append({
'name': row[0],
'id': row[1],
'mentor': row[2],
'special': row[8] == '1'
})
# special kids to the front of the bus!
students.sort(key=lambda k: k['special'], reverse=True)
def will_overflow(schedule):
for i, class_ in enumerate(schedule):
# don't want imbalanced class sizes
if capped(i) and counts[i][class_] + 1 == MAX_CLASS_SIZE:
return True
if counts[i][class_] + 1 > MAX_CLASS_SIZE:
return True
return False
def capped(i):
cap_num = len(students) % len(CLASSES)
return sorted(counts[i].values())[-cap_num:] == [MAX_CLASS_SIZE for i in xrange(cap_num)]
def increment_class(schedule):
for i, class_ in enumerate(schedule):
counts[i][class_] += 1
for student in students:
while not student.get('schedule'):
# throws IndexError if it's hit a corner
schedule = choice(schedules)
if student['special'] and schedule[0] != CLASSES[0]:
continue
if will_overflow(schedule):
schedules.remove(schedule)
continue
student['schedule'] = schedule
increment_class(schedule)
with open('MA10_output.csv', "wb+") as csv_file:
writer = csv.writer(csv_file)
writer.writerow(['ID', 'Name', 'Mentor', 'Period 1', 'Period 2',
'Period 3', 'Period 4', 'Period 5', 'Special?'])
for student in students:
writer.writerow(flatten([
student['id'],
student['name'],
student['mentor'],
student['schedule'], # was a tuple, need to make a list
student['special']
]))
count = 0
ATTEMPTS = 20
print 'finding a schedule!\n'
while count < ATTEMPTS:
try:
main()
print 'found a schedule after', count, 'unsuccessful attempts'
break
except IndexError:
count += 1
if count == 20:
print 'could not find a valid schedule after', ATTEMPTS, 'tries. Adjust parameters and try again?',
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment