Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d624cb4

Browse files
committedOct 5, 2024·
feat: Add GaleShapley in a new folder Greedy
1 parent 5b17ea1 commit d624cb4

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed
 

‎Greedy/GaleShapley.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* The Gale-Shapley algorithm is used to find a stable matching between two sets
3+
* of equal size (e.g., donors and recipients) where no two elements prefer each
4+
* other over their current partners. It ensures a stable matching by proposing
5+
* from one side to the other until all are matched.
6+
*
7+
* Complexity:
8+
* Worst-case performance O(n^2)
9+
* Best-case performance O(n^2)
10+
*
11+
* Reference:
12+
* https://en.wikipedia.org/wiki/Stable_marriage_problem
13+
* https://www.youtube.com/watch?v=Qcv1IqHWAzg (Numberphile)
14+
*
15+
*/
16+
17+
/**
18+
*
19+
* @param {number[][]} donorPref Preferences of donors, where each donor has an ordered list of recipients.
20+
* @param {number[][]} recipientPref Preferences of recipients, where each recipient has an ordered list of donors.
21+
* @returns {number[]} Array where the index is the donor, and the value at the index is the matched recipient.
22+
*
23+
* @example
24+
* const donorPref = [[0, 1, 3, 2], [0, 2, 3, 1], [1, 0, 2, 3], [0, 3, 1, 2]];
25+
* const recipientPref = [[3, 1, 2, 0], [3, 1, 0, 2], [0, 3, 1, 2], [1, 0, 3, 2]];
26+
* stableMatching(donorPref, recipientPref); // Output: [1, 2, 3, 0]
27+
*/
28+
function stableMatching(donorPref, recipientPref) {
29+
// Initialize the number of donors and create a list of unmatched donors
30+
let n = donorPref.length
31+
let unmatchedDonors = Array.from({ length: n }, (_, i) => i)
32+
33+
// Records of which recipient each donor is paired with and vice versa
34+
let donorRecord = Array(n).fill(-1) // Donor to recipient
35+
let recRecord = Array(n).fill(-1) // Recipient to donor
36+
37+
// Array to track how many recipients each donor has proposed to
38+
let numDonations = Array(n).fill(0)
39+
40+
// While there are unmatched donors
41+
while (unmatchedDonors.length > 0) {
42+
// Take the first unmatched donor
43+
let donor = unmatchedDonors[0]
44+
let donorPreference = donorPref[donor]
45+
46+
// Find the next recipient this donor prefers
47+
let recipient = donorPreference[numDonations[donor]]
48+
numDonations[donor] += 1
49+
50+
// Get recipient's preference list and check the current match
51+
let recPreference = recipientPref[recipient]
52+
let prevDonor = recRecord[recipient]
53+
54+
// If recipient is already matched, check if they prefer the new donor
55+
if (prevDonor !== -1) {
56+
if (recPreference.indexOf(prevDonor) > recPreference.indexOf(donor)) {
57+
// If the new donor is preferred, match them and unmatch the previous donor
58+
recRecord[recipient] = donor
59+
donorRecord[donor] = recipient
60+
unmatchedDonors.push(prevDonor)
61+
unmatchedDonors.splice(unmatchedDonors.indexOf(donor), 1) // Remove the current donor from unmatched
62+
}
63+
} else {
64+
// If the recipient is not matched, pair them with the current donor
65+
recRecord[recipient] = donor
66+
donorRecord[donor] = recipient
67+
unmatchedDonors.splice(unmatchedDonors.indexOf(donor), 1) // Remove the current donor from unmatched
68+
}
69+
}
70+
71+
return donorRecord
72+
}
73+
74+
// // Example usage:
75+
// const donorPref = [[0, 1, 3, 2], [0, 2, 3, 1], [1, 0, 2, 3], [0, 3, 1, 2]];
76+
// const recipientPref = [[3, 1, 2, 0], [3, 1, 0, 2], [0, 3, 1, 2], [1, 0, 3, 2]];
77+
// console.log(stableMatching(donorPref, recipientPref)); // Output: [1, 2, 3, 0]
78+
export { stableMatching }

‎Greedy/test/GaleShapley.test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { expect, test } from 'vitest'
2+
import { stableMatching } from '../GaleShapley'
3+
4+
test('Test Case 1', () => {
5+
const donorPref = [
6+
[0, 1, 3, 2],
7+
[0, 2, 3, 1],
8+
[1, 0, 2, 3],
9+
[0, 3, 1, 2]
10+
]
11+
const recipientPref = [
12+
[3, 1, 2, 0],
13+
[3, 1, 0, 2],
14+
[0, 3, 1, 2],
15+
[1, 0, 3, 2]
16+
]
17+
expect(stableMatching(donorPref, recipientPref)).toEqual([1, 2, 3, 0])
18+
})
19+
test('Test Case 2', () => {
20+
const donorPref = [
21+
[0, 1, 2],
22+
[0, 1, 2],
23+
[0, 1, 2]
24+
]
25+
const recipientPref = [
26+
[0, 1, 2],
27+
[0, 1, 2],
28+
[0, 1, 2]
29+
]
30+
expect(stableMatching(donorPref, recipientPref)).toEqual([0, 1, 2])
31+
})
32+
test('Test Case 3', () => {
33+
const donorPref = []
34+
const recipientPref = []
35+
expect(stableMatching(donorPref, recipientPref)).toEqual([])
36+
})

0 commit comments

Comments
 (0)
Please sign in to comment.