Jump to content

_RandomExclusive UDF


 Share

Recommended Posts

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
Link to comment
Share on other sites

  • Moderators

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

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.

Link to comment
Share on other sites

  • Moderators

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.

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.

Link to comment
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
 Share

  • Recently Browsing   0 members

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