diff --git a/contents/stable_marriage_problem/code/java/stable-marriage.java b/contents/stable_marriage_problem/code/java/stable-marriage.java new file mode 100644 index 000000000..e57ba56bf --- /dev/null +++ b/contents/stable_marriage_problem/code/java/stable-marriage.java @@ -0,0 +1,140 @@ +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; + +class StableMarriage { + + /* + * Use the stable marriage algorithm to find stable pairs from the + * lists of men and women. + */ + public static void findStableMarriages(List women, List men) { + // We might have more men/women than women/men. In this case, not everybody can + // get a mate. We should aim to give every member of the less numerous gender a mate, + // as this is always possible. + List leastCommonGender = women.size() <= men.size() ? women : men; + do { + // Every single man proposes to a woman. + for (Man man : men) + if (man.isLonely()) + man.propose(); + + // The women pick their favorite suitor. + for (Woman woman : women) + woman.chooseMate(); + + // End the process if everybody has a mate. + if (!leastCommonGender.stream().anyMatch(Person::isLonely)) + break; + + } while (true); + + women.forEach(w -> System.out.println(w + " married to " + w.getMate())); + } + + public static void main(String[] args) { + int nPairs = 5; + List women = new ArrayList<>(); + List men = new ArrayList<>(); + for (char i = 'A'; i < 'A' + nPairs; ++i) { + women.add(new Woman("" + i)); + men.add(new Man("" + i)); + } + // Make the genders unbalanced: + women.add(new Woman("X")); + + women.forEach(w -> { + w.receiveOptions(men); + System.out.println(w + " prefers " + w.getPreferredMates()); + }); + men.forEach(m -> { + m.receiveOptions(women); + System.out.println(m + " prefers " + m.getPreferredMates()); + }); + + findStableMarriages(women, men); + } + +} + +class Person { + private final String name; + protected Person mate; + protected List preferredMates; + + public Person(String name) { + this.name = name; + } + + public boolean isLonely() { + return mate == null; + } + + public void setMate(Person mate) { + // Only set mates if there is a change. + if (this.mate != mate) { + // Remove old mates mate. + if (this.mate != null) + this.mate.mate = null; + + // Set the new mate. + this.mate = mate; + + // If new mate is someone, update their mate. + if (mate != null) + mate.mate = this; + } + } + + public Person getMate() { + return mate; + } + + public void receiveOptions(List mates) { + // Preferences are subjective. + preferredMates = new ArrayList<>(mates); + Collections.shuffle(preferredMates); + } + + public List getPreferredMates() { + return preferredMates; + } + + public String toString() { + return getClass().getName() + "(" + name + ")"; + } +} + +class Woman extends Person { + private List suitors = new ArrayList<>(); + + public Woman(String name) { + super(name); + } + + public void recieveProposal(Man suitor) { + suitors.add(suitor); + } + + public void chooseMate() { + for (Person mostDesired : preferredMates) { + if (mostDesired == mate || suitors.contains(mostDesired)) { + setMate(mostDesired); + break; + } + } + } +} + +class Man extends Person { + public Man(String name) { + super(name); + } + + public void propose() { + if (!preferredMates.isEmpty()) { + Woman fiance = (Woman) preferredMates.remove(0); + fiance.recieveProposal(this); + } + } +} diff --git a/contents/stable_marriage_problem/stable_marriage_problem.md b/contents/stable_marriage_problem/stable_marriage_problem.md index 41df485a1..fc47c0910 100644 --- a/contents/stable_marriage_problem/stable_marriage_problem.md +++ b/contents/stable_marriage_problem/stable_marriage_problem.md @@ -42,6 +42,8 @@ Program.cs [import, lang:"csharp"](code/csharp/Program.cs) ListExtensions.cs [import, lang:"csharp"](code/csharp/ListExtensions.cs) +{% sample lang="java" %} +[import, lang:"java"](code/java/stable-marriage.java) {% endmethod %}