Funtime60 Posted October 11, 2018 Share Posted October 11, 2018 If the title isn't clear enough I need a way to make Random() favor certain numbers over other numbers. In my specific situation I'm populating a 2D array of undefined dimensions with (essentially) 1's and 0's, 90% 0's and 10% 1's. However, I wish to avoid having all the 1's clustered together as is theoretically possible with Random(), especially with smaller dimensions to the array. To do this I planned on generating a single variable based on surrounding cells that would weight the outcome towards one way or another. This would be essentially as simple as add all the values of adjacent cells (undefined cells would be set to zero) and the higher that variable, the more likely you would get a 0 instead of a 1. I would have then looped through this process until I had the desired number of 1's. At the end of all this planning I realized. I have absolutely no clue as to how I would cause an effect on Random() with a variable. Thank you for your time and any contributions you can make. I'm sorry if I missed an obvious solution. Link to comment Share on other sites More sharing options...
Funtime60 Posted October 11, 2018 Author Share Posted October 11, 2018 I may have solved my own problem, but I do not have the time to test it now so I'll post an update if this works. Instead of Random(0,1,1) I'd use Random($min,$max,1) with $min likely being 0 and $max being many times 1, like 1000 or something Then use something like $min = 0 $max = 1 $mult = 1000 $modmax = ($mult*$max) - $bias Round(Random($min,$maxmod,1)/$mult) $bias would be the variable mentioned in my original question and how much weight it was given could be tweaked by adjusting the value of $mult This should result in a "random" number that is less likely to be close to the $max value but could also be reversed to result in a number further from the $min value. This still isn't perfect as it needs methods to prevent $bias from being out of bounds. In my example out of bounds would be if $bias is less than $min or greater than $max. As I said above I plan on posting the results of my tests and possibly a function that can do this operation. That is if one of you amazing forum members doesn't beat me to it while I sleep. Link to comment Share on other sites More sharing options...
mikell Posted October 11, 2018 Share Posted October 11, 2018 3 hours ago, Funtime60 said: 90% 0's and 10% 1's This requirement makes the use of Random difficult Suggestion : #Include <Array.au3> ; first populate the array with 90% 0 and 10% 1 Local $array[100] For $i = 0 to 89 $array[$i] = 0 Next For $i = 89 to 99 $array[$i] = 1 Next ; then shuffle the array _ArrayShuffle($array) _ArrayDisplay($array) FrancescoDiMuro 1 Link to comment Share on other sites More sharing options...
jchd Posted October 11, 2018 Share Posted October 11, 2018 4 hours ago, Funtime60 said: I'm populating a 2D array of undefined dimensions with (essentially) 1's and 0's, 90% 0's and 10% 1's. ; Number of rows and counter of ones Local $i_01 = Random(1000, 100000, 1), $i_1 ; Declare 2D array with a number of columns Local $a[$i_01][Random(1, 7, 1)] ; Populate 90% zeroes and 10% ones while counting ones For $i = 0 To $i_01 - 1 $a[$i][0] = Int(Random(0, 9, 1) / 9) If $a[$i][0] Then $i_1 += 1 Next ; check ratio ConsoleWrite($i_01 & " entries: " & $i_01 - $i_1 & " zeroes and " & $i_1 & " ones (" & Round($i_1 * 100 / $i_01, 2) & "%)" & @LF) 4 hours ago, Funtime60 said: However, I wish to avoid having all the 1's clustered together as is theoretically possible with Random() Then this isn't [pseudo]random at all. Even with a 90/10 ratio (or 9999/1 or whatever ratio you can choose), a random array perfectly could have all 0 or all 1, without violating any randomness assumption. Same for any number of consecutive invokation to some PRNG. If you want he "neighbourness" of 1's to follow some law you must make it somehow explicit for it to be modelisable by code. The bold part of the quotation is way too vague to represent anything close to a specification. May I ask what's the use of this ad hoc distribution? 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 hereRegExp tutorial: enough to get startedPCRE 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 More sharing options...
Davidowicza Posted October 11, 2018 Share Posted October 11, 2018 There are many ways to do this. Another way could be this: #include <Array.au3> $i = random(1, 1000, 1) local $array[$i] for $x = 0 to ($i - 1) $p = Random(0, 1000, 1) if $p > 900 Then $array[$x] = 1 $x = $x+1 $array[$x] = 0 else $array[$x] = 0 EndIf Next _ArrayDisplay($array) It gives 1s a 10% to show up but forces them to never be next to one another, but as jchd said, there still is a possibility of the array to be all 0s. Just what you get from pure randomness. Link to comment Share on other sites More sharing options...
Funtime60 Posted October 11, 2018 Author Share Posted October 11, 2018 (edited) I just want to say that my potential solution IS a solution to my problem and I apologize for my delayed response. I'm sorry I don't understand some of what you meant jchd. My use for this is a Minefield generator for a Mine Sweeper clone that I decided to make because I was bored. I'm sorry if I didn't use the correct terminology, I hope this more precise target can clear up my goal. I wish to reiterate that I have solved my own problem so try to come up with your solution only if you feel like that's how you want to spend your time. This is what I came up with. It will us my "not actually random biased random" function to generate a minefield like those in minesweeper. expandcollapse popup#include <Array.au3> Local $outmask = _GenMask(10,10) Local $outfield = _GenField($outmask) _ArrayDisplay($outfield) Func _GenMask($xsiz, $ysiz, $count = "Default") Local $mask[$xsiz][$ysiz] Local $masksize = $xsiz * $ysiz If $count = "Default" Then Local $minepop = Round($masksize * .1) Else Local $minepop = $count EndIf Local $minecount = 0 Local $tmpminecount = 0 While $minecount < $minepop For $xcount = 0 To $xsiz - 1 For $ycount = 0 To $ysiz - 1 If $minecount < $minepop Then If $ycount = 0 Then If $xcount = 0 Then Local $minesurround = 0 Else Local $minesurround = $mask[$xcount-1][$ycount] EndIf Else If $xcount = 0 Then Local $minesurround = $mask[$xcount][$ycount-1]+$mask[$xcount+1][$ycount-1] ElseIf $xcount = $xsiz - 1 Then Local $minesurround = $mask[$xcount-1][$ycount-1]+$mask[$xcount][$ycount-1]+$mask[$xcount-1][$ycount] Else Local $minesurround = $mask[$xcount-1][$ycount-1]+$mask[$xcount][$ycount-1]+$mask[$xcount+1][$ycount-1]+$mask[$xcount-1][$ycount] EndIf EndIf If _RandBias(0,1,$minesurround+$tmpminecount,100,6) <> 0 Then $mask[$xcount][$ycount] = 1 $minecount += 1 $tmpminecount += 1 Else $tmpminecount -= 0.1 EndIf EndIf Next Next WEnd Return($mask) EndFunc Func _GenField($amask) Local $xsiz = UBound($amask, 1) Local $ysiz = UBound($amask, 2) Local $afield[$xsiz][$ysiz] For $xcount = 0 To $xsiz - 1 For $ycount = 0 To $ysiz - 1 If $amask[$xcount][$ycount] = 1 Then $afield[$xcount][$ycount] = "*" Else If $ycount = 0 Then If $xcount = 0 Then Local $minesurround = $amask[$xcount+1][$ycount]+$amask[$xcount][$ycount+1]+$amask[$xcount+1][$ycount+1] ElseIf $xcount = $xsiz - 1 Then Local $minesurround = $amask[$xcount-1][$ycount]+$amask[$xcount-1][$ycount+1]+$amask[$xcount][$ycount+1] Else Local $minesurround = $amask[$xcount-1][$ycount]+$amask[$xcount+1][$ycount]+$amask[$xcount-1][$ycount+1]+$amask[$xcount][$ycount+1]+$amask[$xcount+1][$ycount+1] EndIf ElseIf $ycount = $ysiz - 1 Then If $xcount = 0 Then Local $minesurround = $amask[$xcount][$ycount-1]+$amask[$xcount+1][$ycount-1]+$amask[$xcount+1][$ycount] ElseIf $xcount = $xsiz - 1 Then Local $minesurround = $amask[$xcount-1][$ycount-1]+$amask[$xcount][$ycount-1]+$amask[$xcount-1][$ycount] Else Local $minesurround = $amask[$xcount-1][$ycount-1]+$amask[$xcount][$ycount-1]+$amask[$xcount+1][$ycount-1]+$amask[$xcount-1][$ycount]+$amask[$xcount+1][$ycount] EndIf Else If $xcount = 0 Then Local $minesurround = $amask[$xcount][$ycount-1]+$amask[$xcount+1][$ycount-1]+$amask[$xcount+1][$ycount]+$amask[$xcount][$ycount+1]+$amask[$xcount+1][$ycount+1] ElseIf $xcount = $xsiz - 1 Then Local $minesurround = $amask[$xcount-1][$ycount-1]+$amask[$xcount][$ycount-1]+$amask[$xcount-1][$ycount]+$amask[$xcount-1][$ycount+1]+$amask[$xcount][$ycount+1] Else Local $minesurround = $amask[$xcount-1][$ycount-1]+$amask[$xcount][$ycount-1]+$amask[$xcount+1][$ycount-1]+$amask[$xcount-1][$ycount]+$amask[$xcount+1][$ycount]+$amask[$xcount-1][$ycount+1]+$amask[$xcount][$ycount+1]+$amask[$xcount+1][$ycount+1] EndIf EndIf If $minesurround > 0 Then $afield[$xcount][$ycount] = $minesurround EndIf EndIf Next Next Return($afield) EndFunc Func _RandBias($min, $max, $bias = 0, $mult = 100, $AvoExp = 1) Local $modmax = ($mult*$max) - $bias^$AvoExp Return(Round(Random($min,$modmax)/$mult)) EndFunc Edited October 11, 2018 by Funtime60 Poor choice of words, Defined Word1 using Word1 Link to comment Share on other sites More sharing options...
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