11import sequtils, std/ enumerate, random, strutils
2- const PAIRS = 10
3- const m_names = [" abe" , " bob" , " col" , " dan" , " ed" , " fred" , " gav" , " hal" , " ian" , " jon" ]
4- const f_names = [" abi" , " bea" , " cath" , " dee" , " eve" , " fay" , " gay" , " hope" ,
5- " ivy" , " jan" ]
6- const m_prefs = [
2+ const Pairs = 10
3+ const MNames = [" abe" , " bob" , " col" , " dan" , " ed" , " fred" , " gav" , " hal" , " ian" , " jon" ]
4+ const FNames = [" abi" , " bea" , " cath" , " dee" , " eve" , " fay" , " gay" , " hope" , " ivy" , " jan" ]
5+ const MPreferences = [
76[" abi" , " eve" , " cath" , " ivy" , " jan" , " dee" , " fay" , " bea" , " hope" , " gay" ],
87[" cath" , " hope" , " abi" , " dee" , " eve" , " fay" , " bea" , " jan" , " ivy" , " gay" ],
98[" hope" , " eve" , " abi" , " dee" , " bea" , " fay" , " ivy" , " gay" , " cath" , " jan" ],
@@ -15,7 +14,7 @@ const m_prefs = [
1514[" hope" , " cath" , " dee" , " gay" , " bea" , " abi" , " fay" , " ivy" , " jan" , " eve" ],
1615[" abi" , " fay" , " jan" , " gay" , " eve" , " bea" , " dee" , " cath" , " ivy" , " hope" ]
1716]
18- const f_prefs = [
17+ const FPreferences = [
1918[" bob" , " fred" , " jon" , " gav" , " ian" , " abe" , " dan" , " ed" , " col" , " hal" ],
2019[" bob" , " abe" , " col" , " fred" , " gav" , " dan" , " ian" , " ed" , " jon" , " hal" ],
2120[" fred" , " bob" , " ed" , " gav" , " hal" , " col" , " ian" , " abe" , " dan" , " jon" ],
@@ -29,93 +28,87 @@ const f_prefs = [
2928]
3029
3130# recipient's preferences hold the preference score for each contender's id
32- func get_rec_prefs [N: static int ](prefs: array [N, array [N, string ]],
33- names: openArray [string ]): seq [seq [int ]] {.compileTime .} =
34- for pref_seq in prefs:
35- var p = newSeq [int ](PAIRS )
36- for contender in 0 ..< PAIRS :
37- p[contender] = pref_seq.find (m_names[contender])
38- result .add (p)
31+ func getRecPreferences [N: static int ](prefs: array [N, array [N, string ]],
32+ names: openArray [string ]): array [N, array [N, int ]] {.compileTime .} =
33+ for r, prefArray in enumerate (prefs):
34+ for c, contender in enumerate (prefArray):
35+ result [r][c] = prefArray.find (MNames [c])
3936
4037# contender's preferences hold the recipient ids in descending order of preference
41- func get_cont_prefs (prefs: array [PAIRS , array [PAIRS , string ]], names: openArray [
42- string ]): seq [seq [int ]] {.compileTime .} =
43- for pref_seq in prefs:
44- var p: seq [int ]
45- for pref in pref_seq:
46- p.add (names.find (pref))
47- result .add (p)
38+ func getContPreferences [N: static int ](prefs: array [N, array [N, string ]], names: openArray [
39+ string ]): array [N, array [N, int ]] {.compileTime .} =
40+ for c, pref_seq in enumerate (prefs):
41+ for r, pref in enumerate (pref_seq):
42+ result [c][r] = names.find (pref)
4843
49- const RECIPIENT_PREFS = get_rec_prefs (f_prefs, m_names )
50- const CONTENDER_PREFS = get_cont_prefs (m_prefs, f_names )
44+ const RecipientPrefs = getRecPreferences ( FPreferences , MNames )
45+ const ContenderPrefs = getContPreferences ( MPreferences , FNames )
5146
52- proc print_couples (cont_pairs : seq [int ]) =
53- for c, r in enumerate (cont_pairs ):
54- echo m_names [c] & " π" & f_names[cont_pairs [c]]
47+ proc printCoupleNames (contPairs : seq [int ]) =
48+ for c, r in enumerate (contPairs ):
49+ echo MNames [c] & " π" & FNames [contPairs [c]]
5550
5651func pair (): (seq [int ], seq [int ]) =
5752 # double booking to avoid inverse lookup using find
58- var rec_pairs = newSeqWith (10 , - 1 )
59- var cont_pairs = newSeqWith (10 , - 1 )
53+ var recPairs = newSeqWith (10 , - 1 )
54+ var contPairs = newSeqWith (10 , - 1 )
6055 proc engage (c, r: int ) =
61- # echo f_names [r] & " accepted " & m_names [c]
62- cont_pairs [c] = r
63- rec_pairs [r] = c
64- var cont_queue = newSeqWith (10 , 0 )
65- while cont_pairs .contains (- 1 ):
66- for c in 0 ..< PAIRS :
67- if cont_pairs [c] == - 1 :
68- let r = CONTENDER_PREFS [c][cont_queue [c]] # proposing to first in queue
69- cont_queue [c]+= 1 # increment contender's queue for future iterations
70- let cur_pair = rec_pairs [r] # current pair's index or -1 = vacant
71- if cur_pair == - 1 :
56+ # echo FNames [r] & " accepted " & MNames [c]
57+ contPairs [c] = r
58+ recPairs [r] = c
59+ var contQueue = newSeqWith (10 , 0 )
60+ while contPairs .contains (- 1 ):
61+ for c in 0 ..< Pairs :
62+ if contPairs [c] == - 1 :
63+ let r = ContenderPrefs [c][contQueue [c]] # proposing to first in queue
64+ contQueue [c]+= 1 # increment contender's queue for future iterations
65+ let curPair = recPairs [r] # current pair's index or -1 = vacant
66+ if curPair == - 1 :
7267 engage (c, r)
7368 # contender is more preferable than current
74- elif RECIPIENT_PREFS [r][c] < RECIPIENT_PREFS [r][cur_pair ]:
75- cont_pairs[cur_pair ] = - 1 # vacate current pair
76- # echo m_names[cur_pair ] & " was dumped by " & f_names [r]
69+ elif RecipientPrefs [r][c] < RecipientPrefs [r][curPair ]:
70+ contPairs[curPair ] = - 1 # vacate current pair
71+ # echo MNames[curPair ] & " was dumped by " & FNames [r]
7772 engage (c, r)
78- result = (cont_pairs, rec_pairs )
73+ result = (contPairs, recPairs )
7974
80- proc rand_pair (max: int ): (int , int ) =
75+ proc randomPair (max: int ): (int , int ) =
8176 let a = rand (max)
8277 var b = rand (max- 1 )
8378 if b == a:
8479 b = max
8580 result = (a,b)
8681
87- proc perturb_pairs (cont_pairs, rec_pairs : var seq [int ]) =
82+ proc perturbPairs (contPairs, recPairs : var seq [int ]) =
8883 randomize ()
89- let (a,b) = rand_pair ( PAIRS - 1 )
90- echo " Swapping " & m_names [a] & " & " & m_names [b] & " partners"
91- swap (cont_pairs [a], cont_pairs [b])
92- swap (rec_pairs[cont_pairs [a]], rec_pairs[cont_pairs [b]])
84+ let (a,b) = randomPair ( Pairs - 1 )
85+ echo " Swapping " & MNames [a] & " & " & MNames [b] & " partners"
86+ swap (contPairs [a], contPairs [b])
87+ swap (recPairs[contPairs [a]], recPairs[contPairs [b]])
9388
94- proc check_stability (cont_pairs, rec_pairs: seq [int ]): bool =
95- for c in 0 ..< PAIRS : # each contender
96- let cur_p_score = CONTENDER_PREFS [c].find (cont_pairs[c]) # pref. score for current pair
97- for preferred_id in 0 ..< cur_p_score: # try every recipient with higher score
98- let check_r = CONTENDER_PREFS [c][preferred_id]
99- let cur_r_p = rec_pairs[check_r] # current pair of checked recipient
100- # if score of the cur_r_p is worse (>) than score of checked contender
101- if RECIPIENT_PREFS [check_r][cur_r_p] > RECIPIENT_PREFS [check_r][c]:
102- echo m_names[c] & " prefers " & f_names[check_r] & " over " & f_names[cont_pairs[c]]
103- echo f_names[check_r] & " prefers " & m_names[c] & " over " & m_names[cur_r_p]
89+ proc checkPairStability (contPairs, recPairs: seq [int ]): bool =
90+ for c in 0 ..< Pairs : # each contender
91+ let curPairScore = ContenderPrefs [c].find (contPairs[c]) # pref. score for current pair
92+ for preferredRec in 0 ..< curPairScore: # try every recipient with higher score
93+ let checkedRec = ContenderPrefs [c][preferredRec]
94+ let curRecPair = recPairs[checkedRec] # current pair of checked recipient
95+ # if score of the curRecPair is worse (>) than score of checked contender
96+ if RecipientPrefs [checkedRec][curRecPair] > RecipientPrefs [checkedRec][c]:
97+ echo " π " & MNames [c] & " prefers " &
98+ FNames [checkedRec] & " over " & FNames [contPairs[c]]
99+ echo " π " & FNames [checkedRec] & " prefers " &
100+ MNames [c] & " over " & MNames [curRecPair]
101+ echo " β Unstable"
104102 return false # unstable
103+ echo " β Stable"
105104 result = true
106105
107106when isMainModule :
108- var (cont_pairs, rec_pairs ) = pair ()
109- print_couples (cont_pairs )
107+ var (contPairs, recPairs ) = pair ()
108+ printCoupleNames (contPairs )
110109 echo " Current pair analysis:"
111- echo if check_stability (cont_pairs, rec_pairs):
112- " β Stable"
113- else :
114- " β Unstable"
115- perturb_pairs (cont_pairs, rec_pairs)
116- print_couples (cont_pairs)
110+ discard checkPairStability (contPairs, recPairs)
111+ perturbPairs (contPairs, recPairs)
112+ printCoupleNames (contPairs)
117113 echo " Current pair analysis:"
118- echo if check_stability (cont_pairs, rec_pairs):
119- " β Stable"
120- else :
121- " β Unstable"
114+ discard checkPairStability (contPairs, recPairs)
0 commit comments