Skip to content

Instantly share code, notes, and snippets.

@AfroThundr3007730
Last active March 31, 2024 19:45
Show Gist options
  • 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

@AfroThundr3007730
Copy link
Author

AfroThundr3007730 commented Mar 31, 2024

Now part of my HelperFunctions module.

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