Zinthose Posted September 11, 2008 Posted September 11, 2008 (edited) Greetings, I'm trying to determine all the possible permutations of a collection of bit flags so I have all the possible values that Altiris. Currently I'm using a method to iterate through all int32 values performing a BitAnd looking for matches. This is very inefficient and also takes a long time. Anyone have any tips to speed up the process? ;## Determine all permutations of Bit Flags #Include <Array.au3> Global $BaseFlag = 512 Global $SuccessFlags = 0x4 + 0x10 + 0x2000 + 0x20000 + 0x40000 ConsoleWrite("! " & _Permutations($BaseFlag, $SuccessFlags) & @CRLF) Func _Permutations ($BaseFlag, $SuccessFlags) Local $SuccessCodes = "" Local $TestNumber = 1 Local $TestBit = 0 Local $Pattern = "" ConsoleWrite("! Please Wait... This can take a very long time to calculate all possible permutations." & @CRLF) While True $TestBit = BitAND($SuccessFlags, $TestNumber) + $BaseFlag $TestBit = BitOR($TestBit, $BaseFlag) If $TestBit <> 0 Then $Pattern = "(\A|,)" & String($TestBit) & "(\z|,)" If StringRegExp($SuccessCodes, $Pattern) = 0 Then If $SuccessCodes <> "" Then $SuccessCodes &= "," $SuccessCodes &= String($TestBit) EndIf EndIf ;$TestBit = BitShift($TestBit, -1) If $TestNumber = 0x7FFFFFFF Or $TestNumber >= $SuccessFlags Then ExitLoop; <== Added "Or $TestNumber >= $SuccessFlags" which will shorten the process time as long as no high value bit flag is in use or even the negative bit. $TestNumber += 1 WEnd Return $SuccessCodes EndFunc Edited September 11, 2008 by Zinthose --- TTFN
PsaltyDS Posted September 11, 2008 Posted September 11, 2008 Greetings, I'm trying to determine all the possible permutations of a collection of bit flags so I have all the possible values that Altiris. Currently I'm using a method to iterate through all int32 values performing a BitAnd looking for matches. This is very inefficient and also takes a long time. Anyone have any tips to speed up the process? ;## Determine all permutations of Bit Flags #Include <Array.au3> Global $BaseFlag = 512 Global $SuccessFlags = 0x4 + 0x10 + 0x2000 + 0x20000 + 0x40000 ConsoleWrite("! " & _Permutations($BaseFlag, $SuccessFlags) & @CRLF) Func _Permutations ($BaseFlag, $SuccessFlags) Local $SuccessCodes = "" Local $TestNumber = 1 Local $TestBit = 0 Local $Pattern = "" ConsoleWrite("! Please Wait... This can take a very long time to calculate all possible permutations." & @CRLF) While True $TestBit = BitAND($SuccessFlags, $TestNumber) + $BaseFlag $TestBit = BitOR($TestBit, $BaseFlag) If $TestBit <> 0 Then $Pattern = "(\A|,)" & String($TestBit) & "(\z|,)" If StringRegExp($SuccessCodes, $Pattern) = 0 Then If $SuccessCodes <> "" Then $SuccessCodes &= "," $SuccessCodes &= String($TestBit) EndIf EndIf ;$TestBit = BitShift($TestBit, -1) If $TestNumber = 0x7FFFFFFF Or $TestNumber >= $SuccessFlags Then ExitLoop; <== Added "Or $TestNumber >= $SuccessFlags" which will shorten the process time as long as no high value bit flag is in use or even the negative bit. $TestNumber += 1 WEnd Return $SuccessCodes EndFunc You only need a bit per value to permutate (5 bits = 32 permutations = .003sec on my computer): Global $BaseFlag = 512 Global $SuccessFlags[5] = [0x4, 0x10, 0x2000, 0x20000, 0x40000] $Results = "" $iTimer = TimerInit() For $n = 0 To (2^5) - 1 $Test = $BaseFlag For $b = 0 To 4 If BitAND(2^$b, $n) Then $Test += $SuccessFlags[$b] Next $Results &= "0x" & Hex($Test,5) & @CRLF Next $Results = StringTrimRight($Results, 1) $nTimer = Round(TimerDiff($iTimer)/1000, 3) ConsoleWrite("$Results in " & $nTimer & "sec" & @LF & $Results & @LF) Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Zinthose Posted September 11, 2008 Author Posted September 11, 2008 You only need a bit per value to permutate (5 bits = 32 permutations = .003sec on my computer): Global $BaseFlag = 512 Global $SuccessFlags[5] = [0x4, 0x10, 0x2000, 0x20000, 0x40000] $Results = "" $iTimer = TimerInit() For $n = 0 To (2^5) - 1 $Test = $BaseFlag For $b = 0 To 4 If BitAND(2^$b, $n) Then $Test += $SuccessFlags[$b] Next $Results &= "0x" & Hex($Test,5) & @CRLF Next $Results = StringTrimRight($Results, 1) $nTimer = Round(TimerDiff($iTimer)/1000, 3) ConsoleWrite("$Results in " & $nTimer & "sec" & @LF & $Results & @LF) >_< Sweet! This is allot faster... now I just need to pick it apart to understand it. --- TTFN
Malkey Posted September 11, 2008 Posted September 11, 2008 To enhance your example to make it more visual, added binary output. Global $BaseFlag = 512 Global $SuccessFlags[5] = [0x4, 0x10, 0x2000, 0x20000, 0x40000] $Results = "" $iTimer = TimerInit() For $n = 0 To (2 ^ 5) - 1 $Test = $BaseFlag For $b = 0 To 4 If BitAND(2 ^ $b, $n) Then $Test += $SuccessFlags[$b] Next $Results &= "0x" & Hex($Test, 5) & " = " & Hex2Bin("0x" & Hex($Test, 5)) & @CRLF Next ;$Results = StringTrimRight($Results, 1) $nTimer = Round(TimerDiff($iTimer) / 1000, 3) ConsoleWrite("$Results in " & $nTimer & "sec" & @LF & $Results) Func Hex2Bin($hex) Local $b = "" For $i = 1 To 32 $b = BitAND($hex, 1) & $b $hex = BitShift($hex, 1) Next Return $b EndFunc ;==>Hex2Bin
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now