nAutoIT Posted August 17, 2011 Posted August 17, 2011 Global $chararray[4] = ["a", "b", "1", "2"] $outputfile = FileOpen("Output.txt", 1) $time = TimerInit() For $a = 0 To 3 For $b = 0 To 3 For $c = 0 To 3 For $d = 0 To 3 For $e = 0 To 3 For $f = 0 To 3 For $g = 0 To 3 For $h = 0 To 3 For $i = 0 To 3 For $j = 0 To 3 For $k = 0 To 3 For $l = 0 To 3 $line = $chararray[$a] & $chararray[$b] & $chararray[$c] & $chararray[$d] & $chararray[$e] & $chararray[$f] & $chararray[$g] & $chararray[$h] & $chararray[$i] & $chararray[$j] & $chararray[$k] & $chararray[$l] If StringInStr($line, "aaaa") = 0 And StringInStr($line, "bbbb") = 0 And StringInStr($line, "1111") = 0 And StringInStr($line, "2222") = 0 And StringInStr($line, "a") <> 0 And StringInStr($line, "b") <> 0 And StringInStr($line, "1") <> 0 And StringInStr($line, "2") <> 0 Then FileWriteLine($outputfile, $line) Next Next Next Next Next Next Next Next Next Next Next Next MsgBox(1,"Time 1", TimerDiff($time)) This takes 6 Minutes and creates a Text file with all valid permutations. My PC has only 3GB, which is not enough to handle 1-2 arrays with 17Million Elements i guess. Maybe with 8GB you can do it like this: $z = 0 For $m = 0 To 16777215 If StringInStr($permutationarray[$m], "aaaa") = 0 And StringInStr($permutationarray[$m], "bbbb") = 0 And StringInStr($permutationarray[$m], "1111") = 0 And StringInStr($permutationarray[$m], "2222") = 0 And StringInStr($permutationarray[$m], "a") <> 0 And StringInStr($permutationarray[$m], "b") <> 0 And StringInStr($permutationarray[$m], "1") <> 0 And StringInStr($permutationarray[$m], "2") <> 0 Then $validsarray[$z] = $permutationarray[$m] $z += 1 EndIf Next
MvGulik Posted August 17, 2011 Posted August 17, 2011 (edited) Possible speed ups. - Buffering the string to file to write it at loop A (or loop B if memory is a issue) and not doing it in the inner most loop. - Building up the perm-term inside the loop parts. ...For $a = 0 To 3 $bA = $chararray[$a] For $b = 0 To 3 $bB = $bA & $chararray[$b] --- ;; Just for the fun of it.;; Just for the fun of it. MsgBox(0, 'Foobar', main()) Func main() Local Const $NL = '|' ;; @CRLF Local $aChar[4] = ["a", "b", "1", "2"] ;; locked characters -> hardcoded use in _CheckUp(). Local $iPerLoop = UBound($aChar, 1) Local $iLoops = 4 Local $sOut = '' _Recurse($sOut, $aChar, $NL, $iPerLoop, $iLoops) Return StringTrimRight($sOut, StringLen($NL)) EndFunc Func _Recurse(ByRef $sOut, ByRef Const $aChar, ByRef Const $sDelim, ByRef Const $iPerLoop, ByRef Const $iLoops, $sBuf = '', $iLoop = 0) If $iLoop = $iLoops Then _CheckUp($sOut, $sBuf, $sDelim) Else For $i = 0 To $iPerLoop -1 _Recurse($sOut, $aChar, $sDelim, $iPerLoop, $iLoops, $sBuf & $aChar[$i], $iLoop + 1) Next EndIf EndFunc Func _CheckUp(ByRef $sOut, ByRef Const $sPerm, ByRef Const $sDelim) ;; just moved out of the way of the recursion code. If StringInStr($sPerm, "aaaa") Or StringInStr($sPerm, "bbbb") Or StringInStr($sPerm, "1111") Or StringInStr($sPerm, "2222") Then Return EndIf If StringInStr($sPerm, "a") And StringInStr($sPerm, "b") And StringInStr($sPerm, "1") And StringInStr($sPerm, "2") Then $sOut &= $sPerm & $sDelim EndIf EndFunc Think I'm out. Buying new computer or something. Edited August 17, 2011 by iEvKI3gv9Wrkd41u "Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions.""The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014) "Believing what you know ain't so" ... Knock Knock ...
czardas Posted August 19, 2011 Posted August 19, 2011 (edited) Despite my earlier mistakes, this has been a learning curve for me, and also a good coding exercise. I finally decided on the brute force approach. The method avoids building erroneous strings to test, and instead sellects characters that fit the criteria beforehand. I think it's pretty fast. I learned something about the limits of using arrays in AutoIt. The code is valid for string lengths of 6 to 11 characters. I ran into memory allocation problems when trying 12 characters. Presumably a consequence of the 16,000,000 array element limitation in AutoIt. expandcollapse popup#include <String.au3> #include <File.au3> Go() Func Go() Local $aResults, $iTimer, $iStringlen = 8 ; Only accepts integer values from 6 To 11 $iTimer = TimerInit() $aResults = _GetResults($iStringlen) If @error Then MsgBox(64, "Message","Out of bounds input") Exit EndIf Consolewrite("Array created in " & TimerDiff($iTimer)/1000 & " seconds" & @LF & _ "with a total of " & UBound($aResults) & " results >>>" & @LF) $iTimer = TimerInit() _FileWriteFromArray("results.txt", $aResults) Consolewrite("written to file in " & TimerDiff($iTimer)/1000 & " seconds" & @LF) EndFunc Func _GetResults($iStringlen) If IsInt($iStringlen) = 0 Or $iStringlen < 6 Or $iStringlen > 11 Then Return SetError (1) Local $aChar[4] = ["1","2","a","b"], $aArray[64], $n = 0 For $i = 0 To 3 For $j = 0 To 3 For $k = 0 To 3 $aArray[$n] = $aChar[$i] & $aChar[$j] & $aChar[$k] $n +=1 Next Next Next For $i = 4 To $iStringlen $aArray = _AddChars($aArray, $aChar, $i, $iStringlen) Next Return $aArray EndFunc Func _AddChars($aArray, $aChar, $iRun, $iStringlen) Local $n = 0 If $iRun < $iStringlen -1 Then Local $aTemp[_GetUBound($iRun, 0)] For $i = 0 To UBound($aArray) -1 _populate($aTemp, $n, $aArray[$i], $aChar) Next ElseIf $iRun = $iStringlen -1 Then Local $aTemp[_GetUBound($iRun, 1)] For $i = 0 To UBound($aArray) -1 $ret = _GetMissingChars($aArray[$i]) If $ret = -1 Then _populate($aTemp, $n, $aArray[$i], $aChar) Else $aTemp[$n] = $aArray[$i] & $ret $aTemp[$n +1] = $aArray[$i] & _StringReverse($ret) $n +=2 EndIf Next ElseIf $iRun = $iStringlen Then Local $aTemp[_GetUBound($iRun, 2)] For $i = 0 To UBound($aArray) -1 If StringLen($aArray[$i]) <> $iRun Then $ret = _GetFinalChar($aArray[$i]) If $ret = -1 Then _populate($aTemp, $n, $aArray[$i], $aChar) Else $aTemp[$n] = $aArray[$i] & $ret $n +=1 EndIf Else $aTemp[$n] = $aArray[$i] $n +=1 EndIf Next EndIf Return $aTemp EndFunc Func _GetUBound($j, $i) Local $aUBound[3][8] = _ [[252,996,3936,15552,61452,242820,0,0], _ [0,840,3648,15024,60480,241032,956184,0], _ [0,0,1560,8304,39720,178320,769224,3232224]] Return $aUBound[$i][$j -4] EndFunc Func _populate(ByRef $aTemp, ByRef $n, $string, $aChar) $ret = _Capture($string) If $ret = -1 Then For $j = 0 To 3 $aTemp[$n] = $string & $aChar[$j] $n +=1 Next Else For $j = 0 To 3 If $j = $ret Then ContinueLoop $aTemp[$n] = $string & $aChar[$j] $n +=1 Next EndIf EndFunc Func _Capture($string) $string = StringRight($string, 3) Switch $string Case "111" Return 0 Case "222" Return 1 Case "aaa" Return 2 Case "bbb" Return 3 EndSwitch Return -1 EndFunc Func _GetMissingChars($string) Local $ret = _GetFinalChar($string) ; Final or penultimate char If $ret = -1 Then Return -1 Switch $ret Case "1" If Not StringInStr($string, "2") Then Return "12" If Not StringInStr($string, "a") Then Return "1a" If Not StringInStr($string, "b") Then Return "1b" Case "2" If Not StringInStr($string, "a") Then Return "2a" If Not StringInStr($string, "b") Then Return "2b" Case "a" If Not StringInStr($string, "b") Then Return "ab" EndSwitch Return -1 EndFunc Func _GetFinalChar($string) If Not StringInStr($string, "1") Then Return "1" If Not StringInStr($string, "2") Then Return "2" If Not StringInStr($string, "a") Then Return "a" If Not StringInStr($string, "b") Then Return "b" Return -1 EndFunc @iEvKI3gv9Wrkd41u ... I missed this. ;; Just for the fun of it. MsgBox(0, 'Foobar', main()) Func main() Local Const $NL = '|' ;; @CRLF Local $aChar[4] = ["a", "b", "1", "2"] ;; locked characters -> hardcoded use in _CheckUp(). Local $iPerLoop = UBound($aChar, 1) Local $iLoops = 4 Local $sOut = '' _Recurse($sOut, $aChar, $NL, $iPerLoop, $iLoops) Return StringTrimRight($sOut, StringLen($NL)) EndFunc Func _Recurse(ByRef $sOut, ByRef Const $aChar, ByRef Const $sDelim, ByRef Const $iPerLoop, ByRef Const $iLoops, $sBuf = '', $iLoop = 0) If $iLoop = $iLoops Then _CheckUp($sOut, $sBuf, $sDelim) Else For $i = 0 To $iPerLoop -1 _Recurse($sOut, $aChar, $sDelim, $iPerLoop, $iLoops, $sBuf & $aChar[$i], $iLoop + 1) Next EndIf EndFunc Func _CheckUp(ByRef $sOut, ByRef Const $sPerm, ByRef Const $sDelim) ;; just moved out of the way of the recursion code. If StringInStr($sPerm, "aaaa") Or StringInStr($sPerm, "bbbb") Or StringInStr($sPerm, "1111") Or StringInStr($sPerm, "2222") Then Return EndIf If StringInStr($sPerm, "a") And StringInStr($sPerm, "b") And StringInStr($sPerm, "1") And StringInStr($sPerm, "2") Then $sOut &= $sPerm & $sDelim EndIf EndFuncNice use of recursion. I haven't done any speed tests with it yet. Splitting the return string will slow it down a little. Edited August 21, 2011 by czardas operator64 ArrayWorkshop
MvGulik Posted August 19, 2011 Posted August 19, 2011 Nice use of recursion. I haven't done any speed tests with it yet. Splitting the return string will slow it down a little.Thanks.Neither did I, as that would not be a real fair speed test. To be fear those hard-code strings in the _checkup() function should be turned into variable data, based on the initial character array.Imagine that any adjustments in that respect will drag it down considerably. "Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions.""The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014) "Believing what you know ain't so" ... Knock Knock ...
czardas Posted August 19, 2011 Posted August 19, 2011 Thanks.Neither did I, as that would not be a real fair speed test. To be fear those hard-code strings in the _checkup() function should be turned into variable data, based on the initial character array.Imagine that any adjustments in that respect will drag it down considerably.I'll play around with it later. I want to try out a few things out of personal interest. I wonder if any of this is useful to the OP. operator64 ArrayWorkshop
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