From cabb89d78909cd6998464580234b1baa639b41ae Mon Sep 17 00:00:00 2001 From: the-yash-rajput Date: Fri, 3 Oct 2025 13:44:58 +0530 Subject: [PATCH 1/3] Added CountBitsFlip aldo --- .../bitmanipulation/CountBitsFlip.java | 63 +++++++++++++ .../bitmanipulation/CountBitsFlipTest.java | 94 +++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java create mode 100644 src/test/java/com/thealgorithms/bitmanipulation/CountBitsFlipTest.java diff --git a/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java b/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java new file mode 100644 index 000000000000..daa72f4aaa2c --- /dev/null +++ b/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java @@ -0,0 +1,63 @@ +package com.thealgorithms.bitmanipulation; + +/** + * Implementation to count number of bits to be flipped to convert A to B + * + * Problem: Given two numbers A and B, count the number of bits needed to be + * flipped to convert A to B. + * + * Example: + * A = 10 (01010 in binary) + * B = 20 (10100 in binary) + * XOR = 30 (11110 in binary) - positions where bits differ + * Answer: 4 bits need to be flipped + * + * Time Complexity: O(log n) - where n is the number of set bits + * Space Complexity: O(1) + * + *@author [Yash Rajput](https://github.com/the-yash-rajput) + */ +public class CountBitsFlip { + + private CountBitsFlip() { + throw new AssertionError("No instances."); + } + + /** + * Counts the number of bits that need to be flipped to convert A to B + * + * Algorithm: + * 1. XOR A and B to get positions where bits differ + * 2. Count the number of set bits in the XOR result + * 3. Use Brian Kernighan's algorithm: n & (n-1) removes rightmost set bit + * + * @param A the source number + * @param B the target number + * @return the number of bits to flip to convert A to B + */ + public static long countBitsFlip(long A, long B) { + int count = 0; + + // XOR gives us positions where bits differ + long xorResult = A ^ B; + + // Count set bits using Brian Kernighan's algorithm + while (xorResult != 0) { + xorResult = xorResult & (xorResult - 1); // Remove rightmost set bit + count++; + } + + return count; + } + + /** + * Alternative implementation using Long.bitCount() + * + * @param A the source number + * @param B the target number + * @return the number of bits to flip to convert A to B + */ + public static long countBitsFlipAlternative(long A, long B) { + return Long.bitCount(A ^ B); + } +} diff --git a/src/test/java/com/thealgorithms/bitmanipulation/CountBitsFlipTest.java b/src/test/java/com/thealgorithms/bitmanipulation/CountBitsFlipTest.java new file mode 100644 index 000000000000..f33fa0fefbc0 --- /dev/null +++ b/src/test/java/com/thealgorithms/bitmanipulation/CountBitsFlipTest.java @@ -0,0 +1,94 @@ +package com.thealgorithms.bitmanipulation; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Random; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * Unit tests for CountBitsFlip. + * Covers: + * - simple examples + * - zeros and identical values + * - negative numbers and two's complement edge cases + * - Long.MIN_VALUE / Long.MAX_VALUE + * - randomized consistency checks between two implementations + */ +@DisplayName("CountBitsFlip Tests") +class CountBitsFlipTest { + + @Test + @DisplayName("Example: A=10, B=20 => 4 bits") + void exampleTenTwenty() { + long a = 10L; + long b = 20L; + long expected = 4L; + assertEquals(expected, CountBitsFlip.countBitsFlip(a, b), "Brian Kernighan implementation should return 4"); + assertEquals(expected, CountBitsFlip.countBitsFlipAlternative(a, b), "Long.bitCount implementation should return 4"); + } + + @Test + @DisplayName("Identical values => 0 bits") + void identicalValues() { + long a = 123456789L; + long b = 123456789L; + long expected = 0L; + assertEquals(expected, CountBitsFlip.countBitsFlip(a, b)); + assertEquals(expected, CountBitsFlip.countBitsFlipAlternative(a, b)); + } + + @Test + @DisplayName("Both zeros => 0 bits") + void bothZeros() { + assertEquals(0L, CountBitsFlip.countBitsFlip(0L, 0L)); + assertEquals(0L, CountBitsFlip.countBitsFlipAlternative(0L, 0L)); + } + + @Test + @DisplayName("Small example: A=15 (1111), B=8 (1000) => 3 bits") + void smallExample() { + long a = 15L; // 1111 + long b = 8L; // 1000 + long expected = 3L; // differs in three low bits + assertEquals(expected, CountBitsFlip.countBitsFlip(a, b)); + assertEquals(expected, CountBitsFlip.countBitsFlipAlternative(a, b)); + } + + @Test + @DisplayName("Negative values: -1 vs 0 => 64 bits (two's complement all ones)") + void negativeVsZero() { + long a = -1L; + long b = 0L; + long expected = 64L; // all 64 bits differ + assertEquals(expected, CountBitsFlip.countBitsFlip(a, b)); + assertEquals(expected, CountBitsFlip.countBitsFlipAlternative(a, b)); + } + + @Test + @DisplayName("Long.MIN_VALUE vs Long.MAX_VALUE => 64 bits") + void minMaxLongs() { + long a = Long.MIN_VALUE; + long b = Long.MAX_VALUE; + long expected = 64L; // MAX ^ MIN yields all ones on 64-bit long + assertEquals(expected, CountBitsFlip.countBitsFlip(a, b)); + assertEquals(expected, CountBitsFlip.countBitsFlipAlternative(a, b)); + } + + @Test + @DisplayName("Randomized consistency: both implementations agree across many pairs") + void randomizedConsistency() { + final int iterations = 1000; + final Random rnd = new Random(12345L); // deterministic seed for reproducibility + + for (int i = 0; i < iterations; i++) { + long a = rnd.nextLong(); + long b = rnd.nextLong(); + + long res1 = CountBitsFlip.countBitsFlip(a, b); + long res2 = CountBitsFlip.countBitsFlipAlternative(a, b); + + assertEquals(res2, res1, () -> String.format("Mismatch for a=%d, b=%d: impl1=%d, impl2=%d", a, b, res1, res2)); + } + } +} From 6a0c9b6887ad39e6984673940c5edcab9f3a28d9 Mon Sep 17 00:00:00 2001 From: the-yash-rajput Date: Fri, 3 Oct 2025 13:53:08 +0530 Subject: [PATCH 2/3] checkstyle fix --- .../java/com/thealgorithms/bitmanipulation/CountBitsFlip.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java b/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java index daa72f4aaa2c..f90a8686083b 100644 --- a/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java +++ b/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java @@ -17,7 +17,7 @@ * *@author [Yash Rajput](https://github.com/the-yash-rajput) */ -public class CountBitsFlip { +public final class CountBitsFlip { private CountBitsFlip() { throw new AssertionError("No instances."); From 44e6abca86a0bf5b0d1e6c3aaa9392ddbd29c0f8 Mon Sep 17 00:00:00 2001 From: the-yash-rajput Date: Fri, 3 Oct 2025 13:55:40 +0530 Subject: [PATCH 3/3] checkstyle fix --- .../bitmanipulation/CountBitsFlip.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java b/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java index f90a8686083b..8d2c757e5e0a 100644 --- a/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java +++ b/src/main/java/com/thealgorithms/bitmanipulation/CountBitsFlip.java @@ -24,22 +24,22 @@ private CountBitsFlip() { } /** - * Counts the number of bits that need to be flipped to convert A to B + * Counts the number of bits that need to be flipped to convert a to b * * Algorithm: - * 1. XOR A and B to get positions where bits differ + * 1. XOR a and b to get positions where bits differ * 2. Count the number of set bits in the XOR result * 3. Use Brian Kernighan's algorithm: n & (n-1) removes rightmost set bit * - * @param A the source number - * @param B the target number + * @param a the source number + * @param b the target number * @return the number of bits to flip to convert A to B */ - public static long countBitsFlip(long A, long B) { + public static long countBitsFlip(long a, long b) { int count = 0; // XOR gives us positions where bits differ - long xorResult = A ^ B; + long xorResult = a ^ b; // Count set bits using Brian Kernighan's algorithm while (xorResult != 0) { @@ -51,13 +51,13 @@ public static long countBitsFlip(long A, long B) { } /** - * Alternative implementation using Long.bitCount() + * Alternative implementation using Long.bitCount(). * - * @param A the source number - * @param B the target number - * @return the number of bits to flip to convert A to B + * @param a the source number + * @param b the target number + * @return the number of bits to flip to convert a to b */ - public static long countBitsFlipAlternative(long A, long B) { - return Long.bitCount(A ^ B); + public static long countBitsFlipAlternative(long a, long b) { + return Long.bitCount(a ^ b); } }