Skip to content

Refactor AtbashCipher, add ParameterizedTest #5808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 61 additions & 31 deletions src/main/java/com/thealgorithms/ciphers/AtbashCipher.java
Original file line number Diff line number Diff line change
@@ -1,68 +1,98 @@
package com.thealgorithms.ciphers;

/**
* The Atbash cipher is a simple substitution cipher that replaces each letter
* in the alphabet with its reverse.
* For example, 'A' becomes 'Z', 'B' becomes 'Y', and so on. It works
* identically for both uppercase and lowercase letters.
* It's a symmetric cipher, meaning applying it twice returns the original text.
* Hence, the encrypting and the decrypting functions are identical
* @author https://github.com/Krounosity
* Learn more: https://en.wikipedia.org/wiki/Atbash
* The Atbash cipher is a classic substitution cipher that substitutes each letter
* with its opposite letter in the alphabet.
*
* For example:
* - 'A' becomes 'Z', 'B' becomes 'Y', 'C' becomes 'X', and so on.
* - Similarly, 'a' becomes 'z', 'b' becomes 'y', and so on.
*
* 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 {

private String toConvert;

// Default constructor.
AtbashCipher() {
public AtbashCipher() {
}

// String setting constructor.
AtbashCipher(String str) {
toConvert = str;
/**
* Constructor with a string parameter.
*
* @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() {
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) {
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) {
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) {
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() {

// Using StringBuilder to store new string.
StringBuilder convertedString = new StringBuilder();

// Iterating for each character.
for (char ch : toConvert.toCharArray()) {

// If the character is smallcased.
if (isSmall(ch)) {
convertedString.append((char) ('z' - (ch - 'a')));
}
// If the character is capital cased.
else if (isCapital(ch)) {
} else if (isCapital(ch)) {
convertedString.append((char) ('Z' - (ch - 'A')));
}
// Non-alphabetical character.
else {
} else {
convertedString.append(ch);
}
}
Expand Down
43 changes: 29 additions & 14 deletions src/test/java/com/thealgorithms/ciphers/AtbashTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,42 @@

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 {

@Test
public void atbashEncrypt() {
AtbashCipher normalToEncrypt = new AtbashCipher("Hello World! 123, @cipher abcDEF ZYX 987 madam zzZ Palindrome!");
String expectedText = "Svool Dliow! 123, @xrksvi zyxWVU ABC 987 nzwzn aaA Kzormwilnv!";
@ParameterizedTest
@MethodSource("cipherTestProvider")
public void testAtbashCipher(String input, String expected) {
AtbashCipher cipher = new AtbashCipher(input);
assertEquals(expected, cipher.convert());
}

normalToEncrypt.setString(normalToEncrypt.convert());
private static Stream<Arguments> cipherTestProvider() {
return Stream.of(
// Basic tests with lowercase and uppercase
Arguments.of("Hello", "Svool"), Arguments.of("WORLD", "DLIOW"),

assertEquals(expectedText, normalToEncrypt.getString());
}
// Mixed case with spaces and punctuation
Arguments.of("Hello World!", "Svool Dliow!"), Arguments.of("123 ABC xyz", "123 ZYX cba"),

// 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"),

@Test
public void atbashDecrypt() {
AtbashCipher encryptToNormal = new AtbashCipher("Svool Dliow! 123, @xrksvi zyxWVU ABC 987 nzwzn aaA Kzormwilnv!");
String expectedText = "Hello World! 123, @cipher abcDEF ZYX 987 madam zzZ Palindrome!";
// Empty string and single characters
Arguments.of("", ""), Arguments.of("A", "Z"), Arguments.of("z", "a"),

encryptToNormal.setString(encryptToNormal.convert());
// Numbers and symbols
Arguments.of("!@#123", "!@#123"),

assertEquals(expectedText, encryptToNormal.getString());
// 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!"));
}
}