From 0ce5df0c216d41faca1938b4afe231119d9f1ec0 Mon Sep 17 00:00:00 2001 From: Ravishankar Joshi <21024229+ravibitsgoa@users.noreply.github.com> Date: Wed, 17 Feb 2021 08:08:29 +0530 Subject: [PATCH] feat: Hamming distance algorithm. (#1376) * Added bit manipulation algorithms. * Removed Power of 2 and xor swap. * Update bit_manipulation/hamming_distance.cpp Co-authored-by: David Leal * Update bit_manipulation/hamming_distance.cpp Co-authored-by: David Leal * Update bit_manipulation/hamming_distance.cpp Co-authored-by: David Leal * updating DIRECTORY.md * clang-format and clang-tidy fixes for ae4d4707 * Apply suggestions from code review Co-authored-by: David Leal * test: docs: Added tests and docs for hamming distance. * Apply suggestions from code review Co-authored-by: David Leal * clang-format and clang-tidy fixes for 94fb407b * Update bit_manipulation/hamming_distance.cpp Co-authored-by: David Leal * feat: Added string method for hamming distance. * Apply suggestions from code review Co-authored-by: David Leal * clang-format and clang-tidy fixes for 455dce1d * fix: Make hamming distance algorithm work for all strings. * clang-format and clang-tidy fixes for ba18ec04 Co-authored-by: David Leal Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 3 + bit_manipulation/hamming_distance.cpp | 107 ++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 bit_manipulation/hamming_distance.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index cf3bafb75..91cecffc8 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -10,6 +10,9 @@ * [Rat Maze](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/rat_maze.cpp) * [Sudoku Solve](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/sudoku_solve.cpp) +## Bit Manipulation + * [Hamming Distance](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/bit_manipulation/hamming_distance.cpp) + ## Ciphers * [Caesar Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/caesar_cipher.cpp) * [Hill Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/hill_cipher.cpp) diff --git a/bit_manipulation/hamming_distance.cpp b/bit_manipulation/hamming_distance.cpp new file mode 100644 index 000000000..62879cf48 --- /dev/null +++ b/bit_manipulation/hamming_distance.cpp @@ -0,0 +1,107 @@ +/** + * @file + * @brief Returns the [Hamming + * distance](https://en.wikipedia.org/wiki/Hamming_distance) between two + * integers + * + * @details + * To find hamming distance between two integers, we take their xor, which will + * have a set bit iff those bits differ in the two numbers. + * Hence, we return the number of such set bits. + * + * @author [Ravishankar Joshi](https://github.com/ravibitsgoa) + */ + +#include /// for assert +#include /// for io operations + +/** + * @namespace bit_manipulation + * @brief Bit Manipulation algorithms + */ +namespace bit_manipulation { +/** + * @namespace hamming_distance + * @brief Functions for [Hamming + * distance](https://en.wikipedia.org/wiki/Hamming_distance) implementation + */ +namespace hamming_distance { +/** + * This function returns the number of set bits in the given number. + * @param value the number of which we want to count the number of set bits. + * @returns the number of set bits in the given number. + */ +uint64_t bitCount(uint64_t value) { + uint64_t count = 0; + while (value) { // until all bits are zero + if (value & 1) { // check lower bit + count++; + } + value >>= 1; // shift bits, removing lower bit + } + return count; +} + +/** + * This function returns the hamming distance between two integers. + * @param a the first number + * @param b the second number + * @returns the number of bits differing between the two integers. + */ +uint64_t hamming_distance(uint64_t a, uint64_t b) { return bitCount(a ^ b); } + +/** + * This function returns the hamming distance between two strings. + * @param a the first string + * @param b the second string + * @returns the number of characters differing between the two strings. + */ +uint64_t hamming_distance(const std::string& a, const std::string& b) { + assert(a.size() == b.size()); + size_t n = a.size(); + uint64_t count = 0; + for (size_t i = 0; i < n; i++) { + count += (b[i] != a[i]); + } + return count; +} +} // namespace hamming_distance +} // namespace bit_manipulation + +/** + * @brief Function to the test hamming distance. + * @returns void + */ +static void test() { + assert(bit_manipulation::hamming_distance::hamming_distance(11, 2) == 2); + assert(bit_manipulation::hamming_distance::hamming_distance(2, 0) == 1); + assert(bit_manipulation::hamming_distance::hamming_distance(11, 0) == 3); + + assert(bit_manipulation::hamming_distance::hamming_distance("1101", + "1111") == 1); + assert(bit_manipulation::hamming_distance::hamming_distance("1111", + "1111") == 0); + assert(bit_manipulation::hamming_distance::hamming_distance("0000", + "1111") == 4); + + assert(bit_manipulation::hamming_distance::hamming_distance("alpha", + "alphb") == 1); + assert(bit_manipulation::hamming_distance::hamming_distance("abcd", + "abcd") == 0); + assert(bit_manipulation::hamming_distance::hamming_distance("dcba", + "abcd") == 4); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // execute the tests + uint64_t a = 11; // 1011 in binary + uint64_t b = 2; // 0010 in binary + + std::cout << "Hamming distance between " << a << " and " << b << " is " + << bit_manipulation::hamming_distance::hamming_distance(a, b) + << std::endl; +}