Sign in to follow this  
Followers 0
litlmike

_ArrayPermute() UDF

25 posts in this topic

It's a variation on a theme really. Where will people use any of these on a regular basis? Anyway, I used it on a recent password brute forcer app for TrueCrypt (some forum people were forgetting parts of passwords, it automates the GUI so is slow as hell, but it works). This one guy knew his password, but forgot the capitalization. So I used this routine to create an array of 0 / 1 patterns where 0 was lowercase and 1 was uppercase.

In Product Design: Create (only build-able) Bill of Materials!

Anyone who works with BOM's and needs to find (Each & Only_Valid) BOM's will use this, as I certainly will....next time I'm employed & working with BOM's again...I used to be a product structure engineer who attempted weird things with product part data...probably why I'm currently Un-employed ;)

If one understands product structure and the use of engineering / order codes for the product, then this little boogie could possibly help you in early development. The product development processes I've worked with require the team to specify valid BOM's, counts of such, and complexity considerations for manufacturing. Other things are needed such as take rates, supply constraints, etc., but the perrmutations thing has always been ... tedious at best.

Very Cool.


Good intentions will always be pleaded for every assumption of authority. It is hardly too strong to say that the Constitution was made to guard the people against the dangers of good intentions. There are men in all ages who mean to govern well, but they mean to govern. They promise to be good masters, but they mean to be masters.-Daniel Webster

Share this post


Link to post
Share on other sites



#22 ·  Posted (edited)

Way to go! This UDF is excellent! That being said I do have a suggestion regarding the internal _Array_Combination Function. The problem is how autoit fails when attempting to find the Factorial of a large number. The numbers get way to big. Luckly there is a way to find the total possible combinations without using any factorials. Here is an example generating the possible 2 value combinations from 52 values.

#include <Array.au3>

Dim $Cards[52]

For $i = 0 To 51
    $Cards[$i] = $i
Next
$aArrayCombo = _ArrayCombinations1($Cards, 2, ",")
_ArrayDisplay($aArrayCombo)

Func _ArrayCombinations1(ByRef $avArray, $iSet, $sDelim = "")
    Local $i, $aIdx[1], $aResult[1], $iN = 0, $iR = 0, $iLeft = 0, $iTotal = 0, $iCount = 1
    
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)
    If UBound($avArray, 0) <> 1 Then Return SetError(2, 0, 0)
    
    $iN = UBound($avArray)
    $iR = $iSet
    Dim $aIdx[$iR]
    For $i = 0 To $iR - 1
        $aIdx[$i] = $i
    Next
    $iTotal = New_Array_Combinations($iN, $iR)
    $iLeft = $iTotal
    
    ReDim $aResult[$iTotal + 2]
    $aResult[0] = $iTotal
    While $iLeft > 0
        _Array_GetNext($iN, $iR, $iLeft, $iTotal, $aIdx)
        For $i = 0 To $iSet - 1
            $aResult[$iCount] &= $avArray[$aIdx[$i]] & $sDelim
        Next
        If $sDelim <> "" Then $aResult[$iCount] = StringTrimRight($aResult[$iCount], 1)
        $iCount += 1
    WEnd
    Return $aResult
EndFunc   ;==>_ArrayCombinations1

Func New_Array_Combinations($n, $r)
    Local $total = 1
    For $i = $r To 1 Step - 1
        $total *= ($n / $i)
        $n -= 1
    Next
    Return $total
EndFunc   ;==>New_Array_Combinations

Func Old_Array_Combinations($iN, $iR)
    Local $i, $iNFact = 1, $iRFact = 1, $iNRFact = 1
    For $i = $iN To 2 Step - 1
        $iNFact *= $i
    Next
    For $i = $iR To 2 Step - 1
        $iRFact *= $i
    Next
    For $i = ($iN - $iR) To 2 Step - 1
        $iNRFact *= $i
    Next
    Return $iNFact / ($iRFact * $iNRFact)
EndFunc   ;==>Old_Array_Combinations
Edited by bchris01

Share this post


Link to post
Share on other sites

Nice!

Share this post


Link to post
Share on other sites

#24 ·  Posted (edited)

Ok so I found a bug or something. I think it something to do with autoit because its so random! I finally got it fixed but still cant figure out why its happening. $iLeft was becoming a very weird number. Check out the example and let me know if it does the same for you. If I changed the array size to 43, 46 ,50 or 53, the function would also cause autoit crash. The fix i figured out is to change "While $iLeft > 0" to "While Int($iLeft) > 0" . Everything seemed fine after that.

#include <array.au3>

Dim $array[1], $arraycombo

For $i = 0 To 40
    _ArrayAdd($array, $i)
Next
_ArrayDelete($array,0)
$arraycombo = _ArrayCombinations1($array, 4, ',')
MsgBox(0,'',$arraycombo[0])

Func _ArrayCombinations1(ByRef $avArray, $iSet, $sDelim = "")
    Local $i, $aIdx[1],$iN = 0, $iR = 0, $iLeft = 0, $iTotal = 0, $iCount = 1
    Global $aResult[1]
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)
    If UBound($avArray, 0) <> 1 Then Return SetError(2, 0, 0)

    $iN = UBound($avArray)
    $iR = $iSet
    Dim $aIdx[$iR]
    For $i = 0 To $iR - 1
        $aIdx[$i] = $i
    Next
    $iTotal = New_Array_Combinations($iN, $iR)
    $iLeft = $iTotal
    ReDim $aResult[$iTotal + 1]
    $aResult[0] = $iTotal

    While $iLeft > 0
        _Array_GetNextN($iN, $iR, $iLeft, $iTotal, $aIdx)
        For $i = 0 To $iSet - 1
            $aResult[$iCount] &= $avArray[$aIdx[$i]] & $sDelim
        Next
        If $sDelim <> "" Then $aResult[$iCount] = StringTrimRight($aResult[$iCount], 1)
        $iCount += 1
    WEnd
    Return $aResult
EndFunc   ;==>_ArrayCombinations

Func _Array_GetNextN($iN, $iR, ByRef $iLeft, $iTotal, ByRef $aIdx)
    Local $i, $j
    
    If $iLeft == $iTotal Then
        $iLeft -= 1
        Return
    EndIf

    $i = $iR - 1
    While $aIdx[$i] == $iN - $iR + $i
        $i -= 1
        If $i < 0 Then
            MsgBox(0,'ahhh WHAT?', '$iLeft = ' & $iLeft)
            $iLeft = -1
            Return
        EndIf
    WEnd

    $aIdx[$i] += 1
    For $j = $i + 1 To $iR - 1
        $aIdx[$j] = $aIdx[$i] + $j - $i
    Next

    $iLeft -= 1
EndFunc   ;==>_Array_GetNext

Func New_Array_Combinations($n, $r)
    Local $total = 1
    For $i = $r To 1 Step - 1
        $total *= ($n / $i)
        $n -= 1
    Next
    Return $total
EndFunc   ;==>New_Array_Combinations

Edit: Looking a little closer the problem begins in the _ArrayCombinationsInternal function. $i_Total needs to be returned as Int($i_Total).

Edited by bchris01

Share this post


Link to post
Share on other sites

It seems in your new function to get the total combinations, $total is being converted to a double, which messes up somewhere along the way. So yes, the solution is to

Return Int($total)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0