From 3cd6860527c1dcb399769ff890a5870b4300625f Mon Sep 17 00:00:00 2001
From: Jc Calayag <138150245+Jccqt@users.noreply.github.com>
Date: Fri, 11 Jul 2025 22:09:22 +0800
Subject: [PATCH 1/2] Add Autokey encoder
---
.../Encoders/AutokeyEncoderTests.cs | 26 +++++++
Algorithms/Encoders/AutokeyEncorder.cs | 68 +++++++++++++++++++
README.md | 1 +
3 files changed, 95 insertions(+)
create mode 100644 Algorithms.Tests/Encoders/AutokeyEncoderTests.cs
create mode 100644 Algorithms/Encoders/AutokeyEncorder.cs
diff --git a/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs b/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs
new file mode 100644
index 000000000..5ea399261
--- /dev/null
+++ b/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs
@@ -0,0 +1,26 @@
+using System;
+using Algorithms.Encoders;
+using NUnit.Framework;
+using NUnit.Framework.Internal;
+
+namespace Algorithms.Tests.Encoders
+{
+ public class AutokeyEncoderTests
+ {
+ [Test]
+ public static void DecodedStringIsTheSame()
+ {
+ // Arrange
+ var plainText = "PLAINTEXT";
+ var keyword = "KEYWORD";
+ var encoder = new AutokeyEncorder();
+
+ // Act
+ var encoded = encoder.Encode(plainText, keyword);
+ var decoded = encoder.Decode(encoded, keyword);
+
+ // Assert
+ Assert.That(decoded, Is.EqualTo(plainText));
+ }
+ }
+}
diff --git a/Algorithms/Encoders/AutokeyEncorder.cs b/Algorithms/Encoders/AutokeyEncorder.cs
new file mode 100644
index 000000000..83818db3e
--- /dev/null
+++ b/Algorithms/Encoders/AutokeyEncorder.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Algorithms.Encoders
+{
+ ///
+ /// Class for AutoKey encoding strings.
+ ///
+ public class AutokeyEncorder
+ {
+ ///
+ /// Autokey Cipher is a type of polyalphabetic cipher.
+ /// This works by choosing a key (a word or short phrase),
+ /// then you append the plaintext to itself to form a longer key.
+ ///
+ /// The string to be appended to the key.
+ /// The string to be appended to the plaintext.
+ /// The Autokey encoded string (All Uppercase).
+ public string Encode(string plainText, string keyword)
+ {
+ plainText = Regex.Replace(plainText.ToUpper(), "[^A-Z]", string.Empty);
+ keyword = keyword.ToUpper();
+
+ keyword += plainText;
+
+ StringBuilder cipherText = new StringBuilder();
+
+ for(int i = 0; i < plainText.Length; i++)
+ {
+ char plainCharacter = plainText[i];
+ char keyCharacter = keyword[i];
+
+ int encryptedCharacter = (plainCharacter - 'A' + keyCharacter - 'A') % 26 + 'A';
+ cipherText.Append((char)encryptedCharacter);
+ }
+
+ return cipherText.ToString();
+ }
+
+ ///
+ /// Removed the key from the encoded string.
+ ///
+ /// The encoded string.
+ /// The key to be removed from the encoded string.
+ /// The plaintext (All Uppercase).
+ public string Decode(string cipherText, string keyword)
+ {
+ cipherText = Regex.Replace(cipherText.ToUpper(), "[^A-Z]", string.Empty);
+ keyword = keyword.ToUpper();
+
+ StringBuilder plainText = new StringBuilder();
+ StringBuilder extendedKeyword = new StringBuilder(keyword);
+
+ for(int i = 0; i < cipherText.Length; i++)
+ {
+ char cipherCharacter = cipherText[i];
+ char keywordCharacter = extendedKeyword[i];
+
+ int decryptedCharacter = (cipherCharacter - 'A' - (keywordCharacter - 'A') + 26) % 26 + 'A';
+ plainText.Append((char)decryptedCharacter);
+ extendedKeyword.Append((char)decryptedCharacter);
+ }
+
+ return plainText.ToString();
+ }
+ }
+}
diff --git a/README.md b/README.md
index 198d2bd76..b9933f9fc 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,7 @@ find more than one implementation for the same objective but using different alg
* [Soundex](./Algorithms/Encoders/SoundexEncoder.cs)
* [Feistel](./Algorithms/Encoders/FeistelCipher.cs)
* [Blowfish](./Algorithms/Encoders/BlowfishEncoder.cs)
+ * [Autokey](./Algorithms/Encoders/AutokeyEncoder.cs)
* [Graph](./Algorithms/Graph)
* [Minimum Spanning Tree](./Algorithms/Graph/MinimumSpanningTree)
* [Prim's Algorithm (Adjacency Matrix)](./Algorithms/Graph/MinimumSpanningTree/PrimMatrix.cs)
From eca949603016654ef108216e5ba68de3d5c4ab4c Mon Sep 17 00:00:00 2001
From: Jc Calayag <138150245+Jccqt@users.noreply.github.com>
Date: Fri, 11 Jul 2025 22:36:15 +0800
Subject: [PATCH 2/2] Added CurrentCulture.InvariantCulture for ToUpper on
Autokey encoder
---
Algorithms.Tests/Encoders/AutokeyEncoderTests.cs | 2 +-
Algorithms/Encoders/AutokeyEncorder.cs | 9 +++++----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs b/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs
index 5ea399261..0613e1c65 100644
--- a/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs
+++ b/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs
@@ -5,7 +5,7 @@
namespace Algorithms.Tests.Encoders
{
- public class AutokeyEncoderTests
+ public static class AutokeyEncoderTests
{
[Test]
public static void DecodedStringIsTheSame()
diff --git a/Algorithms/Encoders/AutokeyEncorder.cs b/Algorithms/Encoders/AutokeyEncorder.cs
index 83818db3e..8dc13d37e 100644
--- a/Algorithms/Encoders/AutokeyEncorder.cs
+++ b/Algorithms/Encoders/AutokeyEncorder.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
@@ -19,8 +20,8 @@ public class AutokeyEncorder
/// The Autokey encoded string (All Uppercase).
public string Encode(string plainText, string keyword)
{
- plainText = Regex.Replace(plainText.ToUpper(), "[^A-Z]", string.Empty);
- keyword = keyword.ToUpper();
+ plainText = Regex.Replace(plainText.ToUpper(CultureInfo.InvariantCulture), "[^A-Z]", string.Empty);
+ keyword = keyword.ToUpper(CultureInfo.InvariantCulture);
keyword += plainText;
@@ -46,8 +47,8 @@ public string Encode(string plainText, string keyword)
/// The plaintext (All Uppercase).
public string Decode(string cipherText, string keyword)
{
- cipherText = Regex.Replace(cipherText.ToUpper(), "[^A-Z]", string.Empty);
- keyword = keyword.ToUpper();
+ cipherText = Regex.Replace(cipherText.ToUpper(CultureInfo.InvariantCulture), "[^A-Z]", string.Empty);
+ keyword = keyword.ToUpper(CultureInfo.InvariantCulture);
StringBuilder plainText = new StringBuilder();
StringBuilder extendedKeyword = new StringBuilder(keyword);