-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* added rail fence cipher implementation * updated readme * fixed typo --------- Co-authored-by: Rak Laptudirm <[email protected]>
- Loading branch information
1 parent
0d0b97a
commit c5173f3
Showing
3 changed files
with
179 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package railfence | ||
|
||
import ( | ||
"strings" | ||
) | ||
|
||
func Encrypt(text string, rails int) string { | ||
if rails == 1 { | ||
return text | ||
} | ||
|
||
// Create a matrix for the rail fence pattern | ||
matrix := make([][]rune, rails) | ||
for i := range matrix { | ||
matrix[i] = make([]rune, len(text)) | ||
} | ||
|
||
// Fill the matrix | ||
dirDown := false | ||
row, col := 0, 0 | ||
for _, char := range text { | ||
if row == 0 || row == rails-1 { | ||
dirDown = !dirDown | ||
} | ||
matrix[row][col] = char | ||
col++ | ||
if dirDown { | ||
row++ | ||
} else { | ||
row-- | ||
} | ||
} | ||
var result strings.Builder | ||
for _, line := range matrix { | ||
for _, char := range line { | ||
if char != 0 { | ||
result.WriteRune(char) | ||
} | ||
} | ||
} | ||
|
||
return result.String() | ||
} | ||
func Decrypt(cipherText string, rails int) string { | ||
if rails == 1 || rails >= len(cipherText) { | ||
return cipherText | ||
} | ||
|
||
// Placeholder for the decrypted message | ||
decrypted := make([]rune, len(cipherText)) | ||
|
||
// Calculate the zigzag pattern and place characters accordingly | ||
index := 0 | ||
for rail := 0; rail < rails; rail++ { | ||
position := rail | ||
down := true // Direction flag | ||
for position < len(cipherText) { | ||
decrypted[position] = rune(cipherText[index]) | ||
index++ | ||
|
||
// Determine the next position based on the current rail and direction | ||
if rail == 0 || rail == rails-1 { | ||
position += 2 * (rails - 1) | ||
} else if down { | ||
position += 2 * (rails - 1 - rail) | ||
down = false | ||
} else { | ||
position += 2 * rail | ||
down = true | ||
} | ||
} | ||
} | ||
|
||
return string(decrypted) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package railfence | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestEncrypt(t *testing.T) { | ||
var railFenceTestData = []struct { | ||
description string | ||
input string | ||
rails int | ||
expected string | ||
}{ | ||
{ | ||
"Encrypt with 2 rails", | ||
"hello", | ||
2, | ||
"hloel", | ||
}, | ||
{ | ||
"Encrypt with 3 rails", | ||
"hello world", | ||
3, | ||
"horel ollwd", | ||
}, | ||
{ | ||
"Encrypt with edge case: 1 rail", | ||
"hello", | ||
1, | ||
"hello", | ||
}, | ||
{ | ||
"Encrypt with more rails than letters", | ||
"hi", | ||
100, | ||
"hi", | ||
}, | ||
} | ||
|
||
for _, test := range railFenceTestData { | ||
t.Run(test.description, func(t *testing.T) { | ||
actual := Encrypt(test.input, test.rails) | ||
if actual != test.expected { | ||
t.Errorf("FAIL: %s - Encrypt(%s, %d) = %s, want %s", test.description, test.input, test.rails, actual, test.expected) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestDecrypt(t *testing.T) { | ||
var railFenceTestData = []struct { | ||
description string | ||
input string | ||
rails int | ||
expected string | ||
}{ | ||
{ | ||
"Decrypt with 2 rails", | ||
"hloel", | ||
2, | ||
"hello", | ||
}, | ||
{ | ||
"Decrypt with 3 rails", | ||
"ho l lewrdlo", | ||
3, | ||
"hld olle wor", | ||
}, | ||
{ | ||
"Decrypt with edge case: 1 rail", | ||
"hello", | ||
1, | ||
"hello", | ||
}, | ||
{ | ||
"Decrypt with more rails than letters", | ||
"hi", | ||
100, | ||
"hi", | ||
}, | ||
} | ||
|
||
for _, test := range railFenceTestData { | ||
t.Run(test.description, func(t *testing.T) { | ||
actual := Decrypt(test.input, test.rails) | ||
if actual != test.expected { | ||
t.Errorf("FAIL: %s - Decrypt(%s, %d) = %s, want %s", test.description, test.input, test.rails, actual, test.expected) | ||
} | ||
}) | ||
} | ||
} |