Skip to content

Commit 80e9c2e

Browse files
authored
Merge branch 'master' into xorcipher_improve
2 parents 782140c + 03777f8 commit 80e9c2e

File tree

19 files changed

+877
-71
lines changed

19 files changed

+877
-71
lines changed

DIRECTORY.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
* [IsPowerTwo](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/IsPowerTwo.java)
4242
* [LowestSetBit](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/LowestSetBit.java)
4343
* [ModuloPowerOfTwo](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/ModuloPowerOfTwo.java)
44+
* [NextHigherSameBitCount](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NextHigherSameBitCount.java)
4445
* [NonRepeatingNumberFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinder.java)
4546
* [NumberAppearingOddTimes](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NumberAppearingOddTimes.java)
4647
* [NumbersDifferentSigns](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NumbersDifferentSigns.java)
@@ -179,6 +180,7 @@
179180
* [LeftistHeap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java)
180181
* [MaxHeap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MaxHeap.java)
181182
* [MedianFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MedianFinder.java)
183+
* [MergeKSortedArrays](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MergeKSortedArrays.java)
182184
* [MinHeap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MinHeap.java)
183185
* [MinPriorityQueue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MinPriorityQueue.java)
184186
* lists
@@ -207,6 +209,7 @@
207209
* [PriorityQueues](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/PriorityQueues.java)
208210
* [Queue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/Queue.java)
209211
* [QueueByTwoStacks](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/QueueByTwoStacks.java)
212+
* [SlidingWindowMaximum](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/SlidingWindowMaximum.java)
210213
* [TokenBucket](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/TokenBucket.java)
211214
* stacks
212215
* [NodeStack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/stacks/NodeStack.java)
@@ -272,6 +275,7 @@
272275
* [TilingProblem](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/divideandconquer/TilingProblem.java)
273276
* dynamicprogramming
274277
* [Abbreviation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/Abbreviation.java)
278+
* [AllConstruct](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/AllConstruct.java)
275279
* [AssignmentUsingBitmask](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/AssignmentUsingBitmask.java)
276280
* [BoardPath](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/BoardPath.java)
277281
* [BoundaryFill](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/BoundaryFill.java)
@@ -327,6 +331,7 @@
327331
* [StronglyConnectedComponentOptimized](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/graph/StronglyConnectedComponentOptimized.java)
328332
* greedyalgorithms
329333
* [ActivitySelection](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/ActivitySelection.java)
334+
* [BandwidthAllocation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/BandwidthAllocation.java)
330335
* [BinaryAddition](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/BinaryAddition.java)
331336
* [CoinChange](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/CoinChange.java)
332337
* [DigitSeparation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/DigitSeparation.java)
@@ -741,6 +746,7 @@
741746
* [IsPowerTwoTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/IsPowerTwoTest.java)
742747
* [LowestSetBitTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/LowestSetBitTest.java)
743748
* [ModuloPowerOfTwoTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/ModuloPowerOfTwoTest.java)
749+
* [NextHigherSameBitCountTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NextHigherSameBitCountTest.java)
744750
* [NonRepeatingNumberFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinderTest.java)
745751
* [NumberAppearingOddTimesTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NumberAppearingOddTimesTest.java)
746752
* [NumbersDifferentSignsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NumbersDifferentSignsTest.java)
@@ -858,6 +864,7 @@
858864
* [KthElementFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/KthElementFinderTest.java)
859865
* [LeftistHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java)
860866
* [MedianFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java)
867+
* [MergeKSortedArraysTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MergeKSortedArraysTest.java)
861868
* [MinPriorityQueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MinPriorityQueueTest.java)
862869
* lists
863870
* [CircleLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java)
@@ -881,6 +888,7 @@
881888
* [PriorityQueuesTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/PriorityQueuesTest.java)
882889
* [QueueByTwoStacksTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/QueueByTwoStacksTest.java)
883890
* [QueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/QueueTest.java)
891+
* [SlidingWindowMaximumTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/SlidingWindowMaximumTest.java)
884892
* [TokenBucketTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/TokenBucketTest.java)
885893
* stacks
886894
* [NodeStackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/stacks/NodeStackTest.java)
@@ -923,6 +931,7 @@
923931
* [TilingProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/divideandconquer/TilingProblemTest.java)
924932
* dynamicprogramming
925933
* [AbbreviationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/AbbreviationTest.java)
934+
* [AllConstructTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/AllConstructTest.java)
926935
* [AssignmentUsingBitmaskTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/AssignmentUsingBitmaskTest.java)
927936
* [BoardPathTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/BoardPathTest.java)
928937
* [BoundaryFillTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/BoundaryFillTest.java)
@@ -976,6 +985,7 @@
976985
* [StronglyConnectedComponentOptimizedTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/graph/StronglyConnectedComponentOptimizedTest.java)
977986
* greedyalgorithms
978987
* [ActivitySelectionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionTest.java)
988+
* [BandwidthAllocationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/BandwidthAllocationTest.java)
979989
* [BinaryAdditionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/BinaryAdditionTest.java)
980990
* [CoinChangeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/CoinChangeTest.java)
981991
* [DigitSeparationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/DigitSeparationTest.java)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.thealgorithms.bitmanipulation;
2+
3+
/**
4+
* This class provides a method to find the next higher number
5+
* with the same number of set bits as the given number.
6+
*
7+
* @author Hardvan
8+
*/
9+
public final class NextHigherSameBitCount {
10+
private NextHigherSameBitCount() {
11+
}
12+
13+
/**
14+
* Finds the next higher integer with the same number of set bits.
15+
* Steps:
16+
* 1. Find {@code c}, the rightmost set bit of {@code n}.
17+
* 2. Find {@code r}, the rightmost set bit of {@code n + c}.
18+
* 3. Swap the bits of {@code r} and {@code n} to the right of {@code c}.
19+
* 4. Shift the bits of {@code r} and {@code n} to the right of {@code c} to the rightmost.
20+
* 5. Combine the results of steps 3 and 4.
21+
*
22+
* @param n the input number
23+
* @return the next higher integer with the same set bit count
24+
*/
25+
public static int nextHigherSameBitCount(int n) {
26+
int c = n & -n;
27+
int r = n + c;
28+
return (((r ^ n) >> 2) / c) | r;
29+
}
30+
}

src/main/java/com/thealgorithms/ciphers/ADFGVXCipher.java

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,38 @@
33
import java.util.Arrays;
44
import java.util.HashMap;
55
import java.util.Map;
6+
67
/**
7-
* The ADFGVX cipher is a historically significant cipher used by
8-
* the German Army during World War I. It is a fractionating transposition
9-
* cipher that combines a Polybius square substitution with a columnar
10-
* transposition. It's named after the six letters (A, D, F, G, V, X)
11-
* that it uses in its substitution process.
12-
* https://en.wikipedia.org/wiki/ADFGVX_cipher
8+
* The ADFGVX cipher is a fractionating transposition cipher that was used by
9+
* the German Army during World War I. It combines a **Polybius square substitution**
10+
* with a **columnar transposition** to enhance encryption strength.
11+
* <p>
12+
* The name "ADFGVX" refers to the six letters (A, D, F, G, V, X) used as row and
13+
* column labels in the Polybius square. This cipher was designed to secure
14+
* communication and create complex, hard-to-break ciphertexts.
15+
* <p>
16+
* Learn more: <a href="https://en.wikipedia.org/wiki/ADFGVX_cipher">ADFGVX Cipher - Wikipedia</a>.
17+
* <p>
18+
* Example usage:
19+
* <pre>
20+
* ADFGVXCipher cipher = new ADFGVXCipher();
21+
* String encrypted = cipher.encrypt("attack at 1200am", "PRIVACY");
22+
* String decrypted = cipher.decrypt(encrypted, "PRIVACY");
23+
* </pre>
1324
*
1425
* @author bennybebo
1526
*/
1627
public class ADFGVXCipher {
1728

29+
// Constants used in the Polybius square
1830
private static final char[] POLYBIUS_LETTERS = {'A', 'D', 'F', 'G', 'V', 'X'};
1931
private static final char[][] POLYBIUS_SQUARE = {{'N', 'A', '1', 'C', '3', 'H'}, {'8', 'T', 'B', '2', 'O', 'M'}, {'E', '5', 'W', 'R', 'P', 'D'}, {'4', 'F', '6', 'G', '7', 'I'}, {'9', 'J', '0', 'K', 'L', 'Q'}, {'S', 'U', 'V', 'X', 'Y', 'Z'}};
32+
33+
// Maps for fast substitution lookups
2034
private static final Map<String, Character> POLYBIUS_MAP = new HashMap<>();
2135
private static final Map<Character, String> REVERSE_POLYBIUS_MAP = new HashMap<>();
2236

37+
// Static block to initialize the lookup tables from the Polybius square
2338
static {
2439
for (int i = 0; i < POLYBIUS_SQUARE.length; i++) {
2540
for (int j = 0; j < POLYBIUS_SQUARE[i].length; j++) {
@@ -30,26 +45,41 @@ public class ADFGVXCipher {
3045
}
3146
}
3247

33-
// Encrypts the plaintext using the ADFGVX cipher
48+
/**
49+
* Encrypts a given plaintext using the ADFGVX cipher with the provided keyword.
50+
* Steps:
51+
* 1. Substitute each letter in the plaintext with a pair of ADFGVX letters.
52+
* 2. Perform a columnar transposition on the fractionated text using the keyword.
53+
*
54+
* @param plaintext The message to be encrypted (can contain letters and digits).
55+
* @param key The keyword for columnar transposition.
56+
* @return The encrypted message as ciphertext.
57+
*/
3458
public String encrypt(String plaintext, String key) {
35-
plaintext = plaintext.toUpperCase().replaceAll("[^A-Z0-9]", "");
59+
plaintext = plaintext.toUpperCase().replaceAll("[^A-Z0-9]", ""); // Sanitize input
3660
StringBuilder fractionatedText = new StringBuilder();
3761

38-
// Step 1: Polybius square substitution
3962
for (char c : plaintext.toCharArray()) {
4063
fractionatedText.append(REVERSE_POLYBIUS_MAP.get(c));
4164
}
4265

43-
// Step 2: Columnar transposition
4466
return columnarTransposition(fractionatedText.toString(), key);
4567
}
4668

47-
// Decrypts the ciphertext using the ADFGVX cipher
69+
/**
70+
* Decrypts a given ciphertext using the ADFGVX cipher with the provided keyword.
71+
* Steps:
72+
* 1. Reverse the columnar transposition performed during encryption.
73+
* 2. Substitute each pair of ADFGVX letters with the corresponding plaintext letter.
74+
* The resulting text is the decrypted message.
75+
*
76+
* @param ciphertext The encrypted message.
77+
* @param key The keyword used during encryption.
78+
* @return The decrypted plaintext message.
79+
*/
4880
public String decrypt(String ciphertext, String key) {
49-
// Step 1: Reverse the columnar transposition
5081
String fractionatedText = reverseColumnarTransposition(ciphertext, key);
5182

52-
// Step 2: Polybius square substitution
5383
StringBuilder plaintext = new StringBuilder();
5484
for (int i = 0; i < fractionatedText.length(); i += 2) {
5585
String pair = fractionatedText.substring(i, i + 2);
@@ -59,14 +89,21 @@ public String decrypt(String ciphertext, String key) {
5989
return plaintext.toString();
6090
}
6191

92+
/**
93+
* Helper method: Performs columnar transposition during encryption
94+
*
95+
* @param text The fractionated text to be transposed
96+
* @param key The keyword for columnar transposition
97+
* @return The transposed text
98+
*/
6299
private String columnarTransposition(String text, String key) {
63100
int numRows = (int) Math.ceil((double) text.length() / key.length());
64101
char[][] table = new char[numRows][key.length()];
65-
for (char[] row : table) {
66-
Arrays.fill(row, '_'); // Fill with underscores to handle empty cells
102+
for (char[] row : table) { // Fill empty cells with underscores
103+
Arrays.fill(row, '_');
67104
}
68105

69-
// Fill the table row by row
106+
// Populate the table row by row
70107
for (int i = 0; i < text.length(); i++) {
71108
table[i / key.length()][i % key.length()] = text.charAt(i);
72109
}
@@ -88,6 +125,13 @@ private String columnarTransposition(String text, String key) {
88125
return ciphertext.toString();
89126
}
90127

128+
/**
129+
* Helper method: Reverses the columnar transposition during decryption
130+
*
131+
* @param ciphertext The transposed text to be reversed
132+
* @param key The keyword used during encryption
133+
* @return The reversed text
134+
*/
91135
private String reverseColumnarTransposition(String ciphertext, String key) {
92136
int numRows = (int) Math.ceil((double) ciphertext.length() / key.length());
93137
char[][] table = new char[numRows][key.length()];
@@ -96,19 +140,19 @@ private String reverseColumnarTransposition(String ciphertext, String key) {
96140
Arrays.sort(sortedKey);
97141

98142
int index = 0;
99-
// Fill the table column by column according to the sorted key order
143+
// Populate the table column by column according to the sorted key
100144
for (char keyChar : sortedKey) {
101145
int column = key.indexOf(keyChar);
102146
for (int row = 0; row < numRows; row++) {
103147
if (index < ciphertext.length()) {
104148
table[row][column] = ciphertext.charAt(index++);
105149
} else {
106-
table[row][column] = '_'; // Fill empty cells with an underscore
150+
table[row][column] = '_';
107151
}
108152
}
109153
}
110154

111-
// Read the table row by row to get the fractionated text
155+
// Read the table row by row to reconstruct the fractionated text
112156
StringBuilder fractionatedText = new StringBuilder();
113157
for (char[] row : table) {
114158
for (char cell : row) {

0 commit comments

Comments
 (0)