views:

77

answers:

2

I'm implementing a c# program that should automatize a Mono-alphabetic substitution cipher. The functionality i'm working on at the moment is the simplest one: The user will provide a plain text and a cipher alphabet, for example:

Plain text(input): THIS IS A TEST

Cipher alphabet: A -> Y, H -> Z, I -> K, S -> L, E -> J, T -> Q

Cipher Text(output): QZKL KL QJLQ

I thought of using regular expressions since I've been programming in perl for a while, but I'm encountering some problems on c#. First I would like to know if someone would have a suggestion for a regular expression that would replace all occurrence of each letter by its corresponding cipher letter (provided by user) at once and without overwriting anything.

Example:

In this case, user provides plaintext "TEST", and on his cipher alphabet, he wishes to have all his T's replaced with E's, E's replaced with Y and S replaced with J. My first thought was to substitute each occurrence of a letter with an individual character and then replace that character by the cipherletter corresponding to the plaintext letter provided.

Using the same example word "TEST", the steps taken by the program to provide an answer would be:

1 - replace T's with (lets say) @

2 - replace E's with #

3 - replace S's with &

4 - Replace @ with E, # with Y, & with j

5 - Output = EYJE

This solution doesn't seem to work for large texts. I would like to know if anyone can think of a single regular expression that would allow me to replace each letter in a given text by its corresponding letter in a 26-letter cipher alphabet without the need of splitting the task in an intermediate step as I mentioned.

If it helps visualize the process, this is a print screen of my GUI for the program: alt text

+1  A: 

I don't think regular expressions are the right tool here. In Perl you would use the transliteration feature tr/TES/EYJ/. C# doesn't have this but you can do it by using a StringBuilder and looking at each character individually.

private static string Translate(string input, string from, string to)
{
    StringBuilder sb = new StringBuilder();
    foreach (char ch in input)
    {
        int i = from.IndexOf(ch);
        if (i < 0)
        {
            sb.Append(ch);
        }
        else if (i < to.Length)
        {
            sb.Append(to[i]);
        }
    }
    return sb.ToString();
}

The source code is a modified version of this answer from this similar question. The answers there show some other ways of doing this.

Mark Byers
Thank you Mark, I'll have a look into what you just mentioned. I looked everywhere trying to find a translate feature on c#, you just confirmed what I feared.
Everaldo Aguiar
Works great using this solution. Thanks again
Everaldo Aguiar
+2  A: 

You could also make a map of source to destination characters, then simply loop through the string and replace as you go:

Dictionary<char, char> replacements = new Dictionary<char, char>();

// set up replacement chars, like this
replacements['T'] = '@';
replacements['E'] = '#';
replacements['S'] = '&';
replacements['@'] = 'E';
replacements['#'] = 'Y';
replacements['&'] = 'J';

// actually perform the replacements
char[] result = new char[source.Length];
for (int i = 0; i < result.Length; i++) {
    result[i] = replacements[source[i]];
}

return new string(result);
Ben Herila
Yeah, that's another idea. A little less efficient than the previous one, but definitely easier than the regexp.
Everaldo Aguiar