I've taken a permutation generator solution on @Artur Udod answer in this question:
Print all the possible combinations of "X" amount of characters with "X" string length (Brute Force)
I've adapted the code to return Strings instead a collection of Char
andalso be able to specify whether character repetition is allowed or not on the generated permutations:
Public Shared Function PermuteCharacters(ByVal charSet As IEnumerable(Of Char),
ByVal length As Integer,
ByVal isRepetitionAllowed As Boolean) As IEnumerable(Of String)
If length = 1 Then
Return charSet.Select(Function(c As Char)
Return New String(New Char() {c})
End Function)
Else
Return PermuteCharacters(charSet, length - 1, isRepetitionAllowed).
SelectMany(Function(x As String) charSet,
Function(str As String, c As Char)
Select Case isRepetitionAllowed
Case True
Return str & c
Case Else
' Firstly I need to check if string is empty because
' String.Contains() will throw an exception on empty strings.
' This need to be fixed to avoid empty strings.
If String.IsNullOrEmpty(str) Then
Return Nothing
End If
If Not str.Contains(c) Then
Return str & c
Else
Return Nothing
End If
End Select
End Function)
End If
End Function
An example usage:
Dim permutations As IEnumerable(Of String) =
PermuteCharacters("123456789", 2, isRepetitionAllowed:=False)
The problem is that the function will create, parse, and return empty strings when I set repetition to False, with the negative point of performance that will cause in large set or permutation lengths.
I know that I could use IEnumerable.Distinct()
method to remove all empty strings but one, but that will iterate again the entire big collection causing more negative performance on the code itself.
How can I design efficiently and properly the function, taking in count the performance, the overall execution time needed to create a collection of permutations?.
Its important to say that I don't see LINQ usage as a very disadvantage of performance, I will to keep using LINQ because it allows to develop a reduced code instead of the required thousands of lines for a common Loop to translate a LINQ query like that.
PS: My secondary goal is to implement the Iterator
keyword on the function to improve more its performance, if someone could illustrate with a solution for this issue that also implements the Iterator
capabilities will be more than awesome (and perfect).