Building a web app to rank my favorite Marvel superhero movies, part one
I love superhero movies. Specifically, Marvel superhero movies. Specifically specifically, Marvel Cinematic Universe movies — Iron Man, Captain America, Thor, and so on. Never thought I’d be that guy, but somehow I’ve seen every single MCU movie — 22 in total.
Why? Because they’re super good! There’s a reason they have an average Rotten Tomatoes score of 84%.
But which ones are the best? This is a constant debate among my friends. And with the latest phase of the MCU coming to a close with Avengers: Endgame, it’s been a good time to take stock and make best-of lists.
A few problems, though:
- There are too many movies. Organizing 22 films in order of preference is a… tall order. (🥁) You have to keep track of every other movie when you’re considering one, or chunk them in ways that could lead to misalignment later.
- You’re probably going to give better scores to movies you just saw. Because I watched Avengers: Endgame more recently, I’m more likely to rate it higher than the original Avengers, just because I remember more details about it.
- You probably know your favorite and least-favorite films, but nothing in between. This is a twist on the well-documented recency/primacy effect, where humans are better at remembering the beginnings and ends of lists than things in the middle. In this case, fans probably never formed opinions on middling movies, focusing on just the best and the worst.
All of these problems mean tools that let you drag around movie names probably aren’t helping you come up with a definitive list. They’re just confusing you!
My take: It’s easier to pick your favorite movie when you just have two options in front of you. If you run through enough pairings, eventually you’ll get an ordered list.
That’s the idea behind mcu.ninja, a ranking tool I put out last week. 🎉
In this post, I’m going to explain the logic behind the ordering algorithm powering mcu.ninja and the command-line utility I built to demonstrate it. Next week, I’ll discuss the UI and why I thought Tinder-style swiping was the right decision.
Sorting is hard
If you need to order a list of 22 items, it’s simplest to go one by one and compare every movie to every other.
Let’s say I start with Captain Marvel. I’d compare it to Iron Man, the first film in the MCU.
OK, that’s easy — I like Iron Man better. But that’s only the beginning. I still have to compare Captain Marvel to every other MCU movie — 21 comparisons in all.
Once we’re done with Captain Marvel, we move on to the next film: Avengers: Endgame. Since we already compared it to Captain Marvel, we don’t have to match them again. But we still have 20 other movies to compare.
So far, we’ve made 41 comparisons. If we add just two more movies, we’re up to 78:
Taking this to its mathematical conclusion, we’d have to make comparisons equal to 21 + 20 + 19 + 18… + 1, or (n^2 + n) / 2. That’s 231 match-ups — only marginally better than watching 14,000,605 alternative futures.
Quicksort to the rescue
Let’s line up all the movies by date released — the order doesn’t matter — and randomly pick Captain Marvel to start:
Captain Marvel is the pivot. Our job is to re-order the list so every movie that’s worse goes on the left, and every movie that’s better goes on the right.
It doesn’t matter what order we put them in — only that they’re better or worse than the pivot.
Ater sorting (your choices might be different!), we now know Captain Marvel is No. 16 on list. To do this, we had to make 21 comparisons — same as we did before. But the next step is different. We consider the better-than and worse-than movies as their own sets, and run the method again.
So in the “worse-than-Captain Marvel” set, we randomly choose Thor: The Dark World as our pivot. In the “better-than-Captain Marvel” set, we choose Captain America: Civil War. For each of these sets, we again sort the movies by whether or not they’re worse than the pivot.
Now we have three movies properly ordered — with only 40 comparisons, instead of 60 with our previous method. That’s a huge improvement.
That kind of efficiency isn’t guaranteed. Quicksort works best when the pivots land in the middle of a given set — in this case, the movie that’s chosen is average, not terrible or spectacular. But unless you’re really unlucky, Quicksort will work far better than brute force.
Building a proof of concept
Before I built out the full mcu.ninja app, I wanted to make sure this method actually made sense. In practice, would it work to present people with pairs of movies and having Quicksort figure out which to show next?
So to test, I built mcu-rankings-cli, a command line interface script written in Node.
Pretty simple — it gives you two options, and you pick one. On the back end, I wrote a
MovieList class that handled making match-ups and accepting votes from the user. On the front end, the inquirer makes the CLI magic happen.
The method seemed to work pretty well. Sometimes the pivot movies weren’t great — it’s annoying to get a stinker like The Incredible Hulk and have to vote against it 20-something times. Later on, I decided to use Rotten Tomatoes data to choose the most “average” movie in a set as the pivot.
But otherwise, success. Next week, I’ll talk about how the final swipe-y UI came to be!
- The Avengers
- Iron Man
- Guardians of the Galaxy
- Thor: Ragnarok
- Avengers: Infinity War
- Captain America: The Winter Soldier
- Captain America: Civil War
- Avengers: Endgame
- Black Panther
- Spider-Man: Homecoming
- Iron Man 3
- Captain America: The First Avenger
- Captain Marvel
- Avengers: Age of Ultron
- Doctor Strange
- Ant-Man and the Wasp
- Guardians of the Galaxy Vol. 2
- Thor 2
- Iron Man 2
- The Incredible Hulk