The BAT Algorithm

2026-01-11 / Balanced Admissions Thresher, for hackathon admissions.

Hey there! It's been a while, but I'm back with another post about an interesting problem I've had recently. I'll quickly introduce the situation and then talk about how we solved it.

The Problem

At SwampHacks, the University of Florida's flagship hackathon, organizers need to review and select attendees from a list of 1000+ applicants. Our team is relatively small, approximately 30-ish members who all work around different times. Within the organization, we also have smaller teams, such as the six-person tech team, who are more synchronized.

This makes it hard to agree on applicants to admit. We cannot feasibly coordinate everyone sitting down, reviewing applications at once, and making decisions together. Furthermore, each applicant may be on a team, and we would prefer to keep teams together in admissions. So how do we make this process automated? And how can we make it fair?

Brainstorming

At SwampHacks, we hold two aspects of an application as the most important: experience and passion for tech. We still are not sure whether a more passionate group or a more experienced group creates a better hacker cohort.

The more passionate you are, the more likely you are to also be experienced. However, we like to have passion as an extra field because younger applicants can be very passionate but have limited experience in internships, research, projects, and so on. We judge an applicant's passion from their writing pieces in the application, such as essay responses.

Example:

Tell us about a project you have built and how you collaborated with others.

With these two quantifiers in mind, we asked organizers to rate each applicant on a score from 1 to 5 for each aspect. These answers were saved in our database and the application was marked as Reviewed.

The BAT Algorithm

Here I shall introduce the one, the only, BAT algorithm. It stands for Balanced Admissions Thresher. A thresher is a person or machine that separates grain from the plants.

The BAT algorithm is made of three primary parts: preprocessing, staging bucket isolation, and staged selection. I will go step by step. The implementation snippets and service code were written in Go.

1. Preprocess

Preprocessing applications includes assigning scores to applications, grouping teams, and doing other computations before moving on to the stage isolation step.

Weighted Scoring

For each applicant i, we calculate a weighted score from the scores given for passion and experience.

S_i = w_passion * s_passion + w_exp * s_exp + epsilon

where:

Group Applicants

Each applicant is grouped into one of two buckets: individual applicants or teams. If an applicant was on a team, then we try our best to keep that team together, so teams get a dedicated selection bucket.

A team's weighted score is the average of all member scores. Teams are compared against other teams for admissions, and the selection details are specified below.

2. Staging Bucket Isolation

Per our head organizers, we have a few constraints and policies to consider. For example, we want a best effort for 70% of all acceptances to go to applicants from the University of Florida, with the remaining slots going to external schools. We also need to make a best effort for 65% of UF acceptances to come from what we consider early-career applicants, usually freshmen and sophomores.

When we structure these constraints, we form four dedicated selection pools that compete internally for spots:

This split keeps the selection process fair. Early-career applicants are, on average, less experienced than later-career applicants. If we compared everyone in one primary pool by weighted average, later-career applicants would tend to dominate. Isolating each group allows for fairer competition within each group.

To handle a lack of applicants in a specific pool, final slot allocations may roll over to a sister pool. For example, leftover allocations for UF Early may be given to UF Late, and vice versa. The same applies to the Other pools.

3. Selection Phase

Finally, we begin the selection phase. To be completely fair, selection and bucket isolation are intertwined: bucket isolation does not happen until after the team phase of selection.

The Selection Algorithm

We use a modified version of Efraimidis-Spirakis random weighted sampling. This algorithm lets us randomly select applicants without replacement while still making weight significant in the outcome. That is useful because we want every applicant to have at least some chance of getting accepted, no matter how poor their application review was. It also reduces bias introduced by human reviewers.

k_i = v_i ^ (1 / w_i)

where:

Then we sort by key and select the top n applicants or teams for that iteration.

Team Selections

Team selections happen first. We allocate a certain number of acceptance slots to team members. For example, if we allot 50 slots to teams and teams are capped at four members, this gives a minimum of 13 team slots:

50 // 4 = 12
50 % 4 = 2

=> 12 teams of 4 and 1 team of 2

We apply Efraimidis-Spirakis random weighted sampling to each team's average score, then iterate through the selected teams and fill accepted slots until we run out of the team quota.

Afterwards, every non-selected team's members move into the individual applicant selection phase, giving them another chance to make it in based on individual merit and luck.

Individual Selection

Finally, we loop twice over the buckets created above to cover rollover in both directions between sister buckets. For each loop, we calculate each individual's sort key using the random sampling algorithm, then select the top n applicants, where n is the quota for that bucket.

Conclusion

After all that mayhem, we were able to select 500 applicants for SwampHacks XI out of 1000+ applications with ease. We know this algorithm and process are not perfect yet, and there are many ways to expand it: adding an arbitrary number of scoring quantifiers, creating dynamic buckets from rulesets, and making the rollover logic more expressive. However, this current version lets us fairly accept applicants while giving everyone, no matter their score, a chance of getting in.

Thanks, alex out!

Sources

  1. Efraimidis-Spirakis weighted random sampling paper
  2. BAT Engine