From 35e2bb6172101edec1f124fb816eddcf36d2e5d7 Mon Sep 17 00:00:00 2001 From: Armando Valdez <155396846+valde148@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:17:38 -0500 Subject: [PATCH] new changes --- README.me | 117 +++++++++++++++++++++++++++++++++- main.java | 187 ++++++++++++++++++------------------------------------ 2 files changed, 176 insertions(+), 128 deletions(-) diff --git a/README.me b/README.me index 384ea15..acc70d4 100644 --- a/README.me +++ b/README.me @@ -1,3 +1,116 @@ Todo: -- Armando - values to test on -- Armando- Questions \ No newline at end of file +- 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 + + diff --git a/main.java b/main.java index ec0aa10..8148463 100644 --- a/main.java +++ b/main.java @@ -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 temp = new HashMap<>(); int size = programerPreferences.length; + Map matches = new HashMap<>(); boolean[] programersFree = new boolean[size]; boolean[] companiesFree = new boolean[size]; Arrays.fill(programersFree, true); Arrays.fill(companiesFree, true); - ArrayList 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 entry : temp.entrySet()) { - matchedPairs[i] = entry.getValue(); - i++; - matchedPairs[i] = entry.getKey(); - i++; } + } + + int[] matchedPairs = new int[size]; + for (Map.Entry 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; } -} \ No newline at end of file +}