From a179b5b8f5b56ae4014b7e961e2ef58498048cf6 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Mon, 27 Oct 2025 13:46:33 +0530 Subject: [PATCH 1/8] Add One-Time Pad Cipher implementation in Java --- .../ciphers/OneTimePadCipher.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java diff --git a/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java b/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java new file mode 100644 index 000000000000..e8e15efab00a --- /dev/null +++ b/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java @@ -0,0 +1,72 @@ +package com.thealgorithms.ciphers; + +import java.security.SecureRandom; + +/** + * The One-Time Pad Cipher is a symmetric encryption technique + * that XORs plaintext with a truly random key of equal length. + * + * ⚠️ Important: + * - The key must be random and used only once. + * - Key reuse makes it insecure. + * + * Example: + * Plaintext: HELLO + * Key: XMCKL + * Ciphertext: EQNVZ + * + * Reference: + * Shannon, C. E. (1949). Communication Theory of Secrecy Systems. + */ +public class OneTimePadCipher { + + private static final SecureRandom RANDOM = new SecureRandom(); + + /** + * Encrypts or decrypts a message using the One-Time Pad method. + * + * @param input The input string (plaintext or ciphertext) + * @param key The key (must be the same length as input) + * @return The resulting encrypted/decrypted string + */ + public static String xorCipher(String input, String key) { + if (input.length() != key.length()) { + throw new IllegalArgumentException("Input and key lengths must match!"); + } + + StringBuilder output = new StringBuilder(); + for (int i = 0; i < input.length(); i++) { + char encryptedChar = (char) (input.charAt(i) ^ key.charAt(i)); + output.append(encryptedChar); + } + return output.toString(); + } + + /** + * Generates a random key of the same length as the message. + * + * @param length The desired key length + * @return A random key string + */ + public static String generateRandomKey(int length) { + StringBuilder key = new StringBuilder(); + for (int i = 0; i < length; i++) { + // Generate printable ASCII range (32–126) + key.append((char) (RANDOM.nextInt(95) + 32)); + } + return key.toString(); + } + + public static void main(String[] args) { + String message = "HELLO WORLD"; + String key = generateRandomKey(message.length()); + + String encrypted = xorCipher(message, key); + String decrypted = xorCipher(encrypted, key); + + System.out.println("Message: " + message); + System.out.println("Key: " + key); + System.out.println("Encrypted: " + encrypted); + System.out.println("Decrypted: " + decrypted); + } +} From 1e78a3fb9edb33daf9e0a0b98e21be58f31bf16e Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Mon, 27 Oct 2025 14:18:37 +0530 Subject: [PATCH 2/8] Add One-Time Pad Cipher implementation (fixed) --- .../ciphers/OneTimePadCipher.java.txt | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java.txt diff --git a/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java.txt b/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java.txt new file mode 100644 index 000000000000..356bc3ef59a7 --- /dev/null +++ b/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java.txt @@ -0,0 +1,66 @@ +package com.thealgorithms.ciphers; + +import java.security.SecureRandom; + +/** + * Implementation of the One-Time Pad Cipher. + * + *

The One-Time Pad Cipher is a symmetric encryption technique that XORs + * plaintext with a truly random key of equal length. It is considered + * theoretically unbreakable when the key is random, used only once, and kept + * secret. + * + *

Example: + * + *

+ * Plaintext:  HELLO
+ * Key:        XMCKL
+ * Ciphertext: EQNVZ
+ * 
+ * + * @see Wikipedia: One-time pad + */ +public final class OneTimePadCipher { + + private static final SecureRandom RANDOM = new SecureRandom(); + + private OneTimePadCipher() { + // Utility class; prevent instantiation. + } + + /** + * Encrypts or decrypts a message using the One-Time Pad method. + * + * @param input the input string (plaintext or ciphertext) + * @param key the key (must be the same length as input) + * @return the resulting encrypted/decrypted string + * @throws IllegalArgumentException if input and key lengths do not match + */ + public static String xorCipher(String input, String key) { + if (input.length() != key.length()) { + throw new IllegalArgumentException("Input and key lengths must match!"); + } + + StringBuilder output = new StringBuilder(); + for (int i = 0; i < input.length(); i++) { + char encryptedChar = (char) (input.charAt(i) ^ key.charAt(i)); + output.append(encryptedChar); + } + return output.toString(); + } + + /** + * Generates a random key of the same length as the message. + * + * @param length the desired key length + * @return a random key string + */ + public static String generateRandomKey(int length) { + StringBuilder key = new StringBuilder(); + for (int i = 0; i < length; i++) { + // Generate printable ASCII range (32–126) + key.append((char) (RANDOM.nextInt(95) + 32)); + } + return key.toString(); + } +} From e43878b7a8c12bfbd487d9350d8a2d3a47b28c36 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 12:35:26 +0530 Subject: [PATCH 3/8] Add ThreadedBinaryTree with in-order traversal and tests --- .../trees/ThreadedBinaryTree.java | 138 ++++++++++++++++++ .../trees/ThreadedBinaryTreeTest.java | 44 ++++++ 2 files changed, 182 insertions(+) create mode 100644 src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java create mode 100644 src/test/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTreeTest.java diff --git a/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java b/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java new file mode 100644 index 000000000000..0a4a7c15aaa5 --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java @@ -0,0 +1,138 @@ +package com.thealgorithms.datastructures.trees; + +import java.util.ArrayList; +import java.util.List; + +/** + * Threaded binary tree implementation that supports insertion and + * in-order traversal without recursion or stack by using threads. + * + *

In this implementation, a node's null left/right pointers are used + * to point to the in-order predecessor/successor respectively. Two flags + * indicate whether left/right pointers are real children or threads. + * + * @see Wikipedia: + * Threaded binary tree + */ +public final class ThreadedBinaryTree { + + private Node root; + + private static final class Node { + int value; + Node left; + Node right; + boolean leftIsThread; + boolean rightIsThread; + + Node(int value) { + this.value = value; + this.left = null; + this.right = null; + this.leftIsThread = false; + this.rightIsThread = false; + } + } + + public ThreadedBinaryTree() { + this.root = null; + } + + /** + * Inserts a value into the threaded binary tree. Duplicate values are inserted + * to the right subtree (consistent deterministic rule). + * + * @param value the integer value to insert + */ + public void insert(int value) { + Node newNode = new Node(value); + if (root == null) { + root = newNode; + return; + } + + Node current = root; + Node parent = null; + while (current != null) { + parent = current; + if (value < current.value) { + if (!current.leftIsThread && current.left != null) { + current = current.left; + } else { + break; + } + } else { // value >= current.value + if (!current.rightIsThread && current.right != null) { + current = current.right; + } else { + break; + } + } + } + + if (value < parent.value) { + // attach newNode as left child + newNode.left = parent.left; + newNode.leftIsThread = parent.leftIsThread; + newNode.right = parent; + newNode.rightIsThread = true; + + parent.left = newNode; + parent.leftIsThread = false; + } else { + // attach newNode as right child + newNode.right = parent.right; + newNode.rightIsThread = parent.rightIsThread; + newNode.left = parent; + newNode.leftIsThread = true; + + parent.right = newNode; + parent.rightIsThread = false; + } + } + + /** + * Returns the in-order traversal of the tree as a list of integers. + * Traversal is done without recursion or an explicit stack by following threads. + * + * @return list containing the in-order sequence of node values + */ + public List inorderTraversal() { + List result = new ArrayList<>(); + Node current = root; + if (current == null) { + return result; + } + + // Move to the leftmost node + while (current.left != null && !current.leftIsThread) { + current = current.left; + } + + while (current != null) { + result.add(current.value); + + // If right pointer is a thread, follow it + if (current.rightIsThread) { + current = current.right; + } else { + // Move to leftmost node in right subtree + current = current.right; + while (current != null && !current.leftIsThread && current.left != null) { + current = current.left; + } + } + } + + return result; + } + + /** + * Helper: checks whether the tree is empty. + * + * @return true if tree has no nodes + */ + public boolean isEmpty() { + return root == null; + } +} diff --git a/src/test/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTreeTest.java b/src/test/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTreeTest.java new file mode 100644 index 000000000000..8d0c251149fc --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTreeTest.java @@ -0,0 +1,44 @@ +package com.thealgorithms.datastructures.trees; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import org.junit.jupiter.api.Test; + +/** + * Basic tests for ThreadedBinaryTree inorder traversal. + */ +public class ThreadedBinaryTreeTest { + + @Test + public void testInorderTraversalSimple() { + ThreadedBinaryTree tree = new ThreadedBinaryTree(); + tree.insert(50); + tree.insert(30); + tree.insert(70); + tree.insert(20); + tree.insert(40); + tree.insert(60); + tree.insert(80); + + List expected = List.of(20, 30, 40, 50, 60, 70, 80); + List actual = tree.inorderTraversal(); + + assertEquals(expected, actual); + } + + @Test + public void testInorderWithDuplicates() { + ThreadedBinaryTree tree = new ThreadedBinaryTree(); + tree.insert(5); + tree.insert(3); + tree.insert(7); + tree.insert(7); // duplicate + tree.insert(2); + + List expected = List.of(2, 3, 5, 7, 7); + List actual = tree.inorderTraversal(); + + assertEquals(expected, actual); + } +} From 75e7657bbf1b3d94c1f2f567b8faa5455f04791a Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 13:10:54 +0530 Subject: [PATCH 4/8] feat: add threaded binary tree implementation and tests --- .../ciphers/OneTimePadCipher.java | 72 ------------------- .../ciphers/OneTimePadCipher.java.txt | 66 ----------------- .../trees/ThreadedBinaryTree.java | 6 ++ .../trees/ThreadedBinaryTreeTest.java | 6 ++ 4 files changed, 12 insertions(+), 138 deletions(-) delete mode 100644 src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java delete mode 100644 src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java.txt diff --git a/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java b/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java deleted file mode 100644 index e8e15efab00a..000000000000 --- a/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.thealgorithms.ciphers; - -import java.security.SecureRandom; - -/** - * The One-Time Pad Cipher is a symmetric encryption technique - * that XORs plaintext with a truly random key of equal length. - * - * ⚠️ Important: - * - The key must be random and used only once. - * - Key reuse makes it insecure. - * - * Example: - * Plaintext: HELLO - * Key: XMCKL - * Ciphertext: EQNVZ - * - * Reference: - * Shannon, C. E. (1949). Communication Theory of Secrecy Systems. - */ -public class OneTimePadCipher { - - private static final SecureRandom RANDOM = new SecureRandom(); - - /** - * Encrypts or decrypts a message using the One-Time Pad method. - * - * @param input The input string (plaintext or ciphertext) - * @param key The key (must be the same length as input) - * @return The resulting encrypted/decrypted string - */ - public static String xorCipher(String input, String key) { - if (input.length() != key.length()) { - throw new IllegalArgumentException("Input and key lengths must match!"); - } - - StringBuilder output = new StringBuilder(); - for (int i = 0; i < input.length(); i++) { - char encryptedChar = (char) (input.charAt(i) ^ key.charAt(i)); - output.append(encryptedChar); - } - return output.toString(); - } - - /** - * Generates a random key of the same length as the message. - * - * @param length The desired key length - * @return A random key string - */ - public static String generateRandomKey(int length) { - StringBuilder key = new StringBuilder(); - for (int i = 0; i < length; i++) { - // Generate printable ASCII range (32–126) - key.append((char) (RANDOM.nextInt(95) + 32)); - } - return key.toString(); - } - - public static void main(String[] args) { - String message = "HELLO WORLD"; - String key = generateRandomKey(message.length()); - - String encrypted = xorCipher(message, key); - String decrypted = xorCipher(encrypted, key); - - System.out.println("Message: " + message); - System.out.println("Key: " + key); - System.out.println("Encrypted: " + encrypted); - System.out.println("Decrypted: " + decrypted); - } -} diff --git a/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java.txt b/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java.txt deleted file mode 100644 index 356bc3ef59a7..000000000000 --- a/src/main/java/com/thealgorithms/ciphers/OneTimePadCipher.java.txt +++ /dev/null @@ -1,66 +0,0 @@ -package com.thealgorithms.ciphers; - -import java.security.SecureRandom; - -/** - * Implementation of the One-Time Pad Cipher. - * - *

The One-Time Pad Cipher is a symmetric encryption technique that XORs - * plaintext with a truly random key of equal length. It is considered - * theoretically unbreakable when the key is random, used only once, and kept - * secret. - * - *

Example: - * - *

- * Plaintext:  HELLO
- * Key:        XMCKL
- * Ciphertext: EQNVZ
- * 
- * - * @see Wikipedia: One-time pad - */ -public final class OneTimePadCipher { - - private static final SecureRandom RANDOM = new SecureRandom(); - - private OneTimePadCipher() { - // Utility class; prevent instantiation. - } - - /** - * Encrypts or decrypts a message using the One-Time Pad method. - * - * @param input the input string (plaintext or ciphertext) - * @param key the key (must be the same length as input) - * @return the resulting encrypted/decrypted string - * @throws IllegalArgumentException if input and key lengths do not match - */ - public static String xorCipher(String input, String key) { - if (input.length() != key.length()) { - throw new IllegalArgumentException("Input and key lengths must match!"); - } - - StringBuilder output = new StringBuilder(); - for (int i = 0; i < input.length(); i++) { - char encryptedChar = (char) (input.charAt(i) ^ key.charAt(i)); - output.append(encryptedChar); - } - return output.toString(); - } - - /** - * Generates a random key of the same length as the message. - * - * @param length the desired key length - * @return a random key string - */ - public static String generateRandomKey(int length) { - StringBuilder key = new StringBuilder(); - for (int i = 0; i < length; i++) { - // Generate printable ASCII range (32–126) - key.append((char) (RANDOM.nextInt(95) + 32)); - } - return key.toString(); - } -} diff --git a/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java b/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java index 0a4a7c15aaa5..dd670ffe6889 100644 --- a/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java +++ b/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java @@ -1,3 +1,9 @@ +/* + * TheAlgorithms (https://github.com/TheAlgorithms/Java) + * Author: Shewale41 + * This file is licensed under the MIT License. + */ + package com.thealgorithms.datastructures.trees; import java.util.ArrayList; diff --git a/src/test/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTreeTest.java b/src/test/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTreeTest.java index 8d0c251149fc..c5973168438e 100644 --- a/src/test/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTreeTest.java +++ b/src/test/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTreeTest.java @@ -1,3 +1,9 @@ +/* + * TheAlgorithms (https://github.com/TheAlgorithms/Java) + * Author: Shewale41 + * This file is licensed under the MIT License. + */ + package com.thealgorithms.datastructures.trees; import static org.junit.jupiter.api.Assertions.assertEquals; From fd840ddc90f2c175495061a2f3e80253258d8caf Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 13:27:18 +0530 Subject: [PATCH 5/8] fix: remove redundant null check for SpotBugs compliance --- .../thealgorithms/datastructures/trees/ThreadedBinaryTree.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java b/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java index dd670ffe6889..fd8876cecb70 100644 --- a/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java +++ b/src/main/java/com/thealgorithms/datastructures/trees/ThreadedBinaryTree.java @@ -59,7 +59,8 @@ public void insert(int value) { Node current = root; Node parent = null; - while (current != null) { + + while (true) { parent = current; if (value < current.value) { if (!current.leftIsThread && current.left != null) { From fa26245cf4313ba49f57606868ad905b9b3b8a94 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 21:04:46 +0530 Subject: [PATCH 6/8] Add Count Total Set Bits from 1 to N (Bit Manipulation) --- .../bitmanipulation/CountTotalSetBits.java | 49 +++++++++++++++++++ .../CountTotalSetBitsTest.java | 31 ++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/main/java/com/thealgorithms/bitmanipulation/CountTotalSetBits.java create mode 100644 src/test/java/com/thealgorithms/bitmanipulation/CountTotalSetBitsTest.java diff --git a/src/main/java/com/thealgorithms/bitmanipulation/CountTotalSetBits.java b/src/main/java/com/thealgorithms/bitmanipulation/CountTotalSetBits.java new file mode 100644 index 000000000000..512e93d510d4 --- /dev/null +++ b/src/main/java/com/thealgorithms/bitmanipulation/CountTotalSetBits.java @@ -0,0 +1,49 @@ +package com.thealgorithms.bitmanipulation; + +/** + * Count the total number of set bits in binary representations of all numbers from 1 to N. + * + *

This implementation uses bit manipulation and mathematical observation to + * efficiently calculate the total number of set bits in O(log N) time. + * + *

Example: + * N = 3 -> Binary(1):01, Binary(2):10, Binary(3):11 => Total Set Bits = 4 + * + *

Reference: https://www.geeksforgeeks.org/count-total-set-bits-in-all-numbers-from-1-to-n/ + */ +public final class CountTotalSetBits { + + private CountTotalSetBits() { + // utility class + } + + /** + * Returns the total count of set bits in binary representations of all numbers from 1 to n. + * + * @param n the upper limit of the range + * @return total number of set bits from 1 to n + */ + public static int countTotalSetBits(int n) { + if (n == 0) { + return 0; + } + + int x = largestPowerOf2(n); + int bitsTill2x = x * (1 << (x - 1)); + int msbBits = n - (1 << x) + 1; + int rest = n - (1 << x); + + return bitsTill2x + msbBits + countTotalSetBits(rest); + } + + /** + * Helper function to find the largest power of 2 less than or equal to n. + */ + private static int largestPowerOf2(int n) { + int x = 0; + while ((1 << x) <= n) { + x++; + } + return x - 1; + } +} diff --git a/src/test/java/com/thealgorithms/bitmanipulation/CountTotalSetBitsTest.java b/src/test/java/com/thealgorithms/bitmanipulation/CountTotalSetBitsTest.java new file mode 100644 index 000000000000..a5718a76cbf0 --- /dev/null +++ b/src/test/java/com/thealgorithms/bitmanipulation/CountTotalSetBitsTest.java @@ -0,0 +1,31 @@ +package com.thealgorithms.bitmanipulation; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; + +/** + * Test cases for {@link CountTotalSetBits}. + */ +public class CountTotalSetBitsTest { + + @Test + void testSmallNumbers() { + assertEquals(4, CountTotalSetBits.countTotalSetBits(3)); // 1->1,2->1,3->2 + assertEquals(5, CountTotalSetBits.countTotalSetBits(4)); // 1,2,3,4 -> total 5 + } + + @Test + void testPowerOfTwo() { + assertEquals(12, CountTotalSetBits.countTotalSetBits(7)); // from 1 to 7 + } + + @Test + void testLargerNumber() { + assertEquals(17, CountTotalSetBits.countTotalSetBits(10)); // verified manually + } + + @Test + void testZero() { + assertEquals(0, CountTotalSetBits.countTotalSetBits(0)); + } +} From 40561cf04cd0723d6542fbc9273b1c6c6d110093 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 21:15:12 +0530 Subject: [PATCH 7/8] Fix formatting for CountTotalSetBits to match clang-format --- 2 | 0 .../bitmanipulation/CountTotalSetBitsTest.java | 7 ++++--- total | 0 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 2 create mode 100644 total diff --git a/2 b/2 new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/test/java/com/thealgorithms/bitmanipulation/CountTotalSetBitsTest.java b/src/test/java/com/thealgorithms/bitmanipulation/CountTotalSetBitsTest.java index a5718a76cbf0..33bc0ec4eaf8 100644 --- a/src/test/java/com/thealgorithms/bitmanipulation/CountTotalSetBitsTest.java +++ b/src/test/java/com/thealgorithms/bitmanipulation/CountTotalSetBitsTest.java @@ -1,6 +1,7 @@ package com.thealgorithms.bitmanipulation; import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; /** @@ -10,13 +11,13 @@ public class CountTotalSetBitsTest { @Test void testSmallNumbers() { - assertEquals(4, CountTotalSetBits.countTotalSetBits(3)); // 1->1,2->1,3->2 - assertEquals(5, CountTotalSetBits.countTotalSetBits(4)); // 1,2,3,4 -> total 5 + assertEquals(4, CountTotalSetBits.countTotalSetBits(3)); // 1->1,2->1,3->2 + assertEquals(5, CountTotalSetBits.countTotalSetBits(4)); // 1,2,3,4 -> total 5 } @Test void testPowerOfTwo() { - assertEquals(12, CountTotalSetBits.countTotalSetBits(7)); // from 1 to 7 + assertEquals(12, CountTotalSetBits.countTotalSetBits(7)); // from 1 to 7 } @Test diff --git a/total b/total new file mode 100644 index 000000000000..e69de29bb2d1 From f58388c5c6041b9445a14fa84c364452446b3478 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 21:39:38 +0530 Subject: [PATCH 8/8] Add Power of Four Check (Bit Manipulation) --- .../bitmanipulation/PowerOfFour.java | 39 +++++++++++++++++++ .../bitmanipulation/PowerOfFourTest.java | 36 +++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/main/java/com/thealgorithms/bitmanipulation/PowerOfFour.java create mode 100644 src/test/java/com/thealgorithms/bitmanipulation/PowerOfFourTest.java diff --git a/src/main/java/com/thealgorithms/bitmanipulation/PowerOfFour.java b/src/main/java/com/thealgorithms/bitmanipulation/PowerOfFour.java new file mode 100644 index 000000000000..2601f5bb8826 --- /dev/null +++ b/src/main/java/com/thealgorithms/bitmanipulation/PowerOfFour.java @@ -0,0 +1,39 @@ +/* + * TheAlgorithms (https://github.com/TheAlgorithms/Java) + * Author: Shewale41 + * This file is licensed under the MIT License. + */ + +package com.thealgorithms.bitmanipulation; + +/** + * Check if a given integer is a power of four using bit manipulation. + * + *

A number is a power of four if: + *

    + *
  • It is positive.
  • + *
  • It has only one set bit in its binary representation.
  • + *
  • The only set bit is in an even position (checked with 0xAAAAAAAA mask).
  • + *
+ * + *

Example: + * 4 -> true (2^2) + * 16 -> true (4^2) + * 8 -> false (not power of 4) + */ +public final class PowerOfFour { + + private PowerOfFour() { + // Utility class + } + + /** + * Checks whether a given integer is a power of four. + * + * @param n number to check + * @return true if n is a power of four, false otherwise + */ + public static boolean isPowerOfFour(int n) { + return n > 0 && (n & (n - 1)) == 0 && (n & 0xAAAAAAAA) == 0; + } +} diff --git a/src/test/java/com/thealgorithms/bitmanipulation/PowerOfFourTest.java b/src/test/java/com/thealgorithms/bitmanipulation/PowerOfFourTest.java new file mode 100644 index 000000000000..91c758be3136 --- /dev/null +++ b/src/test/java/com/thealgorithms/bitmanipulation/PowerOfFourTest.java @@ -0,0 +1,36 @@ +/* + * TheAlgorithms (https://github.com/TheAlgorithms/Java) + * Author: Shewale41 + * This file is licensed under the MIT License. + */ + +package com.thealgorithms.bitmanipulation; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link PowerOfFour}. + */ +public class PowerOfFourTest { + + @Test + void testPowerOfFourTrueCases() { + assertTrue(PowerOfFour.isPowerOfFour(1)); + assertTrue(PowerOfFour.isPowerOfFour(4)); + assertTrue(PowerOfFour.isPowerOfFour(16)); + assertTrue(PowerOfFour.isPowerOfFour(64)); + assertTrue(PowerOfFour.isPowerOfFour(256)); + } + + @Test + void testPowerOfFourFalseCases() { + assertFalse(PowerOfFour.isPowerOfFour(0)); + assertFalse(PowerOfFour.isPowerOfFour(2)); + assertFalse(PowerOfFour.isPowerOfFour(8)); + assertFalse(PowerOfFour.isPowerOfFour(12)); + assertFalse(PowerOfFour.isPowerOfFour(-4)); + } +}