mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-06 00:54:32 +08:00
Add Rail Fence Cipher (#5761)
This commit is contained in:
147
src/main/java/com/thealgorithms/ciphers/RailFenceCipher.java
Normal file
147
src/main/java/com/thealgorithms/ciphers/RailFenceCipher.java
Normal file
@ -0,0 +1,147 @@
|
||||
package com.thealgorithms.ciphers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* The rail fence cipher (also called a zigzag cipher) is a classical type of transposition cipher.
|
||||
* It derives its name from the manner in which encryption is performed, in analogy to a fence built with horizontal rails.
|
||||
* https://en.wikipedia.org/wiki/Rail_fence_cipher
|
||||
* @author https://github.com/Krounosity
|
||||
*/
|
||||
|
||||
public class RailFenceCipher {
|
||||
|
||||
// Encrypts the input string using the rail fence cipher method with the given number of rails.
|
||||
public String encrypt(String str, int rails) {
|
||||
|
||||
// Base case of single rail or rails are more than the number of characters in the string
|
||||
if (rails == 1 || rails >= str.length()) {
|
||||
return str;
|
||||
}
|
||||
|
||||
// Boolean flag to determine if the movement is downward or upward in the rail matrix.
|
||||
boolean down = true;
|
||||
// Create a 2D array to represent the rails (rows) and the length of the string (columns).
|
||||
char[][] strRail = new char[rails][str.length()];
|
||||
|
||||
// Initialize all positions in the rail matrix with a placeholder character ('\n').
|
||||
for (int i = 0; i < rails; i++) {
|
||||
Arrays.fill(strRail[i], '\n');
|
||||
}
|
||||
|
||||
int row = 0; // Start at the first row
|
||||
int col = 0; // Start at the first column
|
||||
|
||||
int i = 0;
|
||||
|
||||
// Fill the rail matrix with characters from the string based on the rail pattern.
|
||||
while (col < str.length()) {
|
||||
// Change direction to down when at the first row.
|
||||
if (row == 0) {
|
||||
down = true;
|
||||
}
|
||||
// Change direction to up when at the last row.
|
||||
else if (row == rails - 1) {
|
||||
down = false;
|
||||
}
|
||||
|
||||
// Place the character in the current position of the rail matrix.
|
||||
strRail[row][col] = str.charAt(i);
|
||||
col++; // Move to the next column.
|
||||
// Move to the next row based on the direction.
|
||||
if (down) {
|
||||
row++;
|
||||
} else {
|
||||
row--;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Construct the encrypted string by reading characters row by row.
|
||||
StringBuilder encryptedString = new StringBuilder();
|
||||
for (char[] chRow : strRail) {
|
||||
for (char ch : chRow) {
|
||||
if (ch != '\n') {
|
||||
encryptedString.append(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
return encryptedString.toString();
|
||||
}
|
||||
// Decrypts the input string using the rail fence cipher method with the given number of rails.
|
||||
public String decrypt(String str, int rails) {
|
||||
|
||||
// Base case of single rail or rails are more than the number of characters in the string
|
||||
if (rails == 1 || rails >= str.length()) {
|
||||
return str;
|
||||
}
|
||||
// Boolean flag to determine if the movement is downward or upward in the rail matrix.
|
||||
boolean down = true;
|
||||
|
||||
// Create a 2D array to represent the rails (rows) and the length of the string (columns).
|
||||
char[][] strRail = new char[rails][str.length()];
|
||||
|
||||
int row = 0; // Start at the first row
|
||||
int col = 0; // Start at the first column
|
||||
|
||||
// Mark the pattern on the rail matrix using '*'.
|
||||
while (col < str.length()) {
|
||||
// Change direction to down when at the first row.
|
||||
if (row == 0) {
|
||||
down = true;
|
||||
}
|
||||
// Change direction to up when at the last row.
|
||||
else if (row == rails - 1) {
|
||||
down = false;
|
||||
}
|
||||
|
||||
// Mark the current position in the rail matrix.
|
||||
strRail[row][col] = '*';
|
||||
col++; // Move to the next column.
|
||||
// Move to the next row based on the direction.
|
||||
if (down) {
|
||||
row++;
|
||||
} else {
|
||||
row--;
|
||||
}
|
||||
}
|
||||
|
||||
int index = 0; // Index to track characters from the input string.
|
||||
// Fill the rail matrix with characters from the input string based on the marked pattern.
|
||||
for (int i = 0; i < rails; i++) {
|
||||
for (int j = 0; j < str.length(); j++) {
|
||||
if (strRail[i][j] == '*') {
|
||||
strRail[i][j] = str.charAt(index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the decrypted string by following the zigzag pattern.
|
||||
StringBuilder decryptedString = new StringBuilder();
|
||||
row = 0; // Reset to the first row
|
||||
col = 0; // Reset to the first column
|
||||
|
||||
while (col < str.length()) {
|
||||
// Change direction to down when at the first row.
|
||||
if (row == 0) {
|
||||
down = true;
|
||||
}
|
||||
// Change direction to up when at the last row.
|
||||
else if (row == rails - 1) {
|
||||
down = false;
|
||||
}
|
||||
// Append the character from the rail matrix to the decrypted string.
|
||||
decryptedString.append(strRail[row][col]);
|
||||
col++; // Move to the next column.
|
||||
// Move to the next row based on the direction.
|
||||
if (down) {
|
||||
row++;
|
||||
} else {
|
||||
row--;
|
||||
}
|
||||
}
|
||||
|
||||
return decryptedString.toString();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user