Cross-team distribution generator
A small optimization tool for assigning student tutors to cross teams from an Excel sheet.
At the beginning of each study year, new students at DTU are introduced both to people from their own study programme and to students from other engineering programmes. One part of this is a set of cross teams: mixed intro teams where each team is supported by a group of older students acting as tutors.
My task was to help distribute the tutors across these cross teams. Each tutor also belongs to a smaller buddy team, which must stay together during the distribution. At the same time, the resulting cross teams should still be reasonably balanced across size, study programmes, study councils and practical constraints.
Historically, this distribution was done manually during a very compressed week. After several days of interviews and hiring discussions, the teams would be decided on a Wednesday evening, and the tutors would be hired and welcomed the next day. That made the process stressful and fairly easy to get wrong.
I built a tool that imports the tutor data from an Excel file, validates each row, and writes row-by-row feedback to a text file when something needs to be fixed. Once the input is valid, the program groups tutors by their buddy teams and assigns those groups to cross teams.
A large part of the project was deciding what a "good" distribution should mean. The assignment is guided by a scoring function that captures the main planning goals: reasonable team sizes, spreading tutors across study programmes and study councils, and grouping related study programmes where that made sense.
The related-programmes part was new that year and ended up being one of the more interesting pieces. I reused questionnaire data from tutor coordinators about which study programmes felt closest to each other, and treated it as a graph of programme relations. The optimizer could then reward teams where the study programmes had some natural overlap, without letting that dominate the other constraints.
The exact weights were less important than making the trade-offs explicit. Instead of manually moving names around from scratch, we could generate a strong baseline, inspect where it was good or bad, adjust the priorities if needed, and then make the final human decisions on top of that.
I was honestly not sure this simple approach would work when I started. The number of possible distributions is enormous, so I expected either poor results or very slow runtime. In practice, the constraints and scoring function gave the search enough structure that repeated local improvements produced useful results in only a few minutes.
Technically, the program starts by placing buddy groups into teams and then repeatedly tries moves and swaps that improve the score until the result stabilizes. It runs this process several times with different random orders and keeps the highest-scoring distribution. The final result is exported back to Excel, so the rest of the planning process can continue in a familiar format.
In 2026, we used it to create the tutor distribution for the Lyngby intro cross teams, followed by manual adjustments. The first version did not place the tutor coordinator buddy groups, so those were still distributed manually afterwards. Even with that limitation, the tool changed the process from building the distribution from scratch to reviewing and adjusting a generated baseline.
What it did
- Imported tutor and buddy-team data from Excel
- Validated input rows and wrote fixable error feedback to a text file
- Kept tutor buddy teams together as a hard requirement
- Scored assignments based on team size and distribution criteria
- Used questionnaire data to group related study programmes
- Used moves, swaps and repeated randomized runs to improve the result
- Exported the chosen tutor distribution back to Excel
- Provided a baseline for manual review and final adjustments
Tech
- Python
- Excel import/export
- Input validation and error reporting
- Local search / hill climbing