Sign in to follow this  
Followers 0
greenmachine

_RandomExclusive UDF

5 posts in this topic

I made a little UDF dealing with random numbers because I needed a file for a C++ project I'm working on in class. This UDF places random numbers in an array, checking each time if the number has already been placed (to prevent repeats), and returns the completed array.

The function works in production or beta versions. The test script will run under production (if you comment out the correct lines), and work under beta as is.

#include <array.au3>
$Rands = _RandomExclusive (52, 1, 52, 1); Example: shuffle a deck of cards (numbered 1-52)
Select
Case @error = 1
    MsgBox (0, "error " & @error, "Count is too high.")
Case @error = 2
    MsgBox (0, "error " & @error, "Min is greater than or equal to max.")
Case @error = 3
    MsgBox (0, "error " & @error, "One or more of the parameters is not a number.")
Case Else
;~  ;use these with production version
;~   $msg = $Rands[1]
;~   For $i = 2 To $Rands[0]
;~       $msg = $msg & @CRLF & $Rands[$i]
;~   Next
;~   MsgBox (0, "rands", $msg)
    
;~  ;use these with beta or an array.au3 file that does not have "const" in the _ArrayDisplay() func
    _ArrayDisplay ($Rands, "Rands before sort")
    _ArraySort ($Rands, 0, 1)
    _ArrayDisplay ($Rands, "Rands after sort")
EndSelect

;===============================================================================
;
; Function Name     : _RandomExclusive()
; Description       : Returns a quantity of random numbers in an array - does not use the same number more than once
; Parameter(s)      : $iCount - how many random numbers to get?
;                   : $iMin - [Optional] minimum number, default is 0
;                   : $iMax - [Optional] maximum number, default is 1
;                   : $iFlag - [Optional] flag for Random -> 0 is default (floats), set to 1 for ints
; Requirement       : None.
; Return Value(s)   : On Success - returns an array containing the random numbers
;                   : $Array[0] - quantity
;                   : $Array[1] through $Array[n] - random numbers
;                   : On Failure - returns -1 and sets @error to one of the following:
;                   : @error = 1 - Count is too high (only when flag is 1)
;                   : @error = 2 - Min is greater than or equal to Max
;                   : @error = 3 - One or more parameters is not a number
; Author(s)         : Michael Guynn (greenmachine)
; Note(s)           : A good way to shuffle numbers.
;
;===============================================================================



Func _RandomExclusive($iCount, $iMin = 0, $iMax = 1, $iFlag = 0)
    If $iCount > ($iMax - ($iMin - 1)) And $iFlag = 1 Then
        SetError (1)
        Return -1
    EndIf
    If ($iMin >= $iMax) Then
        SetError (2)
        Return -1
    EndIf
    If Not IsNumber ($iCount) Or Not IsNumber ($iMin) Or Not IsNumber ($iMax) Or Not IsNumber ($iFlag) Then
        SetError (3)
        Return -1
    EndIf
    Local $a_randomArray[$iCount + 1], $Rand_found
    For $Rand_counter = 1 To $iCount
        $a_randomArray[0] = $Rand_counter
        Do
            $Rand_found = 0
            $a_randomArray[$Rand_counter] = Random ($iMin, $iMax, $iFlag)
            For $Rand_subcounter = 1 To $Rand_counter - 1
                If $a_randomArray[$Rand_counter] = $a_randomArray[$Rand_subcounter] Then
                    $Rand_found = 1
                    ExitLoop
                EndIf
            Next
        Until $Rand_found = 0
    Next
    Return $a_randomArray
EndFunc

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Hey green... good job... I was toying around with this, because I had to do something similar with EnCodeIt a while back... the one without the For/Next loop seems to be a tad faster most of the time... thought I'd post it and let you test it out to see if it suited your needs for school

$Timer = TimerInit()
$TestRandomArray = _RandomExclusive(10, 1, 10, 1)
Local $Display_Array = ''
For $x = 1 To UBound($TestRandomArray) - 1
    $Display_Array = $Display_Array & '[' & $x & ']  =  ' & $TestRandomArray[$x] & @LF
Next
MsgBox(0, 'Display Array and it took: ' & Round(TimerDiff($Timer) / 1000, 3) & ' seconds', $Display_Array)
Func _RandomExclusive($iCount, $iMin = 0, $iMax = 1, $iFlag = 0)
    If $iCount > ($iMax - ($iMin - 1)) And $iFlag = 1 Then
        SetError(1)
        Return -1
    EndIf
    If ($iMin >= $iMax) Then
        SetError(2)
        Return -1
    EndIf
    If Not IsNumber($iCount) Or Not IsNumber($iMin) Or Not IsNumber($iMax) Or Not IsNumber($iFlag) Then
        SetError(3)
        Return -1
    EndIf
    Local $a_randomArray[$iCount + 1], $Rand_found
    For $Rand_counter = 1 To $iCount
        $a_randomArray[0] = $Rand_counter
        Do
            $Rand_found = 0
            $a_randomArray[$Rand_counter] = Random ($iMin, $iMax, $iFlag)
            For $Rand_subcounter = 1 To $Rand_counter - 1
                If $a_randomArray[$Rand_counter] = $a_randomArray[$Rand_subcounter] Then
                    $Rand_found = 1
                    ExitLoop
                EndIf
            Next
        Until $Rand_found = 0
    Next
    Return $a_randomArray
EndFunc

$Timer = TimerInit()
$TestRandomArray = _RandomNumDisplay(10, 1, 10, 1)
Local $Display_Array = ''
For $x = 1 To UBound($TestRandomArray) - 1
    $Display_Array = $Display_Array & '[' & $x & ']  =  ' & $TestRandomArray[$x] & @LF
Next
MsgBox(0, 'Display Array and it took: ' & Round(TimerDiff($Timer) / 1000, 3) & ' seconds', $Display_Array)
Func _RandomNumDisplay($iCount, $iMin = 0, $iMax = 1, $iFlag = 0)
    Local $Rand_Array = ''
    Local $StartCount = 0
    If $iCount > ($iMax - ($iMin - 1)) And $iFlag = 1 Then
        SetError(1)
        Return -1
    EndIf
    If ($iMin >= $iMax) Then
        SetError(2)
        Return -1
    EndIf
    If Not IsNumber($iCount) Or Not IsNumber($iMin) Or Not IsNumber($iMax) Or Not IsNumber($iFlag) Then
        SetError(3)
        Return -1
    EndIf
    Do
        $StartCount = $StartCount + 1
        $Rand_Number = Random($iMin, $iMax, $iFlag)
        If Not StringInStr(Chr(01) & $Rand_Array, Chr(01) & $Rand_Number & Chr(01)) Then 
            $Rand_Array = $Rand_Array & $Rand_Number & Chr(01)
        Else
            $StartCount = $StartCount - 1
        EndIf
    Until $StartCount = $iCount
    Return StringSplit(StringTrimRight($Rand_Array, 1), Chr(01))
EndFunc
Edit: Rounded the timer of 2 3 decimals. Edited by SmOke_N

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

You're right, yours is much faster. I'm still trying to figure out what it's doing though.. the added chr(01)'s are throwing me off.

Share this post


Link to post
Share on other sites

The Chr(01) is simply the 'delimeter' that StringSplit() will use to create the array. I use Chr(01) alot because it's not a common delimeter that you'll see when parsing strings to create an array. Unlike @LF or other Delimters that you'd run into often. If your trying to keep the array unique, you want the type of delimter that is also unique.


[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

Yeah I figured out that you were using it as a delimeter, it was just weird because (like you said) it isn't used much. I didn't know what it was either, so I looked it up. According to www.lookuptables.com, it's a "start of heading".

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