-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
176 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,116 @@ | ||
Todo: | ||
- Armando - values to test on | ||
- Armando- Questions | ||
- Armando/El - values to test on | ||
- Armando/El- Questions | ||
The conclusion | ||
|
||
Test Case 1: Programmers & Companies | ||
Programmer Preferences: | ||
Programmer 1: [0, 1, 2] | ||
Programmer 2: [1, 0, 2] | ||
Programmer 3: [2, 0, 1] | ||
|
||
Company Preferences: | ||
Company A: [1, 0, 2] | ||
Company B: [0, 1, 2] | ||
Company C: [2, 1, 0] | ||
Algorithm Execution: | ||
Step 1: | ||
Programmer 1 picks Company A their top choice. | ||
Company A accepts , they are free. | ||
Step 2: | ||
Programmer 2 picks Company B their top choice. | ||
Company B accepts, since they are free. | ||
Step 3: | ||
Programmer 3 picks Company C their top choice. | ||
Company C accepts, since they are free. | ||
Final Matching: | ||
Programmer 1 is matched with Company A | ||
Programmer 2 is matched with Company B | ||
Programmer 3 is matched with Company C | ||
|
||
|
||
Test Case 2 : Programmers & Companies | ||
Programmer Preferences: | ||
Programmer 1: [0, 1, 2] | ||
Programmer 2: [2, 1, 0] | ||
Programmer 3: [1, 2, 0] | ||
|
||
Company Preferences: | ||
Company A: [1, 2, 0] | ||
Company B: [0, 1, 2] | ||
Company C: [2, 0, 1] | ||
Steps: | ||
Programmer 1 asks Company A, and Company A accepts. | ||
Programmer 2 asks Company C, and Company C accepts. | ||
Programmer 3 asks Company B, and Company B acce pts. | ||
Final Matching: | ||
Programmer 1 matched with Company A | ||
Programmer 2 matched with Company C | ||
Programmer 3 matched with Company B | ||
|
||
|
||
Test Case 3: Larger Dataset (5 Programmers, 5 Companies) | ||
Programmer Preferences: | ||
Programmer 1: [1, 0, 2, 3, 4] | ||
Programmer 2: [0, 1, 3, 4, 2] | ||
Programmer 3: [2, 0, 1, 4, 3] | ||
Programmer 4: [4, 3, 2, 1, 0] | ||
Programmer 5: [0, 2, 3, 1, 4] | ||
|
||
Company Preferences: | ||
Company A: [1, 2, 3, 4, 0] | ||
Company B: [0, 3, 1, 2, 4] | ||
Company C: [2, 4, 1, 0, 3] | ||
Company D: [4, 2, 1, 0, 3] | ||
Company E: [0, 1, 2, 4, 3] | ||
|
||
Fianl mathcing: | ||
Programmer 1 matched with Company B | ||
Programmer 2 matched with Company A | ||
Programmer 3 matched with Company C | ||
Programmer 4 matched with Company E | ||
Programmer 5 matched with Company D | ||
|
||
|
||
Why the Algorithm is Correct? | ||
The Algorithm Always Stops, | ||
The algorithm will always come to an end because each programmer only gets to ask each company | ||
one time whether they can work there. There are a fixed number of programmers and companies, | ||
and each programmer can only ask each company once. If a programmer gets rejected, they move on | ||
to the next company in their list. Eventually, all programmers will either get a job at a company, | ||
or they will have asked all the companies and the process will end. The worst case is that every | ||
programmer asks every company, but the process won’t go on forever.The pairing we get at the end | ||
is "satisfactory" because we don’t have any situations where: | ||
|
||
A programmer is unhappy with their job and prefers a different company. | ||
The company also prefers that programmer over the person they currently hired. | ||
|
||
Programmers apply to the companies they like best first. | ||
Companies don’t immediately accept all applications. They hold out for the best option based on who | ||
has applied. If they find someone they like more than their current hire, they drop the old one and | ||
take the new person. This way, companies always end up with the best programmer they could get, and | ||
programmers end up with the best company that accepted them. This guarantees that no programmer or | ||
company would rather switch to another option after the process is done. This approach is based on | ||
a famous method called the Gale Shapley algorithm. It’s been mathematically proven to always find a | ||
solution where no one is unhappy enough to want to switch to a stable solution. The way it works is | ||
by having programmers "apply" to companies and companies only saying "yes" if it’s a good option for | ||
them. Because of the way this back and forth works, the final result will always be a stable match. | ||
Since the programmers are the ones doing the asking, the final result tends to be better for them. | ||
Each programmer gets the best company that they could possibly get based on how companies respond. | ||
The algorithm will always stop because each programmer has a limited number of companies they can | ||
apply to. It will always give a result where no one would want to swap with someone else after the | ||
matching is done. This approach is based on a well-proven theory (Gale Shapley) that ensures the | ||
matching will be stable. The programmers get the best possible deal for themselves. So, the algorithm | ||
works because it’s designed to reach a fair solution for everyone and it can’t go on forever. | ||
|
||
the worst case, the number of steps it takes grows with the square of | ||
the number of participants (programmers and companies). This happens | ||
because each programmer might have to go through all the companies before | ||
finding a match, and each company may have to consider multiple proposals | ||
before choosing the best one. So, if there are 10 programmers and 10 companies, | ||
the algorithm could take up to 100 steps. The space complexity is also O(N²) | ||
because the program needs to store all the preferences for both the programmers | ||
and companies, which adds up quickly as more participants are added. This means | ||
the program will take more memory and time as the number of participants increases | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,171 +1,106 @@ | ||
// Armando and El | ||
import java.lang.reflect.Array; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Scanner; | ||
|
||
class main{ | ||
public static void main(String[] args){ | ||
char[] alphabet = {'a','b','c','d','e','f','g','h','i','j'}; | ||
|
||
//test 3x3 | ||
//user entries: | ||
//int[][] companyPreferences1 = {{2, 3, 1}, {1, 2, 3}, {3, 2, 1}}; //this is what is entered on the user side | ||
//char[][] programerPreferences1 = {{'a','b','c'}, {'c','b','a'}, {'b','c','a'}}; //this is what is entered on the user side | ||
//what the program receives: | ||
//index equivalents of intended matches | ||
int[][] companyPreferencesTranslated1 = {{1, 2, 0}, {0, 1 , 2}, {2, 1, 0}}; | ||
int[][] programerPreferencesTranslated1 = {{0,1,2},{2,1,0},{1,2,0}}; | ||
int[] expected = {1, 0, 0, 1, 2, 2}; | ||
int[] returned = match(companyPreferencesTranslated1, programerPreferencesTranslated1); | ||
System.out.println("test one status:" + (Arrays.equals(expected, returned))); | ||
|
||
//test 2x2 | ||
//int[][] companyPreferences2 = {{1,2},{1,2}}; | ||
//char[][] programerPreferences2 = {{'a','b'},{'b','a'}}; | ||
int[][] companyPreferencesTranslated2 = {{0,1},{0,1}}; | ||
int[][] programerPreferencesTranslated2 = {{0,1},{1,0}}; | ||
int[] expected2 = {0, 0, 1, 1}; | ||
int[] returned2 = match(companyPreferencesTranslated2, programerPreferencesTranslated2); | ||
System.out.println("test two status:" + (Arrays.equals(expected2, returned2))); | ||
|
||
class Main { | ||
public static void main(String[] args) { | ||
Scanner s = new Scanner(System.in); | ||
System.out.println("Enter amount of Programers: "); | ||
System.out.println("Enter number of Programmers & Companies: "); | ||
int pro = s.nextInt(); | ||
|
||
//array constructors | ||
char[][] programerPreferencesScanner = new char[pro][pro]; | ||
int[][] companyPreferencesScanner = new int[pro][pro]; | ||
int[][] companyPreferencesTranslatedScanner = new int[pro][pro]; | ||
int[][] programerPreferences = new int[pro][pro]; | ||
int[][] companyPreferences = new int[pro][pro]; | ||
char[] alphabet = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; //these are the lables of the companies | ||
|
||
// processes first input for programer preferences | ||
String inputString1 = s.nextLine().toLowerCase(); | ||
char[] input1 = inputString1.toCharArray(); | ||
for (int j = 0; j < input1.length; j++) { | ||
programerPreferencesScanner[1][j] = input1[j]; | ||
} | ||
//processes rest of inputs | ||
for (int i = 0; i < pro; i++) { | ||
System.out.println("insert programer " + (i+1) + "'s preferences \nplease enter on one line with no spaces or commas"); | ||
String inputString = s.nextLine().toLowerCase(); | ||
char[] input = inputString.toCharArray(); | ||
for (int j = 0; j < input.length; j++) { | ||
programerPreferencesScanner[i][j] = input[j]; | ||
// the input preferences for programmer | ||
for(int i = 0; i < pro; i++){ | ||
System.out.println("put pref for programmer " + (i+1) + " (enter " + pro + " values):"); | ||
for(int j = 0; j < pro; j++){ | ||
programerPreferences[i][j] = s.nextInt(); | ||
} | ||
} | ||
|
||
//processes inputs for company preferences | ||
for (int i = 0; i < pro; i++) { | ||
System.out.println("insert preferences for company " + alphabet[i] + "\nplease enter each programer id number on a new line"); | ||
for (int j = 0; j < pro; j++) { | ||
companyPreferencesScanner[i][j] = s.nextInt(); | ||
companyPreferencesTranslatedScanner[i][j] = companyPreferencesScanner[i][j] -1; | ||
|
||
// the input preferences for companies | ||
for(int x = 0; x < pro; x++){ | ||
System.out.println("put pref for company " + alphabet[x] + " (enter " + pro + " values, where a=0, b=1, c=2, etc.):"); | ||
for(int y = 0; y < pro; y++){ | ||
companyPreferences[x][y] = s.nextInt(); | ||
} | ||
} | ||
//ends scanner | ||
s.close(); | ||
//translates user imputed programer preferences to something our method understands | ||
int[][] programerPreferencesTranslated = translator(programerPreferencesScanner); | ||
//calls match method | ||
int[] matches = match(companyPreferencesTranslatedScanner, programerPreferencesTranslated); | ||
|
||
//print statements | ||
System.out.println("Preferences in Array form \nprogramers: companies:"); | ||
int[] matches = match(programerPreferences, companyPreferences); | ||
|
||
// displaying the prefrences | ||
for (int i = 0; i < pro; i++) { | ||
int programerId = i + 1; | ||
// String c = Integer.toString(i + 1); | ||
System.out.println(programerId + Arrays.toString(programerPreferencesScanner[i]) + " " + alphabet[i] + Arrays.toString(companyPreferencesScanner[i])); | ||
} | ||
for (int i = 0; i < matches.length; i++) { | ||
if(i % 2 == 0) { | ||
System.out.println("Match #"+ (i/2 + 1)); | ||
System.out.println(matches[i] +1); | ||
} else { | ||
System.out.println(alphabet[matches[i]]); | ||
} | ||
System.out.println((i+1) + Arrays.toString(programerPreferences[i]) + " " + alphabet[i] + Arrays.toString(companyPreferences[i])); | ||
} | ||
} | ||
|
||
public static int[][] translator(char[][] companyPreferences){ | ||
//takes character array and converts it to integers where a = 0, b = 1, c = 2, etc... | ||
// logic to make everything lowercase is handled in scanner | ||
int[][] companyPreferencesTranslated = new int[companyPreferences.length][companyPreferences[0].length]; | ||
for (int i = 0; i < companyPreferences.length; i++) { | ||
for (int j = 0; j < companyPreferences[0].length; j++) { | ||
char c = companyPreferences[i][j]; | ||
int n = c - 97; | ||
companyPreferencesTranslated[i][j] = n; | ||
} | ||
// thiw is the matching results | ||
System.out.println("\nMatching results:"); | ||
for (int i = 0; i < matches.length; i++) { | ||
System.out.println("Programmer " + (matches[i] + 1) + " matched with Company " + alphabet[i]); | ||
} | ||
return companyPreferencesTranslated; | ||
} | ||
|
||
// the matching algorithm | ||
static int[] match(int[][] programerPreferences, int[][] companyPreferences) { | ||
// array construction | ||
// temp tracks current pairs | ||
// programersFree and companiesFree track who is not paired | ||
// stillFree tracks who is still free | ||
Map<Integer, Integer> temp = new HashMap<>(); | ||
int size = programerPreferences.length; | ||
Map<Integer, Integer> matches = new HashMap<>(); | ||
boolean[] programersFree = new boolean[size]; | ||
boolean[] companiesFree = new boolean[size]; | ||
Arrays.fill(programersFree, true); | ||
Arrays.fill(companiesFree, true); | ||
ArrayList<Integer> stillFree = new ArrayList<>(); | ||
|
||
while(stillFree.size() + temp.size() < size){ //while there is still unpaired people | ||
for (int i = 0; i < companiesFree.length; i++) { // go through free companies | ||
if (programersFree[i]) { //if the a programer is free | ||
for(int j = 0; j < size; j++){ //for each of the companies they are interested in | ||
if (companiesFree[programerPreferences[i][j]]) { //if the company is free | ||
temp.put(programerPreferences[i][j], i); // log pair | ||
programersFree[i] = false; //mark taken | ||
companiesFree[programerPreferences[i][j]] = false; // mark taken | ||
while (matches.size() < size) { | ||
for (int i = 0; i < size; i++) { | ||
if (programersFree[i]) { | ||
//the programmer i ask to their next preferred company | ||
for (int j = 0; j < size; j++) { | ||
int company = programerPreferences[i][j]; | ||
if (companiesFree[company]) { | ||
// the company if avalible, they accept the proposal | ||
matches.put(company, i); | ||
programersFree[i] = false; | ||
companiesFree[company] = false; | ||
break; | ||
} else { | ||
int possibleProgramer = programerPreferences[i][j]; //else record index of programer | ||
boolean match = checkMatch(possibleProgramer, i , programerPreferences[i][j], companyPreferences); //check if possibleProgram has higher interest from company than current hire | ||
if(!match){ | ||
// replace current match with new programer | ||
temp.put(programerPreferences[i][j], i); | ||
// the company already has a programmer, they will see if they prefer the new one | ||
int currentProgrammer = matches.get(company); | ||
boolean preferNew = checkMatch(currentProgrammer, i, company, companyPreferences); | ||
if (preferNew) { | ||
//the company switches to the new programmer if it is a better choice | ||
matches.put(company, i); | ||
programersFree[i] = false; | ||
programersFree[possibleProgramer] = true; | ||
programersFree[currentProgrammer] = true; | ||
break; | ||
} | ||
} | ||
} | ||
if (programersFree[i]) { | ||
//log that programer needs to go through the process again | ||
stillFree.add(i); | ||
} | ||
} | ||
} | ||
} | ||
// puts matched pairs from the hashMap to an array to be returned | ||
int[] matchedPairs = new int[2*temp.size()]; | ||
int i = 0; | ||
for(Map.Entry<Integer, Integer> entry : temp.entrySet()) { | ||
matchedPairs[i] = entry.getValue(); | ||
i++; | ||
matchedPairs[i] = entry.getKey(); | ||
i++; | ||
} | ||
} | ||
|
||
int[] matchedPairs = new int[size]; | ||
for (Map.Entry<Integer, Integer> entry : matches.entrySet()) { | ||
matchedPairs[entry.getKey()] = entry.getValue(); | ||
} | ||
return matchedPairs; | ||
} | ||
|
||
static boolean checkMatch(int possibleProgramer, int currentProgramer, int company, int[][] companyPreferences) { | ||
int p = 0; //index of possible possibleProgramer | ||
int c = 0; //index of currentProgramer | ||
for (int i = 0; i < companyPreferences.length; i++) { | ||
//for each of the programers the company is interested in, record if the possibleProgramer or current hire is higher | ||
if(companyPreferences[company][i] == possibleProgramer) { | ||
p = i; | ||
} else if (companyPreferences[company][i] == currentProgramer){ | ||
c = i; | ||
// it will check if the company wants the new programmer over the last pick | ||
static boolean checkMatch(int currentProgrammer, int newProgrammer, int company, int[][] companyPreferences) { | ||
for (int i = 0; i < companyPreferences[company].length; i++) { | ||
if (companyPreferences[company][i] == newProgrammer) { | ||
return true; // new programmer is picked over the last one | ||
} | ||
if (companyPreferences[company][i] == currentProgrammer) { | ||
return false; // if the current programmer is picked | ||
} | ||
} | ||
return p < c; // respond if the possible programer is of higher interest | ||
return false; | ||
} | ||
} | ||
} |