Skip to content

Commit 8b60485

Browse files
authored
Enhance docs, add more tests in Vigenere (TheAlgorithms#5899)
1 parent e6f7063 commit 8b60485

File tree

2 files changed

+118
-19
lines changed

2 files changed

+118
-19
lines changed

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

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,54 @@
11
package com.thealgorithms.ciphers;
22

33
/**
4-
* A Java implementation of Vigenere Cipher.
4+
* A Java implementation of the Vigenère Cipher.
5+
*
6+
* The Vigenère Cipher is a polyalphabetic substitution cipher that uses a
7+
* keyword to shift letters in the plaintext by different amounts, depending
8+
* on the corresponding character in the keyword. It wraps around the alphabet,
9+
* ensuring the shifts are within 'A'-'Z' or 'a'-'z'.
10+
*
11+
* Non-alphabetic characters (like spaces, punctuation) are kept unchanged.
12+
*
13+
* Encryption Example:
14+
* - Plaintext: "Hello World!"
15+
* - Key: "suchsecret"
16+
* - Encrypted Text: "Zynsg Yfvev!"
17+
*
18+
* Decryption Example:
19+
* - Ciphertext: "Zynsg Yfvev!"
20+
* - Key: "suchsecret"
21+
* - Decrypted Text: "Hello World!"
22+
*
23+
* Wikipedia Reference:
24+
* <a href="https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher">Vigenère Cipher - Wikipedia</a>
525
*
626
* @author straiffix
727
* @author beingmartinbmc
828
*/
929
public class Vigenere {
1030

31+
/**
32+
* Encrypts a given message using the Vigenère Cipher with the specified key.
33+
* Steps:
34+
* 1. Iterate over each character in the message.
35+
* 2. If the character is a letter, shift it by the corresponding character in the key.
36+
* 3. Preserve the case of the letter.
37+
* 4. Preserve non-alphabetic characters.
38+
* 5. Move to the next character in the key (cyclic).
39+
* 6. Return the encrypted message.
40+
*
41+
* @param message The plaintext message to encrypt.
42+
* @param key The keyword used for encryption.
43+
* @throws IllegalArgumentException if the key is empty.
44+
* @return The encrypted message.
45+
*/
1146
public String encrypt(final String message, final String key) {
12-
StringBuilder result = new StringBuilder();
47+
if (key.isEmpty()) {
48+
throw new IllegalArgumentException("Key cannot be empty.");
49+
}
1350

51+
StringBuilder result = new StringBuilder();
1452
int j = 0;
1553
for (int i = 0; i < message.length(); i++) {
1654
char c = message.charAt(i);
@@ -20,17 +58,35 @@ public String encrypt(final String message, final String key) {
2058
} else {
2159
result.append((char) ((c + key.toLowerCase().charAt(j) - 2 * 'a') % 26 + 'a'));
2260
}
61+
j = ++j % key.length();
2362
} else {
2463
result.append(c);
2564
}
26-
j = ++j % key.length();
2765
}
2866
return result.toString();
2967
}
3068

69+
/**
70+
* Decrypts a given message encrypted with the Vigenère Cipher using the specified key.
71+
* Steps:
72+
* 1. Iterate over each character in the message.
73+
* 2. If the character is a letter, shift it back by the corresponding character in the key.
74+
* 3. Preserve the case of the letter.
75+
* 4. Preserve non-alphabetic characters.
76+
* 5. Move to the next character in the key (cyclic).
77+
* 6. Return the decrypted message.
78+
*
79+
* @param message The encrypted message to decrypt.
80+
* @param key The keyword used for decryption.
81+
* @throws IllegalArgumentException if the key is empty.
82+
* @return The decrypted plaintext message.
83+
*/
3184
public String decrypt(final String message, final String key) {
32-
StringBuilder result = new StringBuilder();
85+
if (key.isEmpty()) {
86+
throw new IllegalArgumentException("Key cannot be empty.");
87+
}
3388

89+
StringBuilder result = new StringBuilder();
3490
int j = 0;
3591
for (int i = 0; i < message.length(); i++) {
3692
char c = message.charAt(i);
@@ -40,11 +96,10 @@ public String decrypt(final String message, final String key) {
4096
} else {
4197
result.append((char) ('z' - (25 - (c - key.toLowerCase().charAt(j))) % 26));
4298
}
99+
j = ++j % key.length();
43100
} else {
44101
result.append(c);
45102
}
46-
47-
j = ++j % key.length();
48103
}
49104
return result.toString();
50105
}
Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.thealgorithms.ciphers;
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertThrows;
45

56
import org.junit.jupiter.api.Test;
67

@@ -9,28 +10,71 @@ class VigenereTest {
910
Vigenere vigenere = new Vigenere();
1011

1112
@Test
12-
void vigenereEncryptTest() {
13-
// given
13+
void testVigenereEncryptDecrypt() {
1414
String text = "Hello World!";
1515
String key = "suchsecret";
1616

17-
// when
18-
String cipherText = vigenere.encrypt(text, key);
17+
String encryptedText = vigenere.encrypt(text, key);
18+
String decryptedText = vigenere.decrypt(encryptedText, key);
1919

20-
// then
21-
assertEquals("Zynsg Yfvev!", cipherText);
20+
assertEquals("Zynsg Aqipw!", encryptedText);
21+
assertEquals("Hello World!", decryptedText);
2222
}
2323

2424
@Test
25-
void vigenereDecryptTest() {
26-
// given
27-
String encryptedText = "Zynsg Yfvev!";
28-
String key = "suchsecret";
25+
void testWithEmptyMessage() {
26+
String text = "";
27+
String key = "anykey";
2928

30-
// when
29+
String encryptedText = vigenere.encrypt(text, key);
3130
String decryptedText = vigenere.decrypt(encryptedText, key);
3231

33-
// then
34-
assertEquals("Hello World!", decryptedText);
32+
assertEquals("", encryptedText);
33+
assertEquals("", decryptedText);
34+
}
35+
36+
@Test
37+
void testWithEmptyKey() {
38+
String text = "This should remain the same";
39+
String key = "";
40+
41+
assertThrows(IllegalArgumentException.class, () -> vigenere.encrypt(text, key));
42+
assertThrows(IllegalArgumentException.class, () -> vigenere.decrypt(text, key));
43+
}
44+
45+
@Test
46+
void testWithNumbersInMessage() {
47+
String text = "Vigenere123!";
48+
String key = "cipher";
49+
50+
String encryptedText = vigenere.encrypt(text, key);
51+
String decryptedText = vigenere.decrypt(encryptedText, key);
52+
53+
assertEquals("Xqvlrvtm123!", encryptedText);
54+
assertEquals(text, decryptedText);
55+
}
56+
57+
@Test
58+
void testLongerKeyThanMessage() {
59+
String text = "Short";
60+
String key = "VeryLongSecretKey";
61+
62+
String encryptedText = vigenere.encrypt(text, key);
63+
String decryptedText = vigenere.decrypt(encryptedText, key);
64+
65+
assertEquals("Nlfpe", encryptedText);
66+
assertEquals(text, decryptedText);
67+
}
68+
69+
@Test
70+
void testUppercaseMessageAndKey() {
71+
String text = "HELLO";
72+
String key = "SECRET";
73+
74+
String encryptedText = vigenere.encrypt(text, key);
75+
String decryptedText = vigenere.decrypt(encryptedText, key);
76+
77+
assertEquals("ZINCS", encryptedText);
78+
assertEquals(text, decryptedText);
3579
}
3680
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy