Match n proposers with n receivers so that no proposer and receiver would both rather be with each other than with their assigned partners. Such a pair is a blocking pair, and a matching without one is stable. Gale–Shapley always finds one.
Implement:
gale_shapley(proposer_prefs, receiver_prefs): each argument maps a name to that person's full preference list, best first. While someone is free, take the alphabetically first free proposer and have them propose to the best receiver they haven't proposed to yet. The receiver accepts if free, or swaps if they prefer the new proposer. Return {proposer: receiver}.blocking_pairs(matching, proposer_prefs, receiver_prefs): the sorted list of (proposer, receiver) blocking pairs