What if you spend extra memory to partially process each pair in the order of how likely they are to be the best pair?
Each pair will need to track where it is in the sequence of categories to check next.
- for my $pair (@contenders).
- If $pair->{nextCategory} >= @categories then you have found the best.
- Otherwise, test the category indicated by $pair->{nextCategory}.
- Increment the pair's nextCategory.
- If the pair didn't match, redo.
- If they do match, push the pair onto a @reserve and try the next contender.
- Once the @contenders are exhausted, repopulate it with the @reserve of pairs that had one more match than the previous contenders.