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?
-
2If 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 Answers
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

- 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
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

- 58
- 7
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

- 3,211
- 6
- 38
- 70
-
LOL. Simpler to understand? Depends on how you think I guess. :-) – Enigmativity Dec 12 '16 at 22:26
-
@Enigmativity I said simpler because you can follow the logic for composing the result, step by step. – genespos Dec 13 '16 at 09:25
-
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

- 4,369
- 3
- 18
- 31