Jump to content

Recommended Posts

Posted

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
  • Replies 44
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted (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 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 ...
 

Posted (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.

#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
EndFunc

Nice use of recursion. I haven't done any speed tests with it yet. Splitting the return string will slow it down a little. Edited by czardas
Posted

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 ...
 

Posted

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. :mellow:

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...