Refactor AtbashCipher, add ParameterizedTest (#5808)

This commit is contained in:
Hardik Pawar
2024-10-26 21:03:33 +05:30
committed by GitHub
parent 20239f20f1
commit 08bd1ffe73
2 changed files with 91 additions and 46 deletions

View File

@ -1,68 +1,98 @@
package com.thealgorithms.ciphers; package com.thealgorithms.ciphers;
/** /**
* The Atbash cipher is a simple substitution cipher that replaces each letter * The Atbash cipher is a classic substitution cipher that substitutes each letter
* in the alphabet with its reverse. * with its opposite letter in the alphabet.
* For example, 'A' becomes 'Z', 'B' becomes 'Y', and so on. It works *
* identically for both uppercase and lowercase letters. * For example:
* It's a symmetric cipher, meaning applying it twice returns the original text. * - 'A' becomes 'Z', 'B' becomes 'Y', 'C' becomes 'X', and so on.
* Hence, the encrypting and the decrypting functions are identical * - Similarly, 'a' becomes 'z', 'b' becomes 'y', and so on.
* @author https://github.com/Krounosity *
* Learn more: https://en.wikipedia.org/wiki/Atbash * The cipher works identically for both uppercase and lowercase letters.
* Non-alphabetical characters remain unchanged in the output.
*
* This cipher is symmetric, meaning that applying the cipher twice will return
* the original text. Therefore, the same function is used for both encryption and decryption.
*
* <p>Usage Example:</p>
* <pre>
* AtbashCipher cipher = new AtbashCipher("Hello World!");
* String encrypted = cipher.convert(); // Output: "Svool Dliow!"
* </pre>
*
* @author <a href="https://github.com/Krounosity">Krounosity</a>
* @see <a href="https://en.wikipedia.org/wiki/Atbash">Atbash Cipher (Wikipedia)</a>
*/ */
public class AtbashCipher { public class AtbashCipher {
private String toConvert; private String toConvert;
// Default constructor. public AtbashCipher() {
AtbashCipher() {
} }
// String setting constructor. /**
AtbashCipher(String str) { * Constructor with a string parameter.
toConvert = str; *
* @param str The string to be converted using the Atbash cipher
*/
public AtbashCipher(String str) {
this.toConvert = str;
} }
// String getter method. /**
* Returns the current string set for conversion.
*
* @return The string to be converted
*/
public String getString() { public String getString() {
return toConvert; return toConvert;
} }
// String setter method. /**
* Sets the string to be converted using the Atbash cipher.
*
* @param str The new string to convert
*/
public void setString(String str) { public void setString(String str) {
toConvert = str; this.toConvert = str;
} }
// Checking whether the current character is capital. /**
* Checks if a character is uppercase.
*
* @param ch The character to check
* @return {@code true} if the character is uppercase, {@code false} otherwise
*/
private boolean isCapital(char ch) { private boolean isCapital(char ch) {
return ch >= 'A' && ch <= 'Z'; return ch >= 'A' && ch <= 'Z';
} }
// Checking whether the current character is smallcased. /**
* Checks if a character is lowercase.
*
* @param ch The character to check
* @return {@code true} if the character is lowercase, {@code false} otherwise
*/
private boolean isSmall(char ch) { private boolean isSmall(char ch) {
return ch >= 'a' && ch <= 'z'; return ch >= 'a' && ch <= 'z';
} }
// Converting text to atbash cipher code or vice versa. /**
* Converts the input string using the Atbash cipher.
* Alphabetic characters are substituted with their opposite in the alphabet,
* while non-alphabetic characters remain unchanged.
*
* @return The converted string after applying the Atbash cipher
*/
public String convert() { public String convert() {
// Using StringBuilder to store new string.
StringBuilder convertedString = new StringBuilder(); StringBuilder convertedString = new StringBuilder();
// Iterating for each character.
for (char ch : toConvert.toCharArray()) { for (char ch : toConvert.toCharArray()) {
// If the character is smallcased.
if (isSmall(ch)) { if (isSmall(ch)) {
convertedString.append((char) ('z' - (ch - 'a'))); convertedString.append((char) ('z' - (ch - 'a')));
} } else if (isCapital(ch)) {
// If the character is capital cased.
else if (isCapital(ch)) {
convertedString.append((char) ('Z' - (ch - 'A'))); convertedString.append((char) ('Z' - (ch - 'A')));
} } else {
// Non-alphabetical character.
else {
convertedString.append(ch); convertedString.append(ch);
} }
} }

View File

@ -2,27 +2,42 @@ package com.thealgorithms.ciphers;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test; import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class AtbashTest { public class AtbashTest {
@Test @ParameterizedTest
public void atbashEncrypt() { @MethodSource("cipherTestProvider")
AtbashCipher normalToEncrypt = new AtbashCipher("Hello World! 123, @cipher abcDEF ZYX 987 madam zzZ Palindrome!"); public void testAtbashCipher(String input, String expected) {
String expectedText = "Svool Dliow! 123, @xrksvi zyxWVU ABC 987 nzwzn aaA Kzormwilnv!"; AtbashCipher cipher = new AtbashCipher(input);
assertEquals(expected, cipher.convert());
normalToEncrypt.setString(normalToEncrypt.convert());
assertEquals(expectedText, normalToEncrypt.getString());
} }
@Test private static Stream<Arguments> cipherTestProvider() {
public void atbashDecrypt() { return Stream.of(
AtbashCipher encryptToNormal = new AtbashCipher("Svool Dliow! 123, @xrksvi zyxWVU ABC 987 nzwzn aaA Kzormwilnv!"); // Basic tests with lowercase and uppercase
String expectedText = "Hello World! 123, @cipher abcDEF ZYX 987 madam zzZ Palindrome!"; Arguments.of("Hello", "Svool"), Arguments.of("WORLD", "DLIOW"),
encryptToNormal.setString(encryptToNormal.convert()); // Mixed case with spaces and punctuation
Arguments.of("Hello World!", "Svool Dliow!"), Arguments.of("123 ABC xyz", "123 ZYX cba"),
assertEquals(expectedText, encryptToNormal.getString()); // Palindromes and mixed cases
Arguments.of("madam", "nzwzn"), Arguments.of("Palindrome", "Kzormwilnv"),
// Non-alphabetic characters should remain unchanged
Arguments.of("@cipher 123!", "@xrksvi 123!"), Arguments.of("no-change", "ml-xszmtv"),
// Empty string and single characters
Arguments.of("", ""), Arguments.of("A", "Z"), Arguments.of("z", "a"),
// Numbers and symbols
Arguments.of("!@#123", "!@#123"),
// Full sentence with uppercase, lowercase, symbols, and numbers
Arguments.of("Hello World! 123, @cipher abcDEF ZYX 987 madam zzZ Palindrome!", "Svool Dliow! 123, @xrksvi zyxWVU ABC 987 nzwzn aaA Kzormwilnv!"),
Arguments.of("Svool Dliow! 123, @xrksvi zyxWVU ABC 987 nzwzn aaA Kzormwilnv!", "Hello World! 123, @cipher abcDEF ZYX 987 madam zzZ Palindrome!"));
} }
} }