-
-
Notifications
You must be signed in to change notification settings - Fork 359
/
Copy pathstable-marriage.java
140 lines (114 loc) · 3.69 KB
/
stable-marriage.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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<Woman> women, List<Man> 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<? extends Person> 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<Woman> women = new ArrayList<>();
List<Man> 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<Person> 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<? extends Person> mates) {
// Preferences are subjective.
preferredMates = new ArrayList<>(mates);
Collections.shuffle(preferredMates);
}
public List<Person> getPreferredMates() {
return preferredMates;
}
public String toString() {
return getClass().getName() + "(" + name + ")";
}
}
class Woman extends Person {
private List<Man> 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);
}
}
}