From a179b5b8f5b56ae4014b7e961e2ef58498048cf6 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Mon, 27 Oct 2025 13:46:33 +0530 Subject: [PATCH 01/13] 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 02/13] 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 03/13] 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 04/13] 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 05/13] 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 06/13] 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 07/13] 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 08/13] 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)); + } +} From 138cb616c221e1ac7ec8bf49459eee7d9d4621c9 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 21:58:52 +0530 Subject: [PATCH 09/13] Add ElGamal Encryption Algorithm (Cryptography) --- .../ciphers/ElGamalEncryption.java | 46 +++++++++++++++++++ .../ciphers/ElGamalEncryptionTest.java | 25 ++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java create mode 100644 src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java diff --git a/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java new file mode 100644 index 000000000000..ff6d5d275744 --- /dev/null +++ b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java @@ -0,0 +1,46 @@ +package com.thealgorithms.cryptography; + +import java.math.BigInteger; +import java.security.SecureRandom; + +/** + * Implementation of the ElGamal Encryption Algorithm. + * + *

This algorithm is based on the Diffie–Hellman key exchange and uses modular arithmetic + * for secure public-key encryption and decryption. + * + *

Reference: + * https://www.geeksforgeeks.org/elgamal-encryption-algorithm/ + */ +public class ElGamalEncryption { + + private static final SecureRandom random = new SecureRandom(); + + /** + * Encrypts and decrypts a given message using ElGamal encryption. + * + * @param message The message to encrypt. + * @param bitLength The bit length of the prime modulus. + */ + public static void runElGamal(String message, int bitLength) { + BigInteger p = BigInteger.probablePrime(bitLength, random); // large prime + BigInteger g = new BigInteger("2"); // primitive root + BigInteger x = new BigInteger(bitLength - 2, random); // private key + BigInteger y = g.modPow(x, p); // public key + + // Encryption + BigInteger k = new BigInteger(bitLength - 2, random); + BigInteger a = g.modPow(k, p); + BigInteger M = new BigInteger(message.getBytes()); + BigInteger b = (y.modPow(k, p).multiply(M)).mod(p); + + // Decryption + BigInteger aInverse = a.modPow(p.subtract(BigInteger.ONE).subtract(x), p); + BigInteger decrypted = (b.multiply(aInverse)).mod(p); + + System.out.println("Prime (p): " + p); + System.out.println("Public Key (y): " + y); + System.out.println("Ciphertext: (" + a + ", " + b + ")"); + System.out.println("Decrypted Message: " + new String(decrypted.toByteArray())); + } +} diff --git a/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java new file mode 100644 index 000000000000..d6337630c1a2 --- /dev/null +++ b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java @@ -0,0 +1,25 @@ +package com.thealgorithms.cryptography; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +/** + * Tests for {@link ElGamalEncryption}. + */ +public class ElGamalEncryptionTest { + + @Test + void testEncryptionDecryption() { + // This test ensures encryption-decryption consistency + String message = "Hello"; + ElGamalEncryption.runElGamal(message, 32); + assertTrue(true); // Basic run test - manual verification for output + } + + @Test + void testDifferentBitLengths() { + assertDoesNotThrow(() -> ElGamalEncryption.runElGamal("Test", 16)); + assertDoesNotThrow(() -> ElGamalEncryption.runElGamal("Secure", 64)); + } +} From b48f2f493662c5689dfa911018e96647ae8fa2a9 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 22:15:31 +0530 Subject: [PATCH 10/13] Fix: Checkstyle compliance for ElGamal Encryption Algorithm --- clang-format | 0 .../ciphers/ElGamalEncryption.java | 39 ++++++++++++------- .../ciphers/ElGamalEncryptionTest.java | 16 +++++--- 3 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 clang-format diff --git a/clang-format b/clang-format new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java index ff6d5d275744..42d53a519079 100644 --- a/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java +++ b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java @@ -1,4 +1,10 @@ -package com.thealgorithms.cryptography; +/* + * TheAlgorithms (https://github.com/TheAlgorithms/Java) + * Author: Shewale41 + * This file is licensed under the MIT License. + */ + +package com.thealgorithms.ciphers; import java.math.BigInteger; import java.security.SecureRandom; @@ -6,33 +12,38 @@ /** * Implementation of the ElGamal Encryption Algorithm. * - *

This algorithm is based on the Diffie–Hellman key exchange and uses modular arithmetic - * for secure public-key encryption and decryption. + *

This algorithm is based on the Diffie–Hellman key exchange and provides secure + * public-key encryption and decryption using modular arithmetic. * *

Reference: - * https://www.geeksforgeeks.org/elgamal-encryption-algorithm/ + * https://en.wikipedia.org/wiki/ElGamal_encryption */ -public class ElGamalEncryption { +public final class ElGamalEncryption { - private static final SecureRandom random = new SecureRandom(); + private static final SecureRandom RANDOM = new SecureRandom(); + + /** Private constructor to prevent instantiation of utility class. */ + private ElGamalEncryption() { + throw new UnsupportedOperationException("Utility class"); + } /** - * Encrypts and decrypts a given message using ElGamal encryption. + * Demonstrates ElGamal encryption and decryption for a given message. * - * @param message The message to encrypt. - * @param bitLength The bit length of the prime modulus. + * @param message the message to encrypt + * @param bitLength the bit length for the prime number used */ public static void runElGamal(String message, int bitLength) { - BigInteger p = BigInteger.probablePrime(bitLength, random); // large prime + BigInteger p = BigInteger.probablePrime(bitLength, RANDOM); // prime modulus BigInteger g = new BigInteger("2"); // primitive root - BigInteger x = new BigInteger(bitLength - 2, random); // private key + BigInteger x = new BigInteger(bitLength - 2, RANDOM); // private key BigInteger y = g.modPow(x, p); // public key // Encryption - BigInteger k = new BigInteger(bitLength - 2, random); + BigInteger k = new BigInteger(bitLength - 2, RANDOM); BigInteger a = g.modPow(k, p); - BigInteger M = new BigInteger(message.getBytes()); - BigInteger b = (y.modPow(k, p).multiply(M)).mod(p); + BigInteger m = new BigInteger(message.getBytes()); + BigInteger b = (y.modPow(k, p).multiply(m)).mod(p); // Decryption BigInteger aInverse = a.modPow(p.subtract(BigInteger.ONE).subtract(x), p); diff --git a/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java index d6337630c1a2..d50d53ae1df2 100644 --- a/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java +++ b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java @@ -1,6 +1,12 @@ -package com.thealgorithms.cryptography; +/* + * TheAlgorithms (https://github.com/TheAlgorithms/Java) + * Author: Shewale41 + * This file is licensed under the MIT License. + */ + +package com.thealgorithms.ciphers; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import org.junit.jupiter.api.Test; @@ -11,14 +17,12 @@ public class ElGamalEncryptionTest { @Test void testEncryptionDecryption() { - // This test ensures encryption-decryption consistency String message = "Hello"; - ElGamalEncryption.runElGamal(message, 32); - assertTrue(true); // Basic run test - manual verification for output + assertDoesNotThrow(() -> ElGamalEncryption.runElGamal(message, 32)); } @Test - void testDifferentBitLengths() { + void testWithDifferentBitLengths() { assertDoesNotThrow(() -> ElGamalEncryption.runElGamal("Test", 16)); assertDoesNotThrow(() -> ElGamalEncryption.runElGamal("Secure", 64)); } From fba505800cb4a416fec56150e82e7374b7512ca7 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 22:39:43 +0530 Subject: [PATCH 11/13] Add: ElGamal Encryption Algorithm with tests --- .../ciphers/ElGamalEncryption.java | 49 +++++++++---------- .../ciphers/ElGamalEncryptionTest.java | 31 +++++++----- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java index 42d53a519079..853fbd29ba40 100644 --- a/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java +++ b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java @@ -1,9 +1,3 @@ -/* - * TheAlgorithms (https://github.com/TheAlgorithms/Java) - * Author: Shewale41 - * This file is licensed under the MIT License. - */ - package com.thealgorithms.ciphers; import java.math.BigInteger; @@ -12,44 +6,49 @@ /** * Implementation of the ElGamal Encryption Algorithm. * - *

This algorithm is based on the Diffie–Hellman key exchange and provides secure - * public-key encryption and decryption using modular arithmetic. + *

ElGamal is an asymmetric key encryption algorithm based on + * the Diffie–Hellman key exchange. It uses randomization + * for security and is widely used in cryptographic systems.

* - *

Reference: - * https://en.wikipedia.org/wiki/ElGamal_encryption + *

Reference: Menezes, van Oorschot, and Vanstone, "Handbook of Applied Cryptography"

*/ public final class ElGamalEncryption { private static final SecureRandom RANDOM = new SecureRandom(); - /** Private constructor to prevent instantiation of utility class. */ + // Private constructor to prevent instantiation private ElGamalEncryption() { throw new UnsupportedOperationException("Utility class"); } /** - * Demonstrates ElGamal encryption and decryption for a given message. + * Runs the ElGamal encryption and decryption demonstration. * - * @param message the message to encrypt - * @param bitLength the bit length for the prime number used + * @param message the plaintext message to encrypt + * @param bitLength the bit length for prime generation */ - public static void runElGamal(String message, int bitLength) { - BigInteger p = BigInteger.probablePrime(bitLength, RANDOM); // prime modulus - BigInteger g = new BigInteger("2"); // primitive root - BigInteger x = new BigInteger(bitLength - 2, RANDOM); // private key - BigInteger y = g.modPow(x, p); // public key + @SuppressWarnings({"PMD.SystemPrintln", "PMD.DataflowAnomalyAnalysis"}) + public static void runElGamal(final String message, final int bitLength) { + // Key generation + final BigInteger p = BigInteger.probablePrime(bitLength, RANDOM); + final BigInteger g = new BigInteger("2"); + final BigInteger x = new BigInteger(bitLength - 2, RANDOM); + final BigInteger y = g.modPow(x, p); // Encryption - BigInteger k = new BigInteger(bitLength - 2, RANDOM); - BigInteger a = g.modPow(k, p); - BigInteger m = new BigInteger(message.getBytes()); - BigInteger b = (y.modPow(k, p).multiply(m)).mod(p); + final BigInteger k = new BigInteger(bitLength - 2, RANDOM); + final BigInteger a = g.modPow(k, p); + final BigInteger m = new BigInteger(message.getBytes()); + final BigInteger b = (y.modPow(k, p).multiply(m)).mod(p); // Decryption - BigInteger aInverse = a.modPow(p.subtract(BigInteger.ONE).subtract(x), p); - BigInteger decrypted = (b.multiply(aInverse)).mod(p); + final BigInteger aInverse = a.modPow(p.subtract(BigInteger.ONE).subtract(x), p); + final BigInteger decrypted = (b.multiply(aInverse)).mod(p); + // Display results System.out.println("Prime (p): " + p); + System.out.println("Generator (g): " + g); + System.out.println("Private Key (x): " + x); System.out.println("Public Key (y): " + y); System.out.println("Ciphertext: (" + a + ", " + b + ")"); System.out.println("Decrypted Message: " + new String(decrypted.toByteArray())); diff --git a/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java index d50d53ae1df2..00a225042ef8 100644 --- a/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java +++ b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java @@ -1,29 +1,34 @@ -/* - * TheAlgorithms (https://github.com/TheAlgorithms/Java) - * Author: Shewale41 - * This file is licensed under the MIT License. - */ - package com.thealgorithms.ciphers; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; /** - * Tests for {@link ElGamalEncryption}. + * Unit tests for {@link ElGamalEncryption}. */ public class ElGamalEncryptionTest { @Test void testEncryptionDecryption() { - String message = "Hello"; - assertDoesNotThrow(() -> ElGamalEncryption.runElGamal(message, 32)); + // Basic functional test (simulated output check) + // Since ElGamal uses randomization, we only verify successful execution + try { + ElGamalEncryption.runElGamal("Hello", 64); + } catch (Exception e) { + throw new AssertionError("ElGamalEncryption failed with exception: " + e.getMessage()); + } } @Test - void testWithDifferentBitLengths() { - assertDoesNotThrow(() -> ElGamalEncryption.runElGamal("Test", 16)); - assertDoesNotThrow(() -> ElGamalEncryption.runElGamal("Secure", 64)); + void testUtilityConstructor() { + // Ensures the utility class constructor is private + try { + var constructor = ElGamalEncryption.class.getDeclaredConstructor(); + constructor.setAccessible(true); + constructor.newInstance(); + } catch (Exception e) { + assertEquals("Utility class", e.getCause().getMessage()); + } } } From f646e48ad36b637736a16c398a49e9ba9d3a7298 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 22:55:30 +0530 Subject: [PATCH 12/13] Fix: SpotBugs violation and improve test for ElGamalEncryption --- .../ciphers/ElGamalEncryption.java | 7 +------ .../ciphers/ElGamalEncryptionTest.java | 20 +++++++------------ 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java index 853fbd29ba40..b35ff064f9c6 100644 --- a/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java +++ b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java @@ -16,7 +16,6 @@ public final class ElGamalEncryption { private static final SecureRandom RANDOM = new SecureRandom(); - // Private constructor to prevent instantiation private ElGamalEncryption() { throw new UnsupportedOperationException("Utility class"); } @@ -27,25 +26,21 @@ private ElGamalEncryption() { * @param message the plaintext message to encrypt * @param bitLength the bit length for prime generation */ - @SuppressWarnings({"PMD.SystemPrintln", "PMD.DataflowAnomalyAnalysis"}) + @SuppressWarnings({ "PMD.SystemPrintln", "PMD.DataflowAnomalyAnalysis" }) public static void runElGamal(final String message, final int bitLength) { - // Key generation final BigInteger p = BigInteger.probablePrime(bitLength, RANDOM); final BigInteger g = new BigInteger("2"); final BigInteger x = new BigInteger(bitLength - 2, RANDOM); final BigInteger y = g.modPow(x, p); - // Encryption final BigInteger k = new BigInteger(bitLength - 2, RANDOM); final BigInteger a = g.modPow(k, p); final BigInteger m = new BigInteger(message.getBytes()); final BigInteger b = (y.modPow(k, p).multiply(m)).mod(p); - // Decryption final BigInteger aInverse = a.modPow(p.subtract(BigInteger.ONE).subtract(x), p); final BigInteger decrypted = (b.multiply(aInverse)).mod(p); - // Display results System.out.println("Prime (p): " + p); System.out.println("Generator (g): " + g); System.out.println("Private Key (x): " + x); diff --git a/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java index 00a225042ef8..0387b177fb80 100644 --- a/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java +++ b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java @@ -1,8 +1,9 @@ package com.thealgorithms.ciphers; -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.Test; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Unit tests for {@link ElGamalEncryption}. @@ -11,8 +12,6 @@ public class ElGamalEncryptionTest { @Test void testEncryptionDecryption() { - // Basic functional test (simulated output check) - // Since ElGamal uses randomization, we only verify successful execution try { ElGamalEncryption.runElGamal("Hello", 64); } catch (Exception e) { @@ -21,14 +20,9 @@ void testEncryptionDecryption() { } @Test - void testUtilityConstructor() { - // Ensures the utility class constructor is private - try { - var constructor = ElGamalEncryption.class.getDeclaredConstructor(); - constructor.setAccessible(true); - constructor.newInstance(); - } catch (Exception e) { - assertEquals("Utility class", e.getCause().getMessage()); - } + void testUtilityConstructor() throws NoSuchMethodException { + Constructor constructor = ElGamalEncryption.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers()), + "Utility class constructor should be private"); } } From 33146c6a2f24fd9b9cb771fc19ba09de9f3c96b2 Mon Sep 17 00:00:00 2001 From: Shewale41 Date: Thu, 30 Oct 2025 23:00:13 +0530 Subject: [PATCH 13/13] final Fix: SpotBugs violation and improve test for ElGamalEncryption --- .../java/com/thealgorithms/ciphers/ElGamalEncryption.java | 2 +- .../com/thealgorithms/ciphers/ElGamalEncryptionTest.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java index b35ff064f9c6..13b07045e1f8 100644 --- a/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java +++ b/src/main/java/com/thealgorithms/ciphers/ElGamalEncryption.java @@ -26,7 +26,7 @@ private ElGamalEncryption() { * @param message the plaintext message to encrypt * @param bitLength the bit length for prime generation */ - @SuppressWarnings({ "PMD.SystemPrintln", "PMD.DataflowAnomalyAnalysis" }) + @SuppressWarnings({"PMD.SystemPrintln", "PMD.DataflowAnomalyAnalysis"}) public static void runElGamal(final String message, final int bitLength) { final BigInteger p = BigInteger.probablePrime(bitLength, RANDOM); final BigInteger g = new BigInteger("2"); diff --git a/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java index 0387b177fb80..ab979f600543 100644 --- a/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java +++ b/src/test/java/com/thealgorithms/ciphers/ElGamalEncryptionTest.java @@ -1,9 +1,10 @@ package com.thealgorithms.ciphers; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; -import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; /** * Unit tests for {@link ElGamalEncryption}. @@ -22,7 +23,6 @@ void testEncryptionDecryption() { @Test void testUtilityConstructor() throws NoSuchMethodException { Constructor constructor = ElGamalEncryption.class.getDeclaredConstructor(); - assertTrue(Modifier.isPrivate(constructor.getModifiers()), - "Utility class constructor should be private"); + assertTrue(Modifier.isPrivate(constructor.getModifiers()), "Utility class constructor should be private"); } }