11package com .thealgorithms .ciphers ;
22
3- import java .util .Arrays ;
4-
53/**
64 * The rail fence cipher (also called a zigzag cipher) is a classical type of transposition cipher.
75 * It derives its name from the manner in which encryption is performed, in analogy to a fence built with horizontal rails.
@@ -14,28 +12,27 @@ public class RailFenceCipher {
1412 // Encrypts the input string using the rail fence cipher method with the given number of rails.
1513 public String encrypt (String str , int rails ) {
1614
15+ checkInput (str , rails );
16+
1717 // Base case of single rail or rails are more than the number of characters in the string
1818 if (rails == 1 || rails >= str .length ()) {
1919 return str ;
2020 }
2121
22- // Boolean flag to determine if the movement is downward or upward in the rail matrix .
22+ // Boolean flag to determine if the movement is downward or upward in the rail pattern .
2323 boolean down = true ;
24- // Create a 2D array to represent the rails (rows) and the length of the string (columns).
25- char [][] strRail = new char [ rails ][ str . length ()];
26-
27- // Initialize all positions in the rail matrix with a placeholder character ('\n').
24+ // Collect the characters of every rail separately. Using one buffer per rail (instead of a
25+ // rails x length matrix with a placeholder character) keeps every character of the input,
26+ // including characters that would otherwise be indistinguishable from the placeholder.
27+ StringBuilder [] railBuffers = new StringBuilder [ rails ];
2828 for (int i = 0 ; i < rails ; i ++) {
29- Arrays . fill ( strRail [i ], '\n' );
29+ railBuffers [i ] = new StringBuilder ( );
3030 }
3131
32- int row = 0 ; // Start at the first row
33- int col = 0 ; // Start at the first column
32+ int row = 0 ; // Start at the first rail
3433
35- int i = 0 ;
36-
37- // Fill the rail matrix with characters from the string based on the rail pattern.
38- while (col < str .length ()) {
34+ // Distribute the characters of the string over the rails following the zigzag pattern.
35+ for (int i = 0 ; i < str .length (); i ++) {
3936 // Change direction to down when at the first row.
4037 if (row == 0 ) {
4138 down = true ;
@@ -45,33 +42,28 @@ else if (row == rails - 1) {
4542 down = false ;
4643 }
4744
48- // Place the character in the current position of the rail matrix.
49- strRail [row ][col ] = str .charAt (i );
50- col ++; // Move to the next column.
45+ // Append the character to the rail it belongs to.
46+ railBuffers [row ].append (str .charAt (i ));
5147 // Move to the next row based on the direction.
5248 if (down ) {
5349 row ++;
5450 } else {
5551 row --;
5652 }
57-
58- i ++;
5953 }
6054
61- // Construct the encrypted string by reading characters row by row.
62- StringBuilder encryptedString = new StringBuilder ();
63- for (char [] chRow : strRail ) {
64- for (char ch : chRow ) {
65- if (ch != '\n' ) {
66- encryptedString .append (ch );
67- }
68- }
55+ // Construct the encrypted string by reading the rails top to bottom.
56+ StringBuilder encryptedString = new StringBuilder (str .length ());
57+ for (StringBuilder railBuffer : railBuffers ) {
58+ encryptedString .append (railBuffer );
6959 }
7060 return encryptedString .toString ();
7161 }
7262 // Decrypts the input string using the rail fence cipher method with the given number of rails.
7363 public String decrypt (String str , int rails ) {
7464
65+ checkInput (str , rails );
66+
7567 // Base case of single rail or rails are more than the number of characters in the string
7668 if (rails == 1 || rails >= str .length ()) {
7769 return str ;
@@ -144,4 +136,14 @@ else if (row == rails - 1) {
144136
145137 return decryptedString .toString ();
146138 }
139+
140+ // Rejects inputs the zigzag pattern is not defined for.
141+ private static void checkInput (String str , int rails ) {
142+ if (str == null ) {
143+ throw new IllegalArgumentException ("Input string must not be null" );
144+ }
145+ if (rails <= 0 ) {
146+ throw new IllegalArgumentException ("Number of rails must be positive, but was " + rails );
147+ }
148+ }
147149}
0 commit comments