-3

I have a word, "seventeen", and have to come up with all possible ways of writing it. That is to say, it might be Seventeen, sEvenTeeN, and so on. Any one with an idea how I can achieve this goal?

xxx
  • 3
  • 4
  • 2
    If you have an n-letter word, you'll have `52^n` possible combinations. – Fᴀʀʜᴀɴ Aɴᴀᴍ Dec 11 '16 at 07:04
  • See [this answer](http://stackoverflow.com/questions/4443671/creating-a-list-of-possible-string-combination?noredirect=1&lq=1). Feed it all the letters from "A-Z" and "a-z" and you should get what you want. – Fᴀʀʜᴀɴ Aɴᴀᴍ Dec 11 '16 at 07:08
  • You probably don't want to loop through them all because there's so many. Assuming the only difference is letter-case then there's 2^n combinations of case, so for a 10-letter word there would be 1024 possibilities. – Dai Dec 11 '16 at 07:10
  • Can you explain why you need it? Because if you tell a final goal - there can be more light approaches for your problem then generating all possible cases – Fabio Dec 11 '16 at 10:02
  • 1
    @FᴀʀʜᴀɴAɴᴀᴍ .. if it's just caps and lower case wouldn't it be 2^n? Please correct me if I'm wrong :-) – David Wilson Dec 12 '16 at 14:33
  • @DavidWilson Oh dear... you're right... I don't know why but I interpreted the question as asking for all possible 17-letter words. :P... – Fᴀʀʜᴀɴ Aɴᴀᴍ Dec 12 '16 at 15:03

4 Answers4

1

Try this:

Dim word = "seventeen"

Dim generate As Func(Of String, IEnumerable(Of String)) = Nothing
generate = Function(w) _
    If(String.IsNullOrEmpty(word), _
        { String.Empty }, _
        From h In _
        { _
            w.Substring(0, 1).ToLowerInvariant(), _
            w.Substring(0, 1).ToUpperInvariant() _
        } _
        From t In generate(w.Substring(1)) _
        Select h & t)

Dim results = generate(word)

It produces 512 variants of the word "seventeen":

seventeen, Seventeen, sEventeen, SEventeen, seVenteen, SeVenteen, sEVenteen, (DELETED), SevENTEEN, sEvENTEEN, SEvENTEEN, seVENTEEN, SeVENTEEN, sEVENTEEN, SEVENTEEN


To help make this a little easier to understand here's the normal function version:

Public Function Generate(word As String) As IEnumerable(Of String)
    If String.IsNullOrEmpty(word)
        Return { String.Empty }
    Else
        Return _
            From h In _
            { _
                word.Substring(0, 1).ToLowerInvariant(), _
                word.Substring(0, 1).ToUpperInvariant() _
            } _
            From t In generate(word.Substring(1)) _
            Select h & t
    End If
End Function
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • And it's quick! about 20 times faster than @genespos code and my code(which I wont bother posting as it's about as fast as his answer) – David Wilson Dec 12 '16 at 19:44
  • 1
    @DavidWilson If your answer has a different logic I think you have to post it, because each idea has pros and cons and I think that looking at a problem from different angles is anyway a good exercise. ;) – genespos Dec 14 '16 at 16:37
0

break the text in to words. The do the test of your string.tolower against each word.tolower. When you find a match save the word without the .tolower

Chestdawg
  • 58
  • 7
0

The answer posted by Enigmativity is clearly better, but this is more simpler to understand:

Private Sub Btn_AllCases_Click(sender As Object, e As EventArgs) Handles Btn_AllCases.Click
    Dim OriginalWord As String = "seventeen"
    Dim CharsArr() As Char = OriginalWord.ToCharArray
    Dim Combs As Integer = CInt(2 ^ CharsArr.Length)
    Dim CombsArr(Combs - 1) As String
    Dim ChangeInterval As Integer = Combs
    For Chr As Integer = 0 To CharsArr.Length - 1
        ChangeInterval = CInt(ChangeInterval / 2)
        Dim UpperLower As Boolean = True
        Dim ChangeCount As Integer = ChangeInterval
        For Comb As Integer = 0 To Combs - 1
            ChangeCount -= 1
            UpperLower = If(ChangeCount = 0, Not UpperLower, UpperLower)
            If UpperLower Then
                CombsArr(Comb) &= CharsArr(Chr).ToString.ToUpper
            Else
                CombsArr(Comb) &= CharsArr(Chr).ToString.ToLower
            End If
            If ChangeCount = 0 Then ChangeCount = ChangeInterval
        Next
    Next
    'Test: Put all words into an HashSet to check for No duplicates
    Dim HashWords As New HashSet(Of String)
    For W As Integer = 0 To CombsArr.Length - 1
        HashWords.Add(CombsArr(W))
    Next
    MsgBox("Hashset.Count:" & HashWords.Count.ToString & vbCrLf &
           "CombsArr.Length:" & CombsArr.Length.ToString)
End Sub
genespos
  • 3,211
  • 6
  • 38
  • 70
0

This is my take on a possible solution.

It's not quite as fast as the solution by genespos and nowhere near as quick as the answer by Enigmativity, but it's comparable to genespos's answer. This function gets the length of the string and iterates over 2 to the power of the number of characters, It occurred to me that each possible state - upper or lower case is binary.

So.. The outer loop uses the loop index to create a binary string of the same number of digits as there are characters in the string. 1 corresponding to upper case and 0 corresponding to lower case.

Then the inner loop iterates over the binary string and the original string and builds a new string with upper and lower case characters depending on what is contained in the binary string. The string produced by the inner loop is added to the list and so on until the outer loop is complete and the final list is returned from the function.

I'm pretty sure that it's possible to optimize this code, but at least you get a sorted list of all the permutations.

Here goes..

Private Function GetAllCasePermutations(originString As String) As List(Of String)
    Dim resultList As New List(Of String)
    Dim originLength As Integer = originString.Length
    originString = originString.ToLower
    For i As Integer = 1 To CInt(2 ^ originLength)
        Dim binaryIndexString As String = Convert.ToString(i, 2)
        binaryIndexString=binaryIndexString.PadLeft(originLength,"0")
        Dim resultString As New StringBuilder
        For j As Integer = 1 To originLength
            If Mid(binaryIndexString, j, 1) = 1 Then
                resultString.Append(Mid(originString, j, 1).ToUpper)
            Else
                resultString.Append(Mid(originString, j, 1).ToLower)
            End If
        Next
        resultList.Add(resultString.ToString)
    Next
    Return resultList
End Function
David Wilson
  • 4,369
  • 3
  • 18
  • 31