The Mathematically Optimal Wardrobe
First published: 24th February 2025
When I was a child, about once a year when the sales were on, my mum would make me go through my wardrobe and decide which clothes to get rid of. These would be taken to a charity shop, and then we would go on a family shopping trip and buy new clothes.
As a child, it was sufficient to remove things that no longer fit (not that I always found this easy at the time). As I was continually growing, it was guaranteed that any given item would eventually be too small and the number of clothes I owned would remain finite. Now that I am a grown-up [citation needed] , I no longer outgrow clothes but still accumulate them. Some I buy, some are gifts, some are from University careers fairs, conferences, or similar, and then I had a recent phase where I was addicted to Vinted. I need a new method to decide what to cull.
We need to go beyond "does this spark joy?" and ask "Exactly how much joy does this spark? How many days of shrimp torture is this worth?".
The problem with simply getting rid of the things you wear the least often, is that these are usually "special occasion" clothes. I might wear a suit once a year or less. It still makes sense to keep it over a T-shirt that I wear twice a year. This is because when a suit-wearing occasion comes around, the next-best alternative to a suit might be a long way down. But when an occasion perfect for one science-pun T-shirt comes around, another science-pun T-shirt will do almost as well. So I should choose to get rid of all my science-pun T-shirts except one before seriously weighing the final one against the suit.
All of this can be formalised mathematically by k-means clustering. All I need to do is plot each of my clothes in n-dimensional space, take k to be the number of things I can fit in my wardrobe, and let the algorithm go.
The difference between a shirt and a pair of trousers is much larger than the difference between any two shirts, so rather than having a dimension of clothes-space be used for category, I chose to segment my wardrobe by category (long-sleeved button shirts, short-sleeved button shirts, T-shirts, trousers, shorts, jumpers) and run the algorithm separately on each. This allows me to choose k independently for each category, and also reflects on the way I actually store my clothes.
T-shirts
I decided somewhat arbitrarily that the dimensions of T-shirt space are:
- Colourful-ness (0: black, 10: rainbow)
- Nerd-ness (0: tribal design, 10: "Never trust atoms, they make up everything")
- Fit: (0: muscle-hugging, 10: baggy)
- Pattern scale: (0: tiny details, 7: very large pattern, 9: ombre, 10: plain colour)
- Edginess: (0: Paisley, 10: A skull)
- Clubbiness: (0: Company logo, 10: UV-active)
As an example, this shirt scored 7 for colourful, 0 for nerdy, 4 for fit, 8 for pattern scale, 3 for edgy and 1 for suitability for clubbing:

Meanwhile, this shirt scored 2 for colourful, 1 for nerdy, 4 for fit, 7 for pattern scale, 8 for edgy and 10 for suitability for clubbing:


I estimate that my T-shirt draw can comfortably hold about 20 items. These are the groups that the algorithm put my shirts into:
Cluster | Description |
---|---|
0 | Cats on the moon |
0 | Firetrap - Lightning |
0 | Firetrap - Smoke |
1 | Sicily Sailing Boat |
1 | Blue Leaf Ombre |
2 | 42 Venn Diagram |
2 | Planet balloons |
2 | Planet Newton's Cradle |
3 | Black red and yellow tie dye |
3 | Centre Stage Performing Arts Academy |
4 | Einstein Love Is The Answer |
4 | Van Gogh Pi in the Sky |
5 | Levi's rainbow - black background |
5 | Rainbow Tie-Dye |
6 | Jane Street - Enter the Monad |
6 | Steampunk wolf |
6 | Twilio |
7 | 44Con JIT-Loader |
7 | 44Con 2024 |
8 | Jane Street - Purple with triangles |
8 | Embrace the Detours |
9 | Studded Skulls |
9 | Alestorm skeletons |
10 | White and Rainbow Altair Designs |
11 | CyberDog Pink |
12 | Firetrap - Birds |
12 | Cyberdog red and black |
12 | Black and White Roses Ombre |
13 | Don't follow me, I'm lost |
13 | Pastel Stripes |
13 | Yellow Pink Blue Ombre |
14 | Space Surfer |
15 | Plain white 3 button |
16 | Polka dots on black |
16 | Paint splashes on black, curved bottom |
17 | Bsides London 2021 - Skyline |
18 | UK Chemistry Olympiad 2016 |
18 | Bsides London 2023 - 30 Years of Connecting Peers |
19 | Buttons, White on Black Paisley |
19 | Buttons, Black on White Paisley |
We can plot a projection of these onto any two dimensions:


Yes, I have too many T-shirts. It's a problem. That's why I'm doing this.
Everything in cluster 0 is something I would call one of my favourites. I'm keeping those, and you can't tell me not to. Sometimes you do need a few similar things in case one of them is in the wash.
So instead, let's make up a new algorithm:
A Better Algorithm
There are a few nice-to-have features that an algorithm should have:
Order Invariance
Suppose I have a set W of shirts, and can keep k of them. The algorithm ought to select the same k shirts if given any subset of W that contains all of those k.
Weirdness Is Not A Survival Strategy
In the algorithm that we looked at above, a shirt could get by being very different to all other shirts without actually being something that I like. An old bedsheet is unlike any shirt that I own. Does that mean I should keep it with my T-shirts?
What I really want is to define the worth of a set of T-shirts, not to define the worth of a single shirt. My goal is, for a given situation, to be able to choose something appropriate. I'll make a list of situations that I sometimes find myself in. Then, I'll rate each shirt for how well suited it is to that occasion.
For each occasion, I'll specify a list of scores that it can assign to different shirts. I need a lot of different shirts for chilling and for being in the office, but I very rarely go to a conference 2 days in a row (and if I did, it wouldn't be that terrible to wear the same shirt on those days). So, waving my hands a lot, these weights are some combination of:
- How many days in a row I might do that activity
- How much variety I want in that set
- How much I care about having the perfect shirt in that situation
The situations I've chosen are:
- Chilling at home
- Working in the office
- Having a meal out
- Having cocktails in bar
- Playing boardgames with friends
- Going to the beach
- Going on a date
- Going to a birthday party
- Going to a concert
- Going clubbing
- Walking in the forest
- Conference
- Ceilidh
- Halloween Party
- Visitng a museum
A few of these have been redacted out of privacy concerns. Rest assured they were normal everyday situations that we all find ourselves in from time to time.
For example, this shirt scored 1 for "office" and 10 for "concert":

This one didn't go below 6 for anything:

This one scored 10 for "conference" and 1 for "date":

There are 15 pairs (a,b) where a is strictly worse than b in all scenarios. This doesn't mean we can immediately get rid of a, as it might be the second best in a situation that awards points for that. It also doesn't necessarily mean I will have to keep b, as you can imagine adding a terrible shirt that scores 1 in all situations, and a slightly-less-terrible one that scores 2 in all situations.
I currently have 40 T-shirts, which is too many to evaluate all of the subsets. I tried iteratively adding the shirt that creates the best subset of size n+1 to the best subset of size n. The results were:
Description | Cumulative Score |
---|---|
Plain white 3 button | 602 |
Levi's rainbow - black background | 922 |
Black and White Roses Ombre | 1013 |
Cats on the moon | 1049 |
Bsides London 2021 - Skyline | 1075 |
Steampunk wolf | 1090 |
Studded Skulls | 1104 |
Bsides London 2023 - 30 Years of Connecting Peers | 1113 |
Black red and yellow tie dye | 1121 |
CyberDog Pink | 1128 |
White and Rainbow Altair Designs | 1134 |
Alestorm skeletons | 1140 |
Rainbow Tie-Dye | 1145 |
Cyberdog red and black | 1148 |
Jane Street - Purple with triangles | 1150 |
Buttons, White on Black Paisley | 1152 |
Blue Leaf Ombre | 1153 |
Jane Street - Enter the Monad | 1153 |
42 Venn Diagram | 1153 |
Planet balloons | 1153 |
As expected, the biggest gain is going from 0 to 1 shirt, and after that we get marginal returns. In fact, the last 3 aren't adding any value at all. This suggests that really I should only keep the first 17 in this table.
I also tried iteratively adding the 2 shirts that create the best subset of size n+2. The results were indistinguishable.
When I added 3 at a time, I couldn't go for 20 shirts of course, so I went for 21, which resulted in one more zero-value shirt making it in.
Considering sets of size 4 gets the same set of 20:
Description | Cumulative Score |
---|---|
Steampunk wolf
Bsides London 2021 - Skyline Plain white 3 button Levi's rainbow - black background |
1051 |
Cats on the moon
Bsides London 2023 - 30 Years of Connecting Peers Studded Skulls Blue Leaf Ombre |
1116 |
Black red and yellow tie dye
White and Rainbow Altair Designs CyberDog Pink Alestorm skeletons |
1142 |
Jane Street - Purple with triangles
Rainbow Tie-Dye Buttons, White on Black Paisley Cyberdog red and black |
1152 |
Jane Street - Enter the Monad
42 Venn Diagram Planet balloons Black and White Roses Ombre |
1153 |
All of the previous runs added "Black and White Roses Ombre" among the first 4 shirts. This time, it didn't make it until the final round. This highlights the need for a better algorithm than the simple greedy approach when you are under pressure for space.
Unfortunately, my laptop couldn't cope with considering all subsets of size 5, so I stopped here. But in all of these runs, the score maxes out at 1153. It appears 17 shirts is enough to fill all of my needs.
For comparision, these are the scores of 10 randomly chosen subsets of size 20:
1120, 1119, 1095, 1123, 1108, 1110, 1136, 1118, 1119, 1094
The optimal set is outside of the range of variation of the random sets, but not by as much as I would have expected. I suppose the lesson is that I have space for plenty of shirts.
If I exclude all the shirts that I bought on Vinted, I score only 1103, which is less than I can now get out of my top 7 shirts. Two of the Vinted shirts didn't make the cut, so I really should have run all of this analysis before buying them.
If I only had space for 4 shirts, I would be getting that score of 1051 from the first row of the table above. Here are the scores of 10 random sets of size 4:
958, 1016, 899, 925, 750, 859, 877, 959, 940, 883
This demonstrates that thinking hard is more worthwhile when you are limited for space.
Buying new clothes
This model implies that when I am thinking of buying a shirt, I should ask myself, "If I already had this shirt, and ran my algorithm, would the new shirt win?" And then, "What would it kick out?" And instead of asking "Would I pay X money to have this shirt?", I should ask "Would I pay X money to replace that shirt with this one?"
Using this set of 17, we can take a look at how many points each scenario is getting:
Situation | Maximum Score | Achieved Score |
---|---|---|
Chilling | 150 | 150 |
Office | 60 | 60 |
Restaurant | 40 | 40 |
Boardgames | 40 | 39 |
Beach | 50 | 50 |
Date | 90 | 89 |
Birthday | 30 | 30 |
Concert | 70 | 70 |
Clubbing | 70 | 70 |
Forest | 100 | 99 |
Cocktails | 60 | 54 |
Conference | 70 | 70 |
REDACTED | 70 | 70 |
Ceilidh | 50 | 45 |
REDACTED | 20 | 16 |
Halloween | 40 | 36 |
Museum | 70 | 56 |
REDACTED | 60 | 48 |
REDACTED | 70 | 63 |
The theoretical maximum total score would be 1210. There is room for improvement here, and this can be used to guide choices for those extra 3 slots.
Further research
Change to the scoring algorithm
The scoring algorithm relies on some pretty arbitrary decisions. It might be interesting to see how sensitive the outcomes are to the weightings assigned to the different situations.
Computational Speedups
It would be good to think of ways to run this faster and get good results. Ideally a heuristic algorithm could be found that could run on a very large set (such as: all the shirts I can buy below a certain price) and find a high-scoring set.
Conclusion
All of the rejected T-shirts will be donated to The Whitechapel Mission where they are currently listed under "We need help!"
Finding a good general model turned out to be a much harder problem than I first realised, and I feel justified in finding this decision hard. On the other hand, finding the perfect set of T-shirts to keep that would both fit in the available space and also equip me for all likely scenarios turned out to be much easier than expected.
I am now satisfied that I have arrived at a logical answer to the question of which things I will keep. As a bonus, I can now easily run the same evaluation in the future on any other collection that is starting to outgrow its allotted cupboard. Stay tuned to join me as I rank my shoes, my boardgames, my sex toys, and my friends (just kidding - unlike a shirt I rarely wear, a friend I rarely spend time with doesn't permanently take up space in my flat).
_ Likes