Over the weekend my brother wanted to figure out his class schedule for the next semester. He is a veterinary medicine and zootechnology student at UNAM. For this upcoming semester there is a set of classes he has to take and each has 8 or so instructor options. The website where he finds the class times lists about 8 pre-constructed class schedules. So he normally finds one he likes quite a bit, and then manually starts checking if he can change X instructor for Y for a given class. He does this based on the referalls and information he has gathered about the instructors, plus he factors in whether it’d be an overall better schedule. For example, he might prefer to have a packed Tuesday if that means that he can leave early on Friday and avoid classes on Saturday.
The problem is that it’s very easy to make a mistake. You (well he) gets all excited thinking that he’s found the perfect schedule. Only to then realize that there is a conflict between two classes. Or that the practical portion of a class is in a location one hour away from the university, meaning that the schedule he has selected won’t work. This process is very frustrating.
I was watching him and I started to think if I could help him with some code. Turns out that it was straightforward to write some code to find which options are valid. Once I wrote a test case, it took us like half an hour to fill out the data. I know that tomorrow is when he and his classmates start registering for classes, so this information might help his classmates.
First, I define some helper functions. These are rather straightforward but I’ll be using them later on. For example,
dias() is just there for typing less.
Next comes the input information. I organized it in a set of nested
list objects. The schedule is stored as a character vector. For example, Lucia Eliana’s class meets on Wednesdays (__M__iercoles in Spanish) from 9 to 11 am. I only keep the starting hours (9 and 10 am) because otherwise the code won’t detect valid opitons that include another class that starts at 11 am. For classes that are 1 hour away from the university, we included 1 hour before and 1 hour after the class.
Now that the input information is complete, I use
expand.grid() to find out all the different possible options.
There’s 81,00 of them including the classes that meet on Saturday. You can see why it’s a frustrating process to find which combination of classes work when doing this manually.
Next, I explore all these options to find those that are valid, meaning that none of the classes overlap. I do this by finding which options have no duplicated hours from the character vectors defined earlier. Nothing fancy.
Now that I have the valid options, I can find the names of the instructors for them. There’s 2,847 valid schedules in the end, out of the 81,000. That’s 3.5 percent!
You can search the interactive version here to select only the options with a given instructor. For example, in my brother’s case there are 30 valid options once he decided to prioritize two instructors as shown in the non-interactive table below.
|5||lucia eliana||isaac reyes 2||jose luis gutierrez||cintli martinez||1701|
|11||lucia eliana||isaac reyes 2||rodrigo mena||cintli martinez||1701|
|14||lucia eliana||isaac reyes 2||beatriz arellano||cintli martinez||1701|
|19||lucia eliana||isaac reyes 2||ramirez ortega||cintli martinez||1701|
|25||lucia eliana||isaac reyes 2||de la pena||cintli martinez||1701|
|31||lucia eliana||isaac reyes 2||efren diaz aparicio||cintli martinez||1701|
|37||lucia eliana||isaac reyes 2||lucia del carmen favila||cintli martinez||1701|
|46||lucia eliana||isaac reyes 2||jose luis gutierrez||osvaldo froylan||1701|
|50||lucia eliana||isaac reyes 2||beatriz arellano||osvaldo froylan||1701|
|58||lucia eliana||isaac reyes 2||ramirez ortega||osvaldo froylan||1701|
|67||lucia eliana||isaac reyes 2||de la pena||osvaldo froylan||1701|
|76||lucia eliana||isaac reyes 2||efren diaz aparicio||osvaldo froylan||1701|
|85||lucia eliana||isaac reyes 2||lucia del carmen favila||osvaldo froylan||1701|
|123||lucia eliana||isaac reyes 2||jose luis gutierrez||guadarrama 01||1701|
|130||lucia eliana||isaac reyes 2||rodrigo mena||guadarrama 01||1701|
|134||lucia eliana||isaac reyes 2||beatriz arellano||guadarrama 01||1701|
|137||lucia eliana||isaac reyes 2||de la pena, ramirez ortega||guadarrama 01||1701|
|144||lucia eliana||isaac reyes 2||de la pena||guadarrama 01||1701|
|151||lucia eliana||isaac reyes 2||efren diaz aparicio||guadarrama 01||1701|
|158||lucia eliana||isaac reyes 2||lucia del carmen favila||guadarrama 01||1701|
|209||lucia eliana||isaac reyes 2||jose luis gutierrez||guadarrama 05||1701|
|217||lucia eliana||isaac reyes 2||rodrigo mena||guadarrama 05||1701|
|222||lucia eliana||isaac reyes 2||de la pena, ramirez ortega||guadarrama 05||1701|
|232||lucia eliana||isaac reyes 2||de la pena||guadarrama 05||1701|
|242||lucia eliana||isaac reyes 2||efren diaz aparicio||guadarrama 05||1701|
|252||lucia eliana||isaac reyes 2||lucia del carmen favila||guadarrama 05||1701|
|872||lucia eliana||isaac reyes 2||jose luis gutierrez||guadarrama 05||1704|
|885||lucia eliana||isaac reyes 2||de la pena||guadarrama 05||1704|
|894||lucia eliana||isaac reyes 2||efren diaz aparicio||guadarrama 05||1704|
|903||lucia eliana||isaac reyes 2||lucia del carmen favila||guadarrama 05||1704|