Jump to content

Random number with certain number of occurrences?


Recommended Posts

I want to random a natural number between 0 and 3, and calculate the number of appearances of each number. If the number 1 appears 60 times (for example) then the next times exclude the number 0 (i.e. randomize one of the numbers 0, 2, 3).

Can anyone help me about this?

Thanks all!

Link to comment
Share on other sites

What have you tried so far?
AutoIt's Random function allows to set the lower and upper boundary. So if you want to remove the lower or upper number from the range then this function is fine.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

If you want a non-flat distribution, that isn't anything close to "random".

So the actual question is: which kind of distribution do you want? Normal, Poisson, what else?

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

#include <Array.au3>

_ArrayDisplay(__RandomNo(33, 38))
Func __RandomNo($o_Min, $o_Max)
    Local $o_Occurrence = 5                             ;~ appearances
    Local $o_Random_Number = ''
    Local $o_totalNumber = ($o_Max - $o_Min)
    Local $o_Digit = ''
    For $i = $o_Min To $o_Max
        $o_Digit &= $i & '|'
    Next
    $o_Digit = StringTrimRight($o_Digit, 1)
    $o_Digit = StringSplit($o_Digit, '|', 2)
    _ArrayColInsert($o_Digit, 1)
;   _ArrayDisplay($o_Digit, 1)

    Local $o_Number
    Local $o_Check
    Do
        $o_Number = Random(0, $o_totalNumber, 1)
        $o_Random_Number &= $o_Digit[$o_Number][0] & '|'      ;~ <<== random number generator
        $o_Digit[$o_Number][1] += 1
        $o_Check = _ArraySearch($o_Digit, $o_Occurrence, 0, 0, 0, 0, 1, 1)
        If $o_Check <> -1 Then
           ConsoleWrite('Delete No: ' & $o_Digit[$o_Check][0] & @crlf)
;           _ArrayDisplay($o_Digit, 1)
            _ArrayDelete($o_Digit, $o_Check)            ;~ delete number if appears / occur 5 times
;           _ArrayDisplay($o_Digit, 1)
            $o_totalNumber -= 1
        EndIf
    Until $o_totalNumber = 0
    ConsoleWrite('last No:   ' & $o_Digit[0][0] & @crlf)

    $o_Random_Number &= $o_Digit[0][0]
    ConsoleWrite($o_Random_Number & @crlf)
    Return StringSplit($o_Random_Number, '|', 2)
EndFunc

 

Edited by jugador
Link to comment
Share on other sites

I think this problem cannot be solved by adjusting Random() parameters, choosing a specific fixed probability distribution, or array scrubbing after the fact. It looks to me that the OP requires a dynamically adjusted index sampling probability, like so:

Global $newInt, $index=0
Global Const $total = 4
Global $integers[$total] = [0, 1, 2, 3]

Global $countInts[$total]
For $rc = 0 to $total-1
    $countInts[$rc] = 0
Next

_GetSampledIndex($total, 0, True)   ; intialise the sampler

Global $adjust = 0  ; strength of outlier suppression
Global $sampleSize = 100

For $rc = 1 to $sampleSize
    $index = _GetSampledIndex($total, $adjust)
    $countInts[$index]+=1
;   $newInt = $integers[$index] ; just for illustration
Next

For $rc = 0 to $total-1
    ConsoleWrite("Integer: " & $rc & @TAB & "Count: " & $countInts[$rc] & @TAB & "Proportion: " & $countInts[$rc]/$sampleSize & @CRLF)
Next


Func _GetSampledIndex($size, $bias, $init = False)
    Static $sum = $size
    Static $count[$size]
    Local $cumulprop[$size]

    If Not $init Then   ; most likely case first
        $sum+=1
    Else
        SRandom(@AutoItPID + @MSEC)
        For $cc = 0 to $size-1
            $count[$cc] = 1
        Next
        Return -1   ; invalid index (do not use)
    EndIf

    Local $prop, $cumul = 0
    For $cc = 0 to $size-1
        $prop = ($sum-1) / ((1 + Abs($bias)) * $count[$cc])
        $cumul += $prop
        $cumulprop[$cc] = $cumul
    Next

    Local $lowerBound=0, $value = Random(0,$cumul)
    For $cc = 0 to $size-2
        If ($value>=$lowerBound) And ($value<$cumulprop[$cc]) Then
            $count[$cc] += 1
            Return $cc
        EndIf
        $lowerBound = $cumulprop[$cc]
    Next

    $count[$cc] += 1
    Return $cc
EndFunc

Increasing the bias parameter $adjust (>0) will impose a stronger constraint on the likelihood of departures from equal sampling. Of course, the smaller the sample size, the higher the likelihood of departures from equal sampling.

Edited by RTFC
count array in func was declared local instead of Static
Link to comment
Share on other sites

I add another half cent
in the proposed script, place the items to select in the first column of the $aMyData array and the maximum allowed number of times an item can be read in the second column. To unrestrict an item, leave the second column of that item blank.
For example I filled the first column with the names of major cities (but you can enter anything, numbers or strings) and the second column with random limits just to show the effect (the reading "statistic" is visually displayed in the form of a histogram).
The _CustomRandom() function will return random data taken from the first column respecting the limits set in the second column.
When and if no data can be returned without violating the bounds, empty data is returned and @error is set.
I hope there are no bugs ...

#include <GUIConstantsEx.au3>
#include <array.au3>

_Example()

Func _Example()
    ; --- enter the data in the first column and the limit (if any) in the second ---
    Local $aMyData = [ _
            ['Tokyo', 11], _
            ['Delhi', 3], _
            ['Shanghai', 17], _
            ['Dhaka', 22], _
            ['Sao Paulo', 9], _
            ['Mexico City', 15], _
            ['Cairo', 10], _
            ['Beijing', 7], _
            ['Mumbai', 1], _
            ['Osaka', 4], _
            ['Chongqing', 8], _
            ['Karachi', 18], _
            ['Kinshasa', 20], _
            ['Lagos', 9], _
            ['Istanbul', 6], _
            ['Buenos Aires', 12], _
            ['Kolkata', 4], _
            ['Manila', 13], _
            ['Guangzhou', 16], _
            ['Tianjin', 2] _
            ]
    ; --- DO NOT CHANGE THE LINES BELOW -------------------------------------------------
    ; automatically adjust and create the necessary variables ---
    ReDim $aMyData[UBound($aMyData)][3] ; create a new column in Data array (for the counters)
    Local $aMyDataNdxs[UBound($aMyData)] ; create data array's index
    ; fill the indexes array with initial indexes
    For $i = 0 To UBound($aMyDataNdxs) - 1
        $aMyDataNdxs[$i] = $i
    Next
    ; --- DO NOT CHANGE THE ABOVE LINES -------------------------------------------------

    Local $hDisplay = GUICreate("number of times read", 305, 300)
    Local $hList = GUICtrlCreateLabel('', 5, 5, 300, 270)
    Local $hData = GUICtrlCreateLabel('', 5, 275, 300, 15)
    Local $vData = ''
    Local $iError
    GUISetState()

    Do
        $idMsg = GUIGetMsg()
        Select
            Case $idMsg = $GUI_EVENT_CLOSE
                MsgBox($MB_SYSTEMMODAL, '', "Dialog was closed")
                ExitLoop
        EndSelect

        $vData = _CustomRandom($aMyData, $aMyDataNdxs)
        $iError = @error
        ControlSetText('', '', $hData, $vData)
        $aIstogram = _Array1DToHistogram(_ArrayExtract($aMyData, -1, -1, 2, 2))
        ControlSetText('', '', $hList, _ArrayToString($aIstogram, @CRLF))

    Until $iError
    MsgBox(0, '', "End")
EndFunc   ;==>_Example

Func _CustomRandom(ByRef $aData, ByRef $aDataNdxs)
    Local $iReturn
    Static Local $iUbound = UBound($aDataNdxs) - 1

    If $iUbound = -1 Then Return SetError(1, 0, '')
    SRandom(@MSEC)
    $iRndPeek = Random(0, $iUbound, 1)
    If Not IsNumber($aData[$aDataNdxs[$iRndPeek]][1]) Or ($aData[$aDataNdxs[$iRndPeek]][2] < $aData[$aDataNdxs[$iRndPeek]][1]) Then
        $aData[$aDataNdxs[$iRndPeek]][2] += 1
        $iReturn = $aData[$aDataNdxs[$iRndPeek]][0]
    Else
        _ArraySwap($aDataNdxs, $iRndPeek, $iUbound)     ; place this element out of bound
        $iUbound -= 1     ; adapt the new bound
        If $iUbound > -1 Then $iReturn = $aData[$aDataNdxs[$iUbound]][0]
    EndIf

    Return SetError($iUbound < 0, 0, $iReturn)
EndFunc   ;==>_CustomRandom

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

not relate to Op request
@Gianni use of _Array1DToHistogram good
so for fun

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiRichEdit.au3>
#include <Array.au3>

__ExampleA()
Func __ExampleA()
    Local $o_DataArray = __Random_Data(1990, 2023)
    If @error Then Return
    __AddColor($o_DataArray)
;   _ArrayDisplay($o_DataArray)

    ;~========
    Local $o_text
    Local $o_width = 320
    Local $o_Height = UBound($o_DataArray) * 15
    Local $hDisplay = GUICreate("Programing Language User", $o_width, $o_Height)
    Local $hList = _GUICtrlRichEdit_Create($hDisplay, '', 5, 5, $o_width - 10, $o_Height - 10, BitOR($ES_MULTILINE, $ES_READONLY), $WS_EX_TRANSPARENT)
    GUISetState()

    Local $o_ColmName = UBound($o_DataArray, 2) - 2
    Local $o_ColmColor  = UBound($o_DataArray, 2) - 1
    For $i = 0 To UBound($o_DataArray, 2) - 3   ;~ last 2 column contain name & color
        $o_text = __GetColumn($o_DataArray, $i, $o_ColmName, $o_ColmColor, $o_width - 85)
        _GUICtrlRichEdit_SetSel($hList, 0, -1, True)
        _GUICtrlRichEdit_ReplaceText($hList, '')
        For $k = 0 To UBound($o_text) - 1
            _GUICtrlRichEdit_SetCharColor($hList, $o_text[$k][2])
            _GUICtrlRichEdit_AppendText($hList, $o_text[$k][0] & '  ' & $o_text[$k][1] & (($k = UBound($o_text) - 1) ? '' : @crlf))
        Next
        Sleep(250)
    Next

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
        Sleep(10)
    WEnd

    _GUICtrlRichEdit_Destroy($hList)
    GUIDelete($hDisplay)
    ;~========
EndFunc

Func __GetColumn(ByRef $o_Array, $o_ValueColm, $o_NameColm, $o_ColorColm, $o_Sizing = 100)
    Local $o_Data[UBound($o_Array)][3]
    For $i = 0 To UBound($o_Array) - 1
        For $k = 0 To UBound($o_Array, 2) - 1
            If $k = $o_ValueColm Then $o_Data[$i][0] = $o_Array[$i][$k]
            If $k = $o_NameColm Then $o_Data[$i][1] = $o_Array[$i][$k]
            If $k = $o_ColorColm Then $o_Data[$i][2] = $o_Array[$i][$k]
        Next
    Next

    _ArraySort($o_Data, 1, 0, 0, 0)

    Local $aExtValue = _ArrayExtract($o_Data, -1, -1, 0, 0)
    $aExtValue = _Array1DToHistogram($aExtValue, $o_Sizing)

    For $i = 0 To UBound($o_Data) - 1
        $o_Data[$i][0] = $aExtValue[$i]
    Next
    Return $o_Data
EndFunc

Func __AddColor(ByRef $o_Array)
    _ArrayColInsert($o_Array, UBound($o_Array, 2))
    Local $o_LastColmn = UBound($o_Array, 2) - 1
    For $i = 0 To UBound($o_Array, 1) - 1
        $o_Array[$i][$o_LastColmn] = Random(0, 0xFFFFFF, 1)
    Next
EndFunc

Func __Random_Data($o_StartY, $o_EndY)
    If ($o_StartY >= $o_EndY) Then Return SetError(1)
    Local $o_Language = ['C', 'C++', 'C#', 'Java', 'Python', 'Ruby', 'PHP', 'Go', 'Kotlin', 'Swift', 'VB.Net', 'Perl']
    Local $o_Data[UBound($o_Language)][($o_EndY - $o_StartY) + 2]
    For $i = 0 To ($o_EndY - $o_StartY) + 1
        For $k = 0 To UBound($o_Data) - 1
            If $i = 0 Then $o_Data[$k][$i] = Random(1, 50, 1)
            If $i > 0 Then $o_Data[$k][$i] = Random(1, 50, 1) + $o_Data[$k][$i - 1]
            If $i > ($o_EndY - $o_StartY) Then $o_Data[$k][$i] = $o_Language[$k]
        Next
    Next
;   ConsoleWrite(_ArrayToString($o_Data, @tab, -1, -1, @CRLF) & @crlf)
    Return $o_Data
EndFunc

 

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