RosettaCodeData/Task/Stable-marriage-problem/Ceylon/stable-marriage-problem.ceylon
2018-06-22 20:57:24 +00:00

138 lines
5.2 KiB
Ceylon

abstract class Single(name) of Gal | Guy {
shared String name;
shared late Single[] preferences;
shared variable Single? fiance = null;
shared Boolean free => fiance is Null;
shared variable Integer currentProposalIndex = 0;
"Does this single prefer this other single over their fiance?"
shared Boolean prefers(Single otherSingle) =>
let (p1 = preferences.firstIndexWhere(otherSingle.equals), f = fiance)
if (!exists p1)
then false
else if (!exists f)
then true
else if (exists p2 = preferences.firstIndexWhere(f.equals))
then p1 < p2
else false;
string => name;
}
abstract class Guy(String name) of abe | bob | col | dan | ed | fred | gav | hal | ian | jon extends Single(name) {}
object abe extends Guy("Abe") {}
object bob extends Guy("Bob") {}
object col extends Guy("Col") {}
object dan extends Guy("Dan") {}
object ed extends Guy("Ed") {}
object fred extends Guy("Fred") {}
object gav extends Guy("Gav") {}
object hal extends Guy("Hal") {}
object ian extends Guy("Ian") {}
object jon extends Guy("Jon") {}
abstract class Gal(String name) of abi | bea | cath | dee | eve | fay | gay | hope | ivy | jan extends Single(name) {}
object abi extends Gal("Abi") {}
object bea extends Gal("Bea") {}
object cath extends Gal("Cath") {}
object dee extends Gal("Dee") {}
object eve extends Gal("Eve") {}
object fay extends Gal("Fay") {}
object gay extends Gal("Gay") {}
object hope extends Gal("Hope") {}
object ivy extends Gal("Ivy") {}
object jan extends Gal("Jan") {}
Guy[] guys = `Guy`.caseValues;
Gal[] gals = `Gal`.caseValues;
"The main function. Run this one."
shared void run() {
abe.preferences = [ abi, eve, cath, ivy, jan, dee, fay, bea, hope, gay ];
bob.preferences = [ cath, hope, abi, dee, eve, fay, bea, jan, ivy, gay ];
col.preferences = [ hope, eve, abi, dee, bea, fay, ivy, gay, cath, jan ];
dan.preferences = [ ivy, fay, dee, gay, hope, eve, jan, bea, cath, abi ];
ed.preferences = [ jan, dee, bea, cath, fay, eve, abi, ivy, hope, gay ];
fred.preferences = [ bea, abi, dee, gay, eve, ivy, cath, jan, hope, fay ];
gav.preferences = [ gay, eve, ivy, bea, cath, abi, dee, hope, jan, fay ];
hal.preferences = [ abi, eve, hope, fay, ivy, cath, jan, bea, gay, dee ];
ian.preferences = [ hope, cath, dee, gay, bea, abi, fay, ivy, jan, eve ];
jon.preferences = [ abi, fay, jan, gay, eve, bea, dee, cath, ivy, hope ];
abi.preferences = [ bob, fred, jon, gav, ian, abe, dan, ed, col, hal ];
bea.preferences = [ bob, abe, col, fred, gav, dan, ian, ed, jon, hal ];
cath.preferences = [ fred, bob, ed, gav, hal, col, ian, abe, dan, jon ];
dee.preferences = [ fred, jon, col, abe, ian, hal, gav, dan, bob, ed ];
eve.preferences = [ jon, hal, fred, dan, abe, gav, col, ed, ian, bob ];
fay.preferences = [ bob, abe, ed, ian, jon, dan, fred, gav, col, hal ];
gay.preferences = [ jon, gav, hal, fred, bob, abe, col, ed, dan, ian ];
hope.preferences = [ gav, jon, bob, abe, ian, dan, hal, ed, col, fred ];
ivy.preferences = [ ian, col, hal, gav, fred, bob, abe, ed, jon, dan ];
jan.preferences = [ ed, hal, gav, abe, bob, jon, col, ian, fred, dan ];
print("------ the matchmaking process ------");
matchmake();
print("------ the final engagements ------");
for (guy in guys) {
print("``guy`` is engaged to ``guy.fiance else "no one"``");
}
print("------ is it stable? ------");
checkStability();
value temp = jon.fiance;
jon.fiance = fred.fiance;
fred.fiance = temp;
print("------ is it stable after switching jon and fred's partners? ------");
checkStability();
}
"Match up all the singles with the Gale/Shapley algorithm."
void matchmake() {
while (true) {
value singleGuys = guys.filter(Guy.free);
if (singleGuys.empty) {
return;
}
for (guy in singleGuys) {
if (exists gal = guy.preferences[guy.currentProposalIndex]) {
guy.currentProposalIndex++;
value fiance = gal.fiance;
if (!exists fiance) {
print("``guy`` and ``gal`` just got engaged!");
guy.fiance = gal;
gal.fiance = guy;
}
else {
if (gal.prefers(guy)) {
print("``gal`` dumped ``fiance`` for ``guy``!");
fiance.fiance = null;
gal.fiance = guy;
guy.fiance = gal;
}
else {
print("``gal`` turned down ``guy`` and stayed with ``fiance``!");
}
}
}
}
}
}
void checkStability() {
variable value stabilityFlag = true;
for (gal in gals) {
for (guy in guys) {
if (guy.prefers(gal) && gal.prefers(guy)) {
stabilityFlag = false;
print("``guy`` prefers ``gal`` over ``guy.fiance else "nobody"``
and ``gal`` prefers ``guy`` over ``gal.fiance else "nobody"``!".normalized);
}
}
}
print("``if(!stabilityFlag) then "Not " else ""``Stable!");
}