June 2018 Update
This commit is contained in:
parent
ba8067c3b7
commit
22f33d4004
5278 changed files with 84726 additions and 14379 deletions
|
|
@ -1,139 +1,148 @@
|
|||
:: Stable Marriage Problem in Rosetta Code
|
||||
:: Batch File Implementation
|
||||
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
%== Initialization ==%
|
||||
set "male= abe bob col dan ed fred gav hal ian jon" ::First whitespace is necessary
|
||||
set "female= abi bea cath dee eve fay gay hope ivy jan" ::same here...
|
||||
:: Initialization (Index Starts in 0)
|
||||
set "male=abe bob col dan ed fred gav hal ian jon"
|
||||
set "femm=abi bea cath dee eve fay gay hope ivy jan"
|
||||
|
||||
::Initialization of pseudo-arrays [Male]
|
||||
set "cnt=0" & for %%. in (abi, eve, cath, ivy, jan, dee, fay, bea, hope, gay) do (set abe[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (cath, hope, abi, dee, eve, fay, bea, jan, ivy, gay) do (set bob[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (hope, eve, abi, dee, bea, fay, ivy, gay, cath, jan) do (set col[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (ivy, fay, dee, gay, hope, eve, jan, bea, cath, abi) do (set dan[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (jan, dee, bea, cath, fay, eve, abi, ivy, hope, gay) do (set ed[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (bea, abi, dee, gay, eve, ivy, cath, jan, hope, fay) do (set fred[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (gay, eve, ivy, bea, cath, abi, dee, hope, jan, fay) do (set gav[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (abi, eve, hope, fay, ivy, cath, jan, bea, gay, dee) do (set hal[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (hope, cath, dee, gay, bea, abi, fay, ivy, jan, eve) do (set ian[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (abi, fay, jan, gay, eve, bea, dee, cath, ivy, hope) do (set jon[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "abe[]=abi, eve, cath, ivy, jan, dee, fay, bea, hope, gay"
|
||||
set "bob[]=cath, hope, abi, dee, eve, fay, bea, jan, ivy, gay"
|
||||
set "col[]=hope, eve, abi, dee, bea, fay, ivy, gay, cath, jan"
|
||||
set "dan[]=ivy, fay, dee, gay, hope, eve, jan, bea, cath, abi"
|
||||
set "ed[]=jan, dee, bea, cath, fay, eve, abi, ivy, hope, gay"
|
||||
set "fred[]=bea, abi, dee, gay, eve, ivy, cath, jan, hope, fay"
|
||||
set "gav[]=gay, eve, ivy, bea, cath, abi, dee, hope, jan, fay"
|
||||
set "hal[]=abi, eve, hope, fay, ivy, cath, jan, bea, gay, dee"
|
||||
set "ian[]=hope, cath, dee, gay, bea, abi, fay, ivy, jan, eve"
|
||||
set "jon[]=abi, fay, jan, gay, eve, bea, dee, cath, ivy, hope"
|
||||
|
||||
::Initialization of pseudo-arrays [Female]
|
||||
set "cnt=0" & for %%. in (bob, fred, jon, gav, ian, abe, dan, ed, col, hal) do (set abi[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (bob, abe, col, fred, gav, dan, ian, ed, jon, hal) do (set bea[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (fred, bob, ed, gav, hal, col, ian, abe, dan, jon) do (set cath[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (fred, jon, col, abe, ian, hal, gav, dan, bob, ed) do (set dee[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (jon, hal, fred, dan, abe, gav, col, ed, ian, bob) do (set eve[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (bob, abe, ed, ian, jon, dan, fred, gav, col, hal) do (set fay[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (jon, gav, hal, fred, bob, abe, col, ed, dan, ian) do (set gay[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (gav, jon, bob, abe, ian, dan, hal, ed, col, fred) do (set hope[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (ian, col, hal, gav, fred, bob, abe, ed, jon, dan) do (set ivy[!cnt!]=%%.&set /a cnt+=1)
|
||||
set "cnt=0" & for %%. in (ed, hal, gav, abe, bob, jon, col, ian, fred, dan) do (set jan[!cnt!]=%%.&set /a cnt+=1)
|
||||
%==/Initialization ==%
|
||||
set "abi[]=bob, fred, jon, gav, ian, abe, dan, ed, col, hal"
|
||||
set "bea[]=bob, abe, col, fred, gav, dan, ian, ed, jon, hal"
|
||||
set "cath[]=fred, bob, ed, gav, hal, col, ian, abe, dan, jon"
|
||||
set "dee[]=fred, jon, col, abe, ian, hal, gav, dan, bob, ed"
|
||||
set "eve[]=jon, hal, fred, dan, abe, gav, col, ed, ian, bob"
|
||||
set "fay[]=bob, abe, ed, ian, jon, dan, fred, gav, col, hal"
|
||||
set "gay[]=jon, gav, hal, fred, bob, abe, col, ed, dan, ian"
|
||||
set "hope[]=gav, jon, bob, abe, ian, dan, hal, ed, col, fred"
|
||||
set "ivy[]=ian, col, hal, gav, fred, bob, abe, ed, jon, dan"
|
||||
set "jan[]=ed, hal, gav, abe, bob, jon, col, ian, fred, dan"
|
||||
|
||||
( %== The main thing ==%
|
||||
echo.HISTORY:
|
||||
rem variable notation:
|
||||
rem <boy>{<index>} = <girl>
|
||||
rem <boy>[<girl>] = <index>
|
||||
for %%M in (%male%) do (
|
||||
set cnt=0
|
||||
for %%. in (!%%M[]!) do (
|
||||
set "%%M{!cnt!}=%%."
|
||||
set "%%M[%%.]=!cnt!"
|
||||
set /a cnt+=1
|
||||
)
|
||||
)
|
||||
for %%F in (%femm%) do (
|
||||
set cnt=0
|
||||
for %%. in (!%%F[]!) do (
|
||||
set "%%F[%%.]=!cnt!"
|
||||
set /a cnt+=1
|
||||
)
|
||||
)
|
||||
|
||||
:: The Main Thing
|
||||
echo(HISTORY:
|
||||
call :stableMatching
|
||||
echo.
|
||||
echo.NEWLYWEDS:
|
||||
echo(
|
||||
echo(NEWLYWEDS:
|
||||
call :display
|
||||
echo.
|
||||
echo(
|
||||
call :isStable
|
||||
echo.
|
||||
echo.What if ed and hal swapped?
|
||||
echo(
|
||||
echo(What if ed and hal swapped?
|
||||
call :swapper ed hal
|
||||
echo.
|
||||
echo.NEW-NEWLYWEDS:
|
||||
echo(
|
||||
echo(NEW-NEWLYWEDS:
|
||||
call :display
|
||||
echo.
|
||||
echo(
|
||||
call :isStable
|
||||
pause>nul
|
||||
exit /b 0
|
||||
) %==/The main thing ==%
|
||||
|
||||
%== The algorithm ==%
|
||||
:: The Algorithm
|
||||
:stableMatching
|
||||
set "free_men=%male%" ::The free-men variable
|
||||
set "free_women=%female%" ::The free-women variable
|
||||
set nextgirl=0
|
||||
:thematchloop
|
||||
set m=&for %%F in (!free_men!) do (if not defined m set "m=%%F")
|
||||
if "!m!"=="" goto :EOF
|
||||
set "free_men=%male%"
|
||||
set "free_fem=%femm%"
|
||||
for %%M in (%male%) do set "%%M_tried=0"
|
||||
|
||||
for /f "tokens=1-2 delims==" %%A in ('set !m![!nextgirl!]') do set "w=%%B"
|
||||
set "propo="
|
||||
for %%W in (!free_women!) do (
|
||||
if "%%W"=="!w!" (
|
||||
set propo=TRUE
|
||||
set "!w!_=!m!" & set "!m!_=!w!"
|
||||
set free_women=!free_women: %w%=!
|
||||
set free_men=!free_men: %m%=!
|
||||
echo. !w! ACCEPTED !m!.
|
||||
)
|
||||
)
|
||||
if defined propo (set "nextgirl=0" & goto thematchloop)
|
||||
:match_loop
|
||||
if "%free_men%"=="" goto :EOF
|
||||
for /f "tokens=1* delims= " %%m in ("%free_men%") do (
|
||||
rem get woman not yet proposed to, but if man's tries exceeds the number
|
||||
rem of women (poor guy), he starts again to his most preferred woman (#0).
|
||||
for /f %%x in ("!%%m_tried!") do if not defined %%m{%%x} (
|
||||
set "%%m_tried=0" & set "w=!%%m{0}!"
|
||||
) else set "w=!%%m{%%x}!"
|
||||
set "m=%%m"
|
||||
|
||||
for /f "tokens=1-2 delims==" %%A in ('set !w!_') do set "mbef=%%B"
|
||||
set "replace=" & for /f "tokens=1-2 delims==" %%R in ('set !w![') do (
|
||||
if not defined replace (
|
||||
if "%%S"=="!m!" (
|
||||
set replace=TRUE
|
||||
set "!w!_=!m!" & set "!m!_=!w!"
|
||||
set "free_men=!free_men! !mbef!"
|
||||
set "free_men=!free_men: %m%=!"
|
||||
set nextgirl=0
|
||||
echo. !w! LEFT !mbef!.
|
||||
echo. !w! ACCEPTED !m!.
|
||||
)
|
||||
if "%%S"=="!mbef!" (
|
||||
set /a nextgirl+=1
|
||||
set replace=FALSE
|
||||
)
|
||||
)
|
||||
)
|
||||
goto thematchloop
|
||||
%==/The Algorithm ==%
|
||||
for /f %%x in ("free_fem:!w!=") do (
|
||||
if not "!free_fem!"=="!%%x!" (
|
||||
rem accept because !w! (the woman) is free
|
||||
set "!m!_=!w!" & set "!w!_=!m!"
|
||||
set "free_men=%%n" & set "free_fem=!%%x!"
|
||||
echo( !w! ACCEPTED !m!.
|
||||
) else (
|
||||
rem here, !w! already has a pair; get his name and rank.
|
||||
for /f %%. in ("!w!") do set "cur_man=!%%._!"
|
||||
for /f %%. in ("!w![!cur_man!]") do set "rank_cur=!%%.!"
|
||||
rem also, get the rank of current proposing man.
|
||||
for /f %%. in ("!w![!m!]") do set "rank_new=!%%.!"
|
||||
|
||||
%== Output the Couples ==%
|
||||
:display
|
||||
for %%S in (!male!) do echo. %%S and !%%S_!.
|
||||
goto :EOF
|
||||
%==/Output the Couples ==%
|
||||
|
||||
%== Stability Checking ==%
|
||||
:isStable
|
||||
for %%M in (!female!) do (
|
||||
set "better="
|
||||
set "dislike=" & for /f "tokens=1-2 delims==" %%R in ('set %%M[') do (
|
||||
if not defined dislike (
|
||||
if "%%S"=="!%%M_!" (set dislike=T) else (set "better=!better! %%S")
|
||||
)
|
||||
)
|
||||
for %%X in (!better!) do (
|
||||
for /f "tokens=1-2 delims==" %%F in ('set %%X_') do set curr_partner_of_boy=%%G
|
||||
set "main_check="
|
||||
for /f "tokens=1-2 delims==" %%B in ('set %%X[') do (
|
||||
if not defined main_check (
|
||||
if "%%C"=="%%M" (
|
||||
echo.STABILITY = FALSE.
|
||||
echo %%M and %%X would rather be together than their current partners.
|
||||
goto :EOF
|
||||
)
|
||||
if "%%C"=="!curr_partner_of_boy!" set "main_check=CONTINUE"
|
||||
)
|
||||
)
|
||||
)
|
||||
if !rank_new! lss !rank_cur! (
|
||||
rem here, !w! will leave her pair, and choose !m!.
|
||||
set "free_men=%%n !cur_man!"
|
||||
echo( !w! LEFT !cur_man!.
|
||||
rem pair them up now!
|
||||
set "!m!_=!w!" & set "!w!_=!m!"
|
||||
echo( !w! ACCEPTED !m!.
|
||||
)
|
||||
)
|
||||
)
|
||||
set /a "!m!_tried+=1"
|
||||
)
|
||||
echo.STABILITY = TRUE.
|
||||
goto :EOF
|
||||
%==/Stability Chacking ==%
|
||||
goto :match_loop
|
||||
|
||||
%== Swapper ==%
|
||||
:: Output the Couples
|
||||
:display
|
||||
for %%S in (%femm%) do echo. %%S and !%%S_!.
|
||||
goto :EOF
|
||||
|
||||
:: Stability Checking
|
||||
:isStable
|
||||
for %%f in (%femm%) do (
|
||||
for %%g in (%male%) do (
|
||||
for /f %%. in ("%%f[!%%f_!]") do set "girl_cur=!%%.!"
|
||||
set "girl_aboy=!%%f[%%g]!"
|
||||
for /f %%. in ("%%g[!%%g_!]") do set "boy_cur=!%%.!"
|
||||
set "boy_agirl=!%%g[%%f]!"
|
||||
|
||||
if !boy_cur! gtr !boy_agirl! (
|
||||
if !girl_cur! gtr !girl_aboy! (
|
||||
echo(STABILITY = FALSE.
|
||||
echo(%%f and %%g would rather be together than their current partners.
|
||||
goto :EOF
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
echo(STABILITY = TRUE.
|
||||
goto :EOF
|
||||
|
||||
:: Swapper
|
||||
:swapper
|
||||
set %~1.tmp=!%~1_!
|
||||
set %~2.tmp=!%~2_!
|
||||
set "%~1_=!%~2.tmp!"
|
||||
set "%~2_=!%~1.tmp!"
|
||||
set "!%~1.tmp!_=%~2"
|
||||
set "!%~2.tmp!_=%~1"
|
||||
goto :EOF
|
||||
%==/Swapper==%
|
||||
set %~1.tmp=!%~1_!
|
||||
set %~2.tmp=!%~2_!
|
||||
set "%~1_=!%~2.tmp!"
|
||||
set "%~2_=!%~1.tmp!"
|
||||
set "!%~1.tmp!_=%~2"
|
||||
set "!%~2.tmp!_=%~1"
|
||||
goto :EOF
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
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!");
|
||||
}
|
||||
125
Task/Stable-marriage-problem/Julia/stable-marriage-problem.julia
Normal file
125
Task/Stable-marriage-problem/Julia/stable-marriage-problem.julia
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
# This is not optimized, but tries to follow the pseudocode given the Wikipedia entry below.
|
||||
# Reference: https://en.wikipedia.org/wiki/Stable_marriage_problem#Algorithm
|
||||
|
||||
const males = ["abe", "bob", "col", "dan", "ed", "fred", "gav", "hal", "ian", "jon"]
|
||||
const females = ["abi", "bea", "cath", "dee", "eve", "fay", "gay", "hope", "ivy", "jan"]
|
||||
|
||||
const malepreferences = Dict(
|
||||
"abe" => ["abi", "eve", "cath", "ivy", "jan", "dee", "fay", "bea", "hope", "gay"],
|
||||
"bob" => ["cath", "hope", "abi", "dee", "eve", "fay", "bea", "jan", "ivy", "gay"],
|
||||
"col" => ["hope", "eve", "abi", "dee", "bea", "fay", "ivy", "gay", "cath", "jan"],
|
||||
"dan" => ["ivy", "fay", "dee", "gay", "hope", "eve", "jan", "bea", "cath", "abi"],
|
||||
"ed" => ["jan", "dee", "bea", "cath", "fay", "eve", "abi", "ivy", "hope", "gay"],
|
||||
"fred" => ["bea", "abi", "dee", "gay", "eve", "ivy", "cath", "jan", "hope", "fay"],
|
||||
"gav" => ["gay", "eve", "ivy", "bea", "cath", "abi", "dee", "hope", "jan", "fay"],
|
||||
"hal" => ["abi", "eve", "hope", "fay", "ivy", "cath", "jan", "bea", "gay", "dee"],
|
||||
"ian" => ["hope", "cath", "dee", "gay", "bea", "abi", "fay", "ivy", "jan", "eve"],
|
||||
"jon" => ["abi", "fay", "jan", "gay", "eve", "bea", "dee", "cath", "ivy", "hope"]
|
||||
)
|
||||
|
||||
const femalepreferences = Dict(
|
||||
"abi"=> ["bob", "fred", "jon", "gav", "ian", "abe", "dan", "ed", "col", "hal"],
|
||||
"bea"=> ["bob", "abe", "col", "fred", "gav", "dan", "ian", "ed", "jon", "hal"],
|
||||
"cath"=> ["fred", "bob", "ed", "gav", "hal", "col", "ian", "abe", "dan", "jon"],
|
||||
"dee"=> ["fred", "jon", "col", "abe", "ian", "hal", "gav", "dan", "bob", "ed"],
|
||||
"eve"=> ["jon", "hal", "fred", "dan", "abe", "gav", "col", "ed", "ian", "bob"],
|
||||
"fay"=> ["bob", "abe", "ed", "ian", "jon", "dan", "fred", "gav", "col", "hal"],
|
||||
"gay"=> ["jon", "gav", "hal", "fred", "bob", "abe", "col", "ed", "dan", "ian"],
|
||||
"hope"=> ["gav", "jon", "bob", "abe", "ian", "dan", "hal", "ed", "col", "fred"],
|
||||
"ivy"=> ["ian", "col", "hal", "gav", "fred", "bob", "abe", "ed", "jon", "dan"],
|
||||
"jan"=> ["ed", "hal", "gav", "abe", "bob", "jon", "col", "ian", "fred", "dan"]
|
||||
)
|
||||
|
||||
function pshuf(d)
|
||||
ret = Dict()
|
||||
for (k,v) in d
|
||||
ret[k] = shuffle(v)
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
# helper functions for the verb: p1 "prefers" p2 over p3
|
||||
pindexin(a, p) = ([i for i in 1:length(a) if a[i] == p])[1]
|
||||
prefers(d, p1, p2, p3) = (pindexin(d[p1], p2) < pindexin(d[p1], p3))
|
||||
|
||||
function isstable(mmatchup, fmatchup, mpref, fpref)
|
||||
for (mmatch, fmatch) in mmatchup
|
||||
for f in mpref[mmatch]
|
||||
if(f != fmatch && prefers(mpref, mmatch, f, fmatch)
|
||||
&& prefers(fpref, f, mmatch, fmatchup[f]))
|
||||
println("$mmatch prefers $f and $f prefers $mmatch over their current partners.")
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
function galeshapley(men, women, malepref, femalepref)
|
||||
# Initialize all m ∈ M and w ∈ W to free
|
||||
mfree = Dict([(p, true) for p in men])
|
||||
wfree = Dict([(p, true) for p in women])
|
||||
mpairs = Dict()
|
||||
wpairs = Dict()
|
||||
while true # while ∃ free man m who still has a woman w to propose to
|
||||
bachelors = [p for p in keys(mfree) if mfree[p]]
|
||||
if(length(bachelors) == 0)
|
||||
return mpairs, wpairs
|
||||
end
|
||||
for m in bachelors
|
||||
for w in malepref[m] # w = first woman on m’s list to whom m has not yet proposed
|
||||
if(wfree[w]) # if w is free (else some pair (m', w) already exists)
|
||||
#println("Free match: $m, $w")
|
||||
mpairs[m] = w # (m, w) become engaged
|
||||
wpairs[w] = m # double entry bookeeping
|
||||
mfree[m] = false
|
||||
wfree[w] = false
|
||||
break
|
||||
elseif(prefers(femalepref, w, m, wpairs[w])) # if w prefers m to m'
|
||||
#println("Unmatch $(wpairs[w]), match: $m, $w")
|
||||
mfree[wpairs[w]] = true # m' becomes free
|
||||
mpairs[m] = w # (m, w) become engaged
|
||||
wpairs[w] = m
|
||||
mfree[m] = false
|
||||
break
|
||||
end # else (m', w) remain engaged, so continue
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tableprint(txt, ans, stab)
|
||||
println(txt)
|
||||
println(" Man Woman")
|
||||
println(" ----- -----")
|
||||
show(STDOUT, "text/plain", ans)
|
||||
if(stab)
|
||||
println("\n ----STABLE----\n\n")
|
||||
else
|
||||
println("\n ---UNSTABLE---\n\n")
|
||||
end
|
||||
end
|
||||
|
||||
println("Use the Gale Shapley algorithm to find a stable set of engagements.")
|
||||
answer = galeshapley(males, females, malepreferences, femalepreferences)
|
||||
stabl = isstable(answer[1], answer[2], malepreferences, femalepreferences)
|
||||
tableprint("Original Data Table", answer[1], stabl)
|
||||
|
||||
println("To check this is not a one-off solution, run the function on a randomized sample.")
|
||||
newmpref = pshuf(malepreferences)
|
||||
newfpref = pshuf(femalepreferences)
|
||||
answer = galeshapley(males, females, newmpref, newfpref)
|
||||
stabl = isstable(answer[1], answer[2], newmpref, newfpref)
|
||||
tableprint("Shuffled Preferences", answer[1], stabl)
|
||||
|
||||
# trade abe with bob
|
||||
println("Perturb this set of engagements to form an unstable set of engagements then check this new set for stability.")
|
||||
answer = galeshapley(males, females, malepreferences, femalepreferences)
|
||||
fia1 = (answer[1])["abe"]
|
||||
fia2 = (answer[1])["bob"]
|
||||
answer[1]["abe"] = fia2
|
||||
answer[1]["bob"] = fia1
|
||||
answer[2][fia1] = "bob"
|
||||
answer[2][fia2] = "abe"
|
||||
stabl = isstable(answer[1], answer[2], malepreferences, femalepreferences)
|
||||
tableprint("Original Data With Bob and Abe Switched", answer[1], stabl)
|
||||
|
|
@ -1,122 +1,106 @@
|
|||
import java.util.*
|
||||
data class Person(val name: String) {
|
||||
val preferences = mutableListOf<Person>()
|
||||
var matchedTo: Person? = null
|
||||
|
||||
class People(val map: Map<String, Array<String>>) {
|
||||
operator fun get(name: String) = map[name]
|
||||
|
||||
val names: List<String> by lazy { map.keys.toList() }
|
||||
|
||||
fun preferences(k: String, v: String): List<String> {
|
||||
val prefers = get(k)!!
|
||||
return ArrayList<String>(prefers.slice(0..prefers.indexOf(v)))
|
||||
}
|
||||
}
|
||||
|
||||
class EngagementRegistry() : TreeMap<String, String>() {
|
||||
constructor(guys: People, girls: People) : this() {
|
||||
val freeGuys = guys.names.toMutableList()
|
||||
while (freeGuys.any()) {
|
||||
val guy = freeGuys.removeAt(0) // get a load of THIS guy
|
||||
val guy_p = guys[guy]!!
|
||||
for (girl in guy_p)
|
||||
if (this[girl] == null) {
|
||||
this[girl] = guy // girl is free
|
||||
break
|
||||
} else {
|
||||
val other = this[girl]!!
|
||||
val girl_p = girls[girl]!!
|
||||
if (girl_p.indexOf(guy) < girl_p.indexOf(other)) {
|
||||
this[girl] = guy // this girl prefers this guy to the guy she's engaged to
|
||||
freeGuys += other
|
||||
break
|
||||
} // else no change... keep looking for this guy
|
||||
}
|
||||
fun trySwap(p: Person) {
|
||||
if (prefers(p)) {
|
||||
matchedTo?.matchedTo = null
|
||||
matchedTo = p
|
||||
p.matchedTo = this
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val s = StringBuilder()
|
||||
for ((k, v) in this) s.append("$k is engaged to $v\n")
|
||||
return s.toString()
|
||||
fun prefers(p: Person) = when (matchedTo) {
|
||||
null -> true
|
||||
else -> preferences.indexOf(p) < preferences.indexOf(matchedTo!!)
|
||||
}
|
||||
|
||||
fun analyse(guys: People, girls: People) {
|
||||
if (check(guys, girls))
|
||||
println("Marriages are stable")
|
||||
else
|
||||
println("Marriages are unstable")
|
||||
}
|
||||
fun showMatch() = "$name <=> ${matchedTo?.name}"
|
||||
}
|
||||
|
||||
fun swap(girls: People, i: Int, j: Int) {
|
||||
val n1 = girls.names[i]
|
||||
val n2 = girls.names[j]
|
||||
val g0 = this[n1]!!
|
||||
val g1 = this[n2]!!
|
||||
this[n1] = g1
|
||||
this[n2] = g0
|
||||
println("$n1 and $n2 have switched partners")
|
||||
}
|
||||
|
||||
private fun check(guys: People, girls: People): Boolean {
|
||||
val guy_names = guys.names
|
||||
val girl_names = girls.names
|
||||
if (!keys.containsAll(girl_names) or !values.containsAll(guy_names))
|
||||
return false
|
||||
|
||||
val invertedMatches = TreeMap<String, String>()
|
||||
for ((k, v) in this) invertedMatches[v] = k
|
||||
|
||||
for ((k, v) in this) {
|
||||
val sheLikesBetter = girls.preferences(k, v)
|
||||
val heLikesBetter = guys.preferences(v, k)
|
||||
for (guy in sheLikesBetter) {
|
||||
val fiance = invertedMatches[guy]
|
||||
val guy_p = guys[guy]!!
|
||||
if (guy_p.indexOf(fiance) > guy_p.indexOf(k)) {
|
||||
println("$k likes $guy better than $v and $guy likes $k better than their current partner")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for (girl in heLikesBetter) {
|
||||
val fiance = get(girl)
|
||||
val girl_p = girls[girl]!!
|
||||
if (girl_p.indexOf(fiance) > girl_p.indexOf(v)) {
|
||||
println("$v likes $girl better than $k and $girl likes $v better than their current partner")
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
fun match(males: Collection<Person>) {
|
||||
while (males.find { it.matchedTo == null }?.also { match(it) } != null) {
|
||||
}
|
||||
}
|
||||
|
||||
fun match(male: Person) {
|
||||
while (male.matchedTo == null) {
|
||||
male.preferences.removeAt(0).trySwap(male)
|
||||
}
|
||||
}
|
||||
|
||||
fun isStableMatch(males: Collection<Person>, females: Collection<Person>): Boolean {
|
||||
return males.all { isStableMatch(it, females) }
|
||||
}
|
||||
|
||||
fun isStableMatch(male: Person, females: Collection<Person>): Boolean {
|
||||
|
||||
val likesBetter = females.filter { !male.preferences.contains(it) }
|
||||
val stable = !likesBetter.any { it.prefers(male) }
|
||||
|
||||
if (!stable) {
|
||||
println("#### Unstable pair: ${male.showMatch()}")
|
||||
}
|
||||
return stable
|
||||
}
|
||||
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val guys = People(mapOf("abe" to arrayOf("abi", "eve", "cath", "ivy", "jan", "dee", "fay", "bea", "hope", "gay"),
|
||||
"bob" to arrayOf("cath", "hope", "abi", "dee", "eve", "fay", "bea", "jan", "ivy", "gay"),
|
||||
"col" to arrayOf("hope", "eve", "abi", "dee", "bea", "fay", "ivy", "gay", "cath", "jan"),
|
||||
"dan" to arrayOf("ivy", "fay", "dee", "gay", "hope", "eve", "jan", "bea", "cath", "abi"),
|
||||
"ed" to arrayOf("jan", "dee", "bea", "cath", "fay", "eve", "abi", "ivy", "hope", "gay"),
|
||||
"fred" to arrayOf("bea", "abi", "dee", "gay", "eve", "ivy", "cath", "jan", "hope", "fay"),
|
||||
"gav" to arrayOf("gay", "eve", "ivy", "bea", "cath", "abi", "dee", "hope", "jan", "fay"),
|
||||
"hal" to arrayOf("abi", "eve", "hope", "fay", "ivy", "cath", "jan", "bea", "gay", "dee"),
|
||||
"ian" to arrayOf("hope", "cath", "dee", "gay", "bea", "abi", "fay", "ivy", "jan", "eve"),
|
||||
"jon" to arrayOf("abi", "fay", "jan", "gay", "eve", "bea", "dee", "cath", "ivy", "hope")))
|
||||
val inMales = mapOf(
|
||||
"abe" to mutableListOf("abi", "eve", "cath", "ivy", "jan", "dee", "fay", "bea", "hope", "gay"),
|
||||
"bob" to mutableListOf("cath", "hope", "abi", "dee", "eve", "fay", "bea", "jan", "ivy", "gay"),
|
||||
"col" to mutableListOf("hope", "eve", "abi", "dee", "bea", "fay", "ivy", "gay", "cath", "jan"),
|
||||
"dan" to mutableListOf("ivy", "fay", "dee", "gay", "hope", "eve", "jan", "bea", "cath", "abi"),
|
||||
"ed" to mutableListOf("jan", "dee", "bea", "cath", "fay", "eve", "abi", "ivy", "hope", "gay"),
|
||||
"fred" to mutableListOf("bea", "abi", "dee", "gay", "eve", "ivy", "cath", "jan", "hope", "fay"),
|
||||
"gav" to mutableListOf("gay", "eve", "ivy", "bea", "cath", "abi", "dee", "hope", "jan", "fay"),
|
||||
"hal" to mutableListOf("abi", "eve", "hope", "fay", "ivy", "cath", "jan", "bea", "gay", "dee"),
|
||||
"ian" to mutableListOf("hope", "cath", "dee", "gay", "bea", "abi", "fay", "ivy", "jan", "eve"),
|
||||
"jon" to mutableListOf("abi", "fay", "jan", "gay", "eve", "bea", "dee", "cath", "ivy", "hope"))
|
||||
|
||||
val girls = People(mapOf("abi" to arrayOf("bob", "fred", "jon", "gav", "ian", "abe", "dan", "ed", "col", "hal"),
|
||||
"bea" to arrayOf("bob", "abe", "col", "fred", "gav", "dan", "ian", "ed", "jon", "hal"),
|
||||
"cath" to arrayOf("fred", "bob", "ed", "gav", "hal", "col", "ian", "abe", "dan", "jon"),
|
||||
"dee" to arrayOf("fred", "jon", "col", "abe", "ian", "hal", "gav", "dan", "bob", "ed"),
|
||||
"eve" to arrayOf("jon", "hal", "fred", "dan", "abe", "gav", "col", "ed", "ian", "bob"),
|
||||
"fay" to arrayOf("bob", "abe", "ed", "ian", "jon", "dan", "fred", "gav", "col", "hal"),
|
||||
"gay" to arrayOf("jon", "gav", "hal", "fred", "bob", "abe", "col", "ed", "dan", "ian"),
|
||||
"hope" to arrayOf("gav", "jon", "bob", "abe", "ian", "dan", "hal", "ed", "col", "fred"),
|
||||
"ivy" to arrayOf("ian", "col", "hal", "gav", "fred", "bob", "abe", "ed", "jon", "dan"),
|
||||
"jan" to arrayOf("ed", "hal", "gav", "abe", "bob", "jon", "col", "ian", "fred", "dan")))
|
||||
val inFemales = mapOf(
|
||||
"abi" to listOf("bob", "fred", "jon", "gav", "ian", "abe", "dan", "ed", "col", "hal"),
|
||||
"bea" to listOf("bob", "abe", "col", "fred", "gav", "dan", "ian", "ed", "jon", "hal"),
|
||||
"cath" to listOf("fred", "bob", "ed", "gav", "hal", "col", "ian", "abe", "dan", "jon"),
|
||||
"dee" to listOf("fred", "jon", "col", "abe", "ian", "hal", "gav", "dan", "bob", "ed"),
|
||||
"eve" to listOf("jon", "hal", "fred", "dan", "abe", "gav", "col", "ed", "ian", "bob"),
|
||||
"fay" to listOf("bob", "abe", "ed", "ian", "jon", "dan", "fred", "gav", "col", "hal"),
|
||||
"gay" to listOf("jon", "gav", "hal", "fred", "bob", "abe", "col", "ed", "dan", "ian"),
|
||||
"hope" to listOf("gav", "jon", "bob", "abe", "ian", "dan", "hal", "ed", "col", "fred"),
|
||||
"ivy" to listOf("ian", "col", "hal", "gav", "fred", "bob", "abe", "ed", "jon", "dan"),
|
||||
"jan" to listOf("ed", "hal", "gav", "abe", "bob", "jon", "col", "ian", "fred", "dan"))
|
||||
|
||||
with(EngagementRegistry(guys, girls)) {
|
||||
print(this)
|
||||
analyse(guys, girls)
|
||||
swap(girls, 0, 1)
|
||||
analyse(guys, girls)
|
||||
|
||||
fun buildPrefs(person: Person, stringPrefs: List<String>, population: List<Person>) {
|
||||
person.preferences.addAll(
|
||||
stringPrefs.map { name -> population.single { it.name == name } }
|
||||
)
|
||||
}
|
||||
|
||||
val males = inMales.keys.map { Person(it) }
|
||||
val females = inFemales.keys.map { Person(it) }
|
||||
|
||||
males.forEach { buildPrefs(it, inMales[it.name]!!, females) }
|
||||
females.forEach { buildPrefs(it, inFemales[it.name]!!, males) }
|
||||
|
||||
|
||||
match(males)
|
||||
males.forEach { println(it.showMatch()) }
|
||||
println("#### match is stable: ${isStableMatch(males, females)}")
|
||||
|
||||
|
||||
fun swapMatch(male1: Person, male2: Person) {
|
||||
val female1 = male1.matchedTo!!
|
||||
val female2 = male2.matchedTo!!
|
||||
|
||||
male1.matchedTo = female2
|
||||
male2.matchedTo = female1
|
||||
|
||||
female1.matchedTo = male2
|
||||
female2.matchedTo = male1
|
||||
}
|
||||
|
||||
swapMatch(males.single { it.name == "fred" }, males.single { it.name == "jon" })
|
||||
males.forEach { println(it.showMatch()) }
|
||||
println("#### match is stable: ${isStableMatch(males, females)}")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue