# ROT13 encoder/decoder

This is a simple utility, intended to sit on the desktop for when needed, that does the simple ROT13 encoding and decoding.

I am used to coding in VBA, and I am interested in more .Net idiomatic coding styles.

Public Class Rot13Decoder

Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles txtRotEntry.TextChanged
lblResult.Text = Rot13(txtRotEntry.Text)
End Sub

Function Rot13(Source As String) As String
Dim i As Long
Dim result As String = ""

For i = 0 To Source.Length - 1
Dim myChar As Char
myChar = Source.Substring(i, 1)

Select Case myChar ' originally used Asc(Source(i)), hence the integers below
Case "a" To "m", "A" To "M" '65 To 77, 97 To 109
result &= Chr(Asc(myChar) + 13) 'Chr(Asc(Source(i)) + 13)
Case "n" To "z", "N" To "Z" '78 To 90, 110 To 122
result &= Chr(Asc(myChar) - 13) 'Chr(Asc(Source(i)) - 13)
Case Else
result &= myChar
End Select
Next

Return result
End Function

Public Sub New()

' This call is required by the designer.
InitializeComponent()

' Add any initialization after the InitializeComponent() call.

End Sub
End Class


(The title of the form says decoder, and I am using it in the example to encode!)

Double clicking on the form result label copies the text to the clipboard for use.

## 2 Answers

The number one problem here is that you concatenate translated letters on to your string one at a time. Since strings are immutable in .NET (and most right thinking languages), this means for the first translated character your program allocates space for a new string of length 1 (copying the previous 0-char string), for the second character it allocates space for a new string of length 2 (copying the previous 1-char string), for the third character it allocates space for a new string of length 3 (copying the previous 2-char string), and so on. The end result is that for an input n characters long, your program will allocate 1 + 2 + 3 + ... + n = $$\O(n^2)\$$ space and, similarly, perform $$\O(n^2)\$$ operations! A better structure is to use a .NET StringBuilder which is designed precisely for this piecemeal kind of string construction. Using a StringBuilder your program will allocate $$\O(n)\$$ space and perform $$\O(n)\$$ operations -- that's a big saving when your input is of any non-trivial length.

One of the problems with your approach, is it's not very extensible. If you wanted different rotation factors or even to make a full Caesar Cypher, you would have to totally rewrite your code. A math based approach(Mod 26) can be used to allow any rotation factor, within reasonable limits.

Another approach which will allow O(n) space is to convert the string to a char array and change the characters in place.

It could look something like this:

Public Function ROT13(input As String) As String
Dim chars = input.ToArray()
Const UpperA As Integer = Asc("A"c)
Const LowerA As Integer = Asc("a"c)
For i = 0 To chars.Length - 1
If Char.IsLetter(chars(i)) Then
If Char.IsUpper(chars(i)) Then
chars(i) = Chr((((Asc(chars(i)) - UpperA) + 13) Mod 26) + UpperA)
Else
chars(i) = Chr((((Asc(chars(i)) - LowerA) + 13) Mod 26) + LowerA)
End If
End If
Next
Return New String(chars)
End Function


I've hard coded the rotation factor to 13. But it should be a simple matter to add a rotation parameter to the function.

• On the other hand, the current case-based version is quite clear in what it's doing. – Mark Jul 17 '19 at 20:15
• @Mark - Clear yes. But extending it to other rotations requires a total rewrite. It's always to good practice to think in terms of being able to re-use an algorithms. – tinstaafl Jul 17 '19 at 20:21
• It's also good practice to think in terms of maintenance, and a ROT-13 function is more likely to need maintenance than to need to be turned into a Caesar cipher. – Mark Jul 17 '19 at 20:23
• Surely a single modulo expression is far more readable and maintainable than something containing branching logic! – Daniel McLaury Jul 17 '19 at 21:07
• @DanielMcLaury: Maintainable and extensible - yes; readable - not necessarily. – AJD Jul 18 '19 at 22:29