How I Used Slack to Optimize This Year’s Secret Santa So It Wasn’t Awkward for Anyone Involved 🎅
By: Justin Fung
Tags: Python, Web Development, Optimization, Data Science, Slack

WARNING: TECHNICAL COMPUTER-RELATED CONTENT AHEAD.

Be warned (or bored), all ye who read further…

(Possibly Boring) Technical Content Part I: Scraping Slack

Enter the workplace “productivity” tool Slack. Slack (and all social media in this context) is great if you are not scared sh*tless by that fact that interpersonal interactions are now etched permanently in bits. There are surely innumerable ways to quantify “interaction” between people in 1s and 0s, but the one my particular team is fond of is the beloved and liberal use of the emoji. We take our emoji game pretty seriously, to that point that the best contributions and ribbings are awarded with custom emojis that capture a team member’s idiosyncrasies for all perpetuity.

Turns out photoshopping your teammates alongside gansta-rap outfit N.W.A. is a good way to earn sweet, sweet emojis. (screenshot by author)

Rather than engineer some new-fangled deep learning model that ingests human language Slack messages, I determined that I could capture a measure of how familiar someone is with someone else by simply counting the number of reactions a member has to another’s Slack messages (by way of an aptly applied reaction emoji). To be certain, this method by no means captures all the nuances of human relationships, but true to econometric modeling, it probably provides some positive correlation with it, and is therefore better than the alternative, which is to omit it altogether. So, a plan was hatched to construct a matrix of emoji counts between all members of this year’s Secret Santa game. In the pursuit of counting Slack reactions, I had two problems to overcome.

The first is that, regrettably, I am just an individual contributor in my company and we have a totally reasonable and just (and awesome) IT department that isn’t about to grant administrative privileges to new hires so that they can see all of the quasi-private user information contained in the company’s global Slack database. The second problem was that I am not about to manually scroll through tens of thousands of messages in my limited time off in order to extract by hand the data I was after. Thankfully, there are plenty of open-sourced tools out there that allow you to automate “scraping” that addressed both problems for me, so I took the opportunity to re-familiarize myself with browser automation and fired up a Selenium script using Python and a headless Chrome instance that mimicked the way I would otherwise go about collecting this data.

The script is conceptually simple- you scroll back to the very first post at the beginning of time and enter an indefinite loop that extracts the poster and time, then “hovers” over the emojis and extracts the reactions, all before “scrolling” to the next post and repeating. After building in some time delays to account for lazy-loaded messages and Slack’s event-driven DOM rendering, I had a script that scraped ~45,000 messages and their reactions into a database in about 12 hours. Not exactly production-level performance, but since this was a one-off, it suited my purposes just fine.

Take the wheel, Selenium. (screenshot by author)

In order to cast this measure of familiarity into risks associated with gifting a well-received gift, I normalized each individual’s total reactions to all the others by casting them as percentages and subtracting each value from the maximum (basically taking a complement). What this left me with was a matrix containing, for each team member, a list of “risks” associated with choosing a gift for every other member on the team, ranging from a low of 1 for the person they reacted to the most over the year, to some greater number, bounded by 100, for the person they interacted with the least.

With this measure of familiarity accomplished by way of estimating gift-giving “risks”, I turned my attention to solving the Secret Santa assignment programmatically, and in all hope, for the optimal case.

(Possibly Boring) Technical Content Part II: Optimizing Pairings

Even though I studied this kind of problem solving in graduate school, I was a little rusty and figured I might have to enumerate every possible assignment and take the permutation that minimized the overall sum of everyone’s risk of choosing well-received gifts for their assignments. We have 16 members in our team, so a quick reaction might have you recognizing there are 16! (16 factorial) potential permutations I would have to evaluate in order to find the best. Don’t let that little exclamation mark fool you- “16!” expanded is about 21 trillion, but it turns out it would only amount to a paltry 7 trillion arrangements because a derangement allows you to ignore the arrangements in which a team member was assigned to themselves. In any case, an exhaustive search of this size would probably require me to solve it on a much-faster computer than my MacBook Pro in order to come up with a solution in any reasonable amount of time.

Well, I wasn’t satisfied with the prospect of having to turn to AWS for a simple Secret Santa so I strapped on my Google hat again and started researching ways to optimize a derangement without an exhaustive search. “Secret Santa optimization” turned up little, but after further reading, it turns out that the problem of assignment belongs to the fundamental class of computer science problems known as — you guessed it — assignment problems. After more research, it appeared that this was one of the most straight-forward classes of assignment, and as such, has a whole history of solutions that bring the search for the optimal assignment down from factorial time to polynomial time. In our case, it turns the search for a naïve solution to a 16-person derangement that relies on trillions of comparisons into a “minimum cost flow” problem backed by an iterative algorithm requiring thousands of iterations at most, meaning you can find the optimal solution nearly instantly on virtually any computer you can get your hands on today.