-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into dev/ps_ISSUE-2719
- Loading branch information
Showing
5 changed files
with
254 additions
and
6 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
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 |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/** | ||
* @brief Program to generate n-bit [Gray | ||
* code](https://en.wikipedia.org/wiki/Gray_code) | ||
* | ||
* @details | ||
* Gray code is a binary numeral system | ||
* where consecutive values differ in exactly 1 bit. | ||
* The following code offers one of many possible Gray codes | ||
* given some pre-determined number of bits. | ||
*/ | ||
|
||
#include <bitset> /// for gray code representation | ||
#include <cassert> /// for assert | ||
#include <iostream> /// for IO operations | ||
#include <vector> /// for vector data structure | ||
|
||
/** | ||
* @namespace bit_manipulation | ||
* @brief Bit manipulation algorithms | ||
*/ | ||
namespace bit_manipulation { | ||
/** | ||
* @namespace gray_code | ||
* @brief Generate n-bit Gray code | ||
*/ | ||
namespace gray_code { | ||
/** | ||
* @brief The main function to generate n-bit Gray code | ||
* | ||
* @param n Number of bits | ||
* @return A vector that stores the n-bit Gray code | ||
*/ | ||
std::vector<std::bitset<32>> gray_code_generation(int n) { | ||
std::vector<std::bitset<32>> gray_code = {}; // Initialise empty vector | ||
|
||
// No Gray codes for non-positive values of n | ||
if (n <= 0) { | ||
return gray_code; | ||
} | ||
|
||
int total_codes = 1 << n; // Number of n-bit gray codes | ||
|
||
for (int i = 0; i < total_codes; i++) { | ||
int gray_num = i ^ (i >> 1); // Gray code formula | ||
gray_code.push_back(std::bitset<32>(gray_num)); // Store the value | ||
} | ||
|
||
return gray_code; | ||
} | ||
} // namespace gray_code | ||
} // namespace bit_manipulation | ||
|
||
/** | ||
* @brief Self-test implementation | ||
* | ||
* @returns void | ||
*/ | ||
static void test() { | ||
std::vector<std::bitset<32>> gray_code_negative_1 = {}; | ||
|
||
std::vector<std::bitset<32>> gray_code_0 = {}; | ||
|
||
std::vector<std::bitset<32>> gray_code_1 = { | ||
std::bitset<32>(0), std::bitset<32>(1) | ||
}; | ||
|
||
std::vector<std::bitset<32>> gray_code_2 = { | ||
std::bitset<32>(0), std::bitset<32>(1), std::bitset<32>(3), std::bitset<32>(2) | ||
}; | ||
|
||
std::vector<std::bitset<32>> gray_code_3 = { | ||
std::bitset<32>(0), std::bitset<32>(1), std::bitset<32>(3), std::bitset<32>(2), | ||
std::bitset<32>(6), std::bitset<32>(7), std::bitset<32>(5), std::bitset<32>(4) | ||
}; | ||
|
||
std::vector<std::bitset<32>> gray_code_4 = { | ||
std::bitset<32>(0), std::bitset<32>(1), std::bitset<32>(3), std::bitset<32>(2), | ||
std::bitset<32>(6), std::bitset<32>(7), std::bitset<32>(5), std::bitset<32>(4), | ||
std::bitset<32>(12), std::bitset<32>(13), std::bitset<32>(15), std::bitset<32>(14), | ||
std::bitset<32>(10), std::bitset<32>(11), std::bitset<32>(9), std::bitset<32>(8) | ||
}; | ||
|
||
std::vector<std::bitset<32>> gray_code_5 = { | ||
std::bitset<32>(0), std::bitset<32>(1), std::bitset<32>(3), std::bitset<32>(2), | ||
std::bitset<32>(6), std::bitset<32>(7), std::bitset<32>(5), std::bitset<32>(4), | ||
std::bitset<32>(12), std::bitset<32>(13), std::bitset<32>(15), std::bitset<32>(14), | ||
std::bitset<32>(10), std::bitset<32>(11), std::bitset<32>(9), std::bitset<32>(8), | ||
std::bitset<32>(24), std::bitset<32>(25), std::bitset<32>(27), std::bitset<32>(26), | ||
std::bitset<32>(30), std::bitset<32>(31), std::bitset<32>(29), std::bitset<32>(28), | ||
std::bitset<32>(20), std::bitset<32>(21), std::bitset<32>(23), std::bitset<32>(22), | ||
std::bitset<32>(18), std::bitset<32>(19), std::bitset<32>(17), std::bitset<32>(16) | ||
}; | ||
|
||
// invalid values for n | ||
assert(bit_manipulation::gray_code::gray_code_generation(-1) == gray_code_negative_1); | ||
assert(bit_manipulation::gray_code::gray_code_generation(0) == gray_code_0); | ||
|
||
// valid values for n | ||
assert(bit_manipulation::gray_code::gray_code_generation(1) == gray_code_1); | ||
assert(bit_manipulation::gray_code::gray_code_generation(2) == gray_code_2); | ||
assert(bit_manipulation::gray_code::gray_code_generation(3) == gray_code_3); | ||
assert(bit_manipulation::gray_code::gray_code_generation(4) == gray_code_4); | ||
assert(bit_manipulation::gray_code::gray_code_generation(5) == gray_code_5); | ||
} | ||
|
||
/** | ||
* @brief Main function | ||
* @returns 0 on exit | ||
*/ | ||
int main() { | ||
test(); //Run self-test implementation | ||
return 0; | ||
} |
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 |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/** | ||
* @file | ||
* @brief [Gale Shapley Algorithm](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) | ||
* @details | ||
* This implementation utilizes the Gale-Shapley algorithm to find stable matches. | ||
* | ||
* **Gale Shapley Algorithm** aims to find a stable matching between two equally sized | ||
* sets of elements given an ordinal preference for each element. The algorithm was | ||
* introduced by David Gale and Lloyd Shapley in 1962. | ||
* | ||
* Reference: | ||
* [Wikipedia](https://en.wikipedia.org/wiki/Gale%E2%80%93Shapley_algorithm) | ||
* [Wikipedia](https://en.wikipedia.org/wiki/Stable_matching_problem) | ||
* | ||
* @author [B Karthik](https://github.com/BKarthik7) | ||
*/ | ||
|
||
#include <iostream> /// for std::u32int_t | ||
#include <vector> /// for std::vector | ||
#include <algorithm> /// for std::find | ||
#include <cassert> /// for assert | ||
|
||
/** | ||
* @namespace | ||
* @brief Greedy Algorithms | ||
*/ | ||
namespace greedy_algorithms { | ||
/** | ||
* @namespace | ||
* @brief Functions for the Gale-Shapley Algorithm | ||
*/ | ||
namespace stable_matching { | ||
/** | ||
* @brief The main function that finds the stable matching between two sets of elements | ||
* using the Gale-Shapley Algorithm. | ||
* @note This doesn't work on negative preferences. the preferences should be continuous integers starting from | ||
* 0 to number of preferences - 1. | ||
* @param primary_preferences the preferences of the primary set should be a 2D vector | ||
* @param secondary_preferences the preferences of the secondary set should be a 2D vector | ||
* @returns matches the stable matching between the two sets | ||
*/ | ||
std::vector<std::uint32_t> gale_shapley(const std::vector<std::vector<std::uint32_t>>& secondary_preferences, const std::vector<std::vector<std::uint32_t>>& primary_preferences) { | ||
std::uint32_t num_elements = secondary_preferences.size(); | ||
std::vector<std::uint32_t> matches(num_elements, -1); | ||
std::vector<bool> is_free_primary(num_elements, true); | ||
std::vector<std::uint32_t> proposal_index(num_elements, 0); // Tracks the next secondary to propose for each primary | ||
|
||
while (true) { | ||
int free_primary_index = -1; | ||
|
||
// Find the next free primary | ||
for (std::uint32_t i = 0; i < num_elements; i++) { | ||
if (is_free_primary[i]) { | ||
free_primary_index = i; | ||
break; | ||
} | ||
} | ||
|
||
// If no free primary is found, break the loop | ||
if (free_primary_index == -1) break; | ||
|
||
// Get the next secondary to propose | ||
std::uint32_t secondary_to_propose = primary_preferences[free_primary_index][proposal_index[free_primary_index]]; | ||
proposal_index[free_primary_index]++; | ||
|
||
// Get the current match of the secondary | ||
std::uint32_t current_match = matches[secondary_to_propose]; | ||
|
||
// If the secondary is free, match them | ||
if (current_match == -1) { | ||
matches[secondary_to_propose] = free_primary_index; | ||
is_free_primary[free_primary_index] = false; | ||
} else { | ||
// Determine if the current match should be replaced | ||
auto new_proposer_rank = std::find(secondary_preferences[secondary_to_propose].begin(), | ||
secondary_preferences[secondary_to_propose].end(), | ||
free_primary_index); | ||
auto current_match_rank = std::find(secondary_preferences[secondary_to_propose].begin(), | ||
secondary_preferences[secondary_to_propose].end(), | ||
current_match); | ||
|
||
// If the new proposer is preferred over the current match | ||
if (new_proposer_rank < current_match_rank) { | ||
matches[secondary_to_propose] = free_primary_index; | ||
is_free_primary[free_primary_index] = false; | ||
is_free_primary[current_match] = true; // Current match is now free | ||
} | ||
} | ||
} | ||
|
||
return matches; | ||
} | ||
} // namespace stable_matching | ||
} // namespace greedy_algorithms | ||
|
||
/** | ||
* @brief Self-test implementations | ||
* @returns void | ||
*/ | ||
static void tests() { | ||
// Test Case 1 | ||
std::vector<std::vector<std::uint32_t>> primary_preferences = {{0, 1, 2, 3}, {2, 1, 3, 0}, {1, 2, 0, 3}, {3, 0, 1, 2}}; | ||
std::vector<std::vector<std::uint32_t>> secondary_preferences = {{1, 0, 2, 3}, {3, 0, 1, 2}, {0, 2, 1, 3}, {1, 2, 0, 3}}; | ||
assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector<std::uint32_t>({0, 2, 1, 3})); | ||
|
||
// Test Case 2 | ||
primary_preferences = {{0, 2, 1, 3}, {2, 3, 0, 1}, {3, 1, 2, 0}, {2, 1, 0, 3}}; | ||
secondary_preferences = {{1, 0, 2, 3}, {3, 0, 1, 2}, {0, 2, 1, 3}, {1, 2, 0, 3}}; | ||
assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector<std::uint32_t>({0, 3, 1, 2})); | ||
|
||
// Test Case 3 | ||
primary_preferences = {{0, 1, 2}, {2, 1, 0}, {1, 2, 0}}; | ||
secondary_preferences = {{1, 0, 2}, {2, 0, 1}, {0, 2, 1}}; | ||
assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector<std::uint32_t>({0, 2, 1})); | ||
|
||
// Test Case 4 | ||
primary_preferences = {}; | ||
secondary_preferences = {}; | ||
assert(greedy_algorithms::stable_matching::gale_shapley(secondary_preferences, primary_preferences) == std::vector<std::uint32_t>({})); | ||
} | ||
|
||
/** | ||
* @brief Main function | ||
* @returns 0 on exit | ||
*/ | ||
int main() { | ||
tests(); // Run self-test implementations | ||
return 0; | ||
} |
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
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