Lauren
Lauren

Reputation: 77

VB - Substitution of letters

so I am making a decryption software that allows the user to input some text and then they can swap out letters in the program. For example, there is a drop down box that allows you to swap all the "O"'s in a user input to "W". So in the input "Stack overflow" the output would be "Stack wverflww".

However, my problem is is that when the user chooses a second letter to change, that has already been swapped, it causes a problem. For example, after the first above example has occurred, if the user then wanted to then change all the "W"'s in their input to "A"'s the output would be "stack averflaa". However, what I'm looking for the code to do is give an output of "Stack wverflwa". So only the original "W"'s of the user input are changed to the letter "A".

I hope the above makes sense.

Someone suggested using a two dimensional array to reassign the letters new letters and I am able to do this, but I have no idea how to then put this into my code and get it working. Below is my code and thank you to anyone who can help me.

    Dim chooseLetter, replaceLetter, words2
    chooseLetter = selectLetterCombo.Text
    replaceLetter = replaceLetterCombo.Text
    words2 = UCase(textInputBox.Text)
    Dim replaceList As New List(Of String)
    For Each z In words2
        If z = chooseLetter Then
            replaceList.Add(replaceLetter)
        Else
            replaceList.Add(z)
        End If
    Next
    letterReplaceBox.Text = ""
    For Each f In replaceList
        letterReplaceBox.Text = letterReplaceBox.Text & f
    Next

note: selectLetterCombo.Text is the letter chosen by the user that they want to replace and replaceLetterCombo.Text is the letter chosen by the user that they want to swap the first chosen letter with. Also, textInputBox.text is the text the user has inputted.

Thank you!

Upvotes: 0

Views: 435

Answers (3)

David Wilson
David Wilson

Reputation: 4439

These two functions will do the job, although there is no allowance for punctuation, just spaces.

Private Function EncryptText(str As String) As String
    Dim swapletters() As String = {"l", "s", "d", "f", "g", "h", "j", "k", "a", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "z", "x", "c", "v", "b", "n", "m"}
    Dim encryptedText As String = ""
    For Each letter As Char In str
        If letter = " "c Then
            encryptedText = encryptedText & " "
        Else
            Dim charactercode As Integer = Asc(letter) - 97
            encryptedText = encryptedText & swapletters(charactercode)
        End If
    Next
    Return encryptedText
End Function

Private Function DecryptText(str As String) As String
    Dim swapletters As New List(Of String) From {"l", "s", "d", "f", "g", "h", "j", "k", "a", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "z", "x", "c", "v", "b", "n", "m"}
    Dim decryptedText As String = ""
    For Each letter As Char In str
        If letter = " "c Then
            decryptedText = decryptedText & " "
        Else
            Dim character As String = Chr(swapletters.IndexOf(letter)  + 97)
            decryptedText = decryptedText & character
        End If
    Next
    Return decryptedText
End Function

To use them, declare a string to hold the return value of each function

Dim etext As String 
etext = EncryptText("disambiguation is the root of all evil")

results in etext being "faplrsajxlzayt ap zkg oyyz yh lee gcae"

and

Dim dtext As String 
dtext = DecryptText("faplrsajxlzayt ap zkg oyyz yh lee gcae")

results in "disambiguation is the root of all evil"

Upvotes: 0

Andrew Morton
Andrew Morton

Reputation: 25057

I have an answer, but you're really not going to like it:

Option Infer On
Option Strict On

Imports System.Text.RegularExpressions

Module Module1

    Dim swaps As New Dictionary(Of Char, Char)

    Function DoSwaps(originalText As String, swapLetters As Dictionary(Of Char, Char)) As String
        Dim newText As String = ""
        For Each c In originalText
            If swapLetters.ContainsKey(c) Then
                newText &= swapLetters(c)
            Else
                newText &= c
            End If
        Next

        Return newText

    End Function

    Sub Main()
        Console.Write("Enter the text to be altered: ")
        Dim t = Console.ReadLine()

        Dim exitNow = False

        Do
            Console.Write("Enter the letter to swap from and the letter to swap to, or a blank line to quit: ")
            Dim s = Console.ReadLine()
            If s.Trim().Length = 0 Then
                exitNow = True
            Else
                Dim parts = Regex.Matches(s, "([A-Za-z])")
                If parts.Count >= 2 Then
                    Dim letter1 = CChar(parts.Item(0).Value)
                    Dim letter2 = CChar(parts.Item(1).Value)

                    If swaps.ContainsKey(letter1) Then
                        swaps.Item(letter1) = letter2
                    Else
                        swaps.Add(letter1, letter2)
                    End If

                    Console.WriteLine(DoSwaps(t, swaps))

                End If
            End If

        Loop Until exitNow

    End Sub

End Module

... unless you'd like to learn about the Dictionary class to understand how it works. I used a simple regular expression to parse the user input, but if you're using dropdowns to select the letters then that would just be bonus learning if you explore it.

The essential feature is that you keep the original string (t in the above code) and apply the transformation (I named it DoSwaps) to that each time, not to the previously transformed string.

Upvotes: 0

Sorceri
Sorceri

Reputation: 8043

You should be able to keep a list of the index of the character that changed and check that before making another change.

'List to keep track of changed character index
Dim replacedCharsList As New List(Of Integer)'member variable

Dim chooseLetter, replaceLetter, words2
chooseLetter = selectLetterCombo.Text
replaceLetter = replaceLetterCombo.Text
words2 = UCase(textInputBox.Text)

Dim replaceList As New List(Of String)
Dim i As Integer
For i = 1 To Len(words2)
    'remove the for each and go with a straight for loop to keep track if the index
    If Mid(words2, i, 1) = chooseLetter Then
        'check to see if we have already replaced this character via the index position
        If replacedCharsList.Contains(i) = False Then
            'we have not changed this so add the replacement letter and update our index list
            replaceList.Add(replaceLetter)
            replacedCharsList.Add(i)
        Else
            'we have already changed this character so just add it as is
            replaceList.Add(Mid(words2, i, 1))
        End If
    Else
        replaceList.Add(Mid(words2, i, 1))
    End If
Next

letterReplaceBox.Text = ""
For Each f In replaceList
    letterReplaceBox.Text = letterReplaceBox.Text & f
Next

Upvotes: 1

Related Questions