Skip to content

Instantly share code, notes, and snippets.

@AfroThundr3007730
Last active March 5, 2024 06:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AfroThundr3007730/ffaaf3d8b8f5a748e3d341c0c042b8df to your computer and use it in GitHub Desktop.
Save AfroThundr3007730/ffaaf3d8b8f5a748e3d341c0c042b8df to your computer and use it in GitHub Desktop.
Gets recursive unique combinations of characters in a string
function Get-StringPermutations {
<# .SYNOPSIS
Calculates the permutations of an input string #>
[Alias('permutate')]
Param(
# String to calculate permutations from
[Parameter(Mandatory)]
[String]$String,
# Return only unique permutations
[Parameter()]
[Switch]$Unique
)
function _Permutate($String, $Stub = '') {
if ($String.length -eq 2) {
return ($Stub + $String[0] + $String[1]), ($Stub + $String[1] + $String[0])
}
for ($i = 0; $i -lt $String.Length; $i++) {
_Permutate -String $String.remove($i, 1) -Stub ($Stub + $String[$i])
}
}
if ($String.length -eq 1) { return $String }
if (!$Unique) { _Permutate -String $String } else {
[Collections.Generic.HashSet[string]]::new([string[]](_Permutate -String $String))
}
}
$needs_work = @'
function Get-StringPermutations {
<# .SYNOPSIS
Calculates the permutations of an input string #>
[Alias('permutate')]
Param(
# String to calculate permutations from
[Parameter(Mandatory)]
[String]$String,
# Return only unique permutations
[Parameter()]
[Switch]$Unique
)
function _Permutate($String, $Stub, $Level) {
for ($i = 0; $i -lt $String.Length; $i++) {
if ($Level -eq 1) { return $Stub + $String[$i] }
_Permutate -String $String.remove($i, 1) -Stub ($Stub + $String[$i]) -Level ($Level - 1)
}
}
function _UPermutate($String, $Stub, $Level) {
$Pool = [Collections.Generic.HashSet[char]]::new($String.length)
foreach ($i in (0..($String.length - 1) | & { process { if ($Pool.add([char]$String[$_])) { $_ } } })) {
if ($Level -eq 1) { return $Stub + $String[$i] }
_UPermutate -String $String.remove($i, 1) -Stub ($Stub + $String[$i]) -Level ($Level - 1)
}
}
# function _UPermutate($String, $Stub, $Level) {
# foreach ($i in [Collections.Generic.HashSet[char]]::new([char[]]$String)) {
# if ($Level -eq 1) { return $Stub + $i }
# _UPermutate -String $String.remove($String.LastIndexOf($i), 1) -Stub ($Stub + $i) -Level ($Level - 1)
# }
# }
if (!$Unique) { _Permutate -String $String -Stub '' -Level $String.length }
else { _UPermutate -String $String -Stub '' -Level $String.length }
}
'@
@AfroThundr3007730
Copy link
Author

Implement runspaces for parallelization of large jobs

Set-StrictMode -Version Latest

function Get-StringPermutations {
    <# .SYNOPSIS
    Calculates the permutations of an input string #>
    [Alias('permutate')]
    Param(
        # String to calculate permutations from
        [Parameter(Mandatory)]
        [String]$String,
        # Return only unique permutations
        [Parameter()]
        [Switch]$Unique
    )

    function _Permutate($String, $Stub = '') {
        if ($String.length -eq 2) {
            return ($Stub + $String[0] + $String[1]), ($Stub + $String[1] + $String[0])
        }
        for ($i = 0; $i -lt $String.Length; $i++) {
            _Permutate -String $String.remove($i, 1) -Stub ($Stub + $String[$i])
        }
    }

    if ($String.length -eq 1) { return $String }
    elseif ($String.length -le 10) {
        if (!$Unique) { _Permutate -String $String } else {
            [Collections.Generic.HashSet[string]]::new([string[]](_Permutate -String $String))
        }
    } elseif ($String.length -gt 10) {
        $jobs = [Collections.Concurrent.ConcurrentDictionary[string, object]]::new()
        if (!$Unique) {} else {
            #runspaces
        }
    }
}

Notes:

  • Parrallelization for longer strings by iterating until the length = 10 threshold and launching _Permutate in a runspace
  • Runspace pool will have concurrent job count equal to hardware thread count or core count, if no hyperthreading
  • Store results by job id, which is the permutation stub for the current iteration at the length = 10 threshold
  • Each job id only runs once, even though multiple stubs could be equivalent, results can be retrieved more than once
  • Need to decide on whether ordered results retrieval is necessary and investigate the impact of sequential retrieval
  • Perhaps export the runspace pool management to another function, or look at how foreach-object -parallel manages it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment