Match two groups by their rankings so no pair wants to swap — free, no account or key needed.
A STABLE matching: USE THIS WHEN you're assigning two sides to each other by
mutual preference — interns<->teams, students<->schools, mentors<->mentees —
and want a result with no "blocking pair" (no person+slot that both prefer
each other over what they got).
Provide proposers and receivers, each a list of {"id": name,
"preferences": [ids of the OTHER side, most-wanted first]}. Receivers may add
"capacity" (default 1) to accept several. Returns {matching (name -> name),
unmatched_proposers, blocking_pairs (empty list = provably stable),
n_proposals}. NOTE: the result is PROPOSER-optimal, so put the side you want
to favor in `proposers`.
Example: stable_match(
proposers=[{"id":"Ana","preferences":["Growth","Core"]},
{"id":"Ben","preferences":["Core","Growth"]}],
receivers=[{"id":"Growth","preferences":["Ben","Ana"]},
{"id":"Core","preferences":["Ana","Ben"]}])
-> matching {"Ana":"Growth","Ben":"Core"}, blocking_pairs [].