View Full Version : Random number
Michael Clease
02-06-2008, 14:52
I am looking for a fast way to produce a sequence of random numbers that dont repeat and in a specified range.
ie. 1,4,6,9,2... you get the idea
I will post what I am doing later tonight when I get home, I would be interested to see different ways of doing it.
thanks
Mike
Petr Schreiber
02-06-2008, 18:56
Hi Mike,
this is very dumb version, not very optimized ... but works :)
Petr
dim Numbers(1) as long
if Generate( Numbers, 10, 1, 10 ) = %TRUE then
msgbox 0, "Generated:"+$CRLF+join$(Numbers, ",")
else
msgbox 0, "Error ocurred"
endif
function Generate( byref arr() as long, xNumbers as long, nFrom as long, nTo as long )
local i as long
local f as long
' -- Make sure the array is properly dimensioned
if ubound(arr) <> xNumbers then
redim arr(xNumbers)
endIf
' -- Check if it is possible to generate such a series
if xNumbers > nTo-nFrom+1 then
msgbox 0, "Nice try, but impossible :)"
Return %FALSE
endIf
' -- Fill array with the numbers
for i = 1 to xNumbers
arr(i) = rnd(nFrom, nTo)
if i > 1 then ' -- Check if value was already used
f = 1
do
f = array scan arr(1) for i-1, =arr(i)
if f = 0 then exit do
arr(i) = rnd(nFrom, nTo)
loop
endIf
next
Return %True
end function
Here is my version Mike.
Used logic from this site:
http://www.techuser.net/randpermgen.html
Uses "Console"
Dim I, N, R As Long
N = 10
Dim Ar(N) As Long
'--- fill and array in order
For I = 1 To N
Ar(I) = I
Print Str$( Ar(I) ) + $Crlf
Next
Print $Crlf + $Crlf
'--- then rearrange that order randomly
For I = 1 To N
R = Rnd(I,N)
Swap Ar(I),Ar(R)
Print Str$( Ar(I) ) + $Crlf
Next
Console_Writeline($Crlf + "Press Any Key To End.")
Console_Waitkey
Petr Schreiber
02-06-2008, 19:11
Nice one Kent!,
that is really smart, and completely eliminates check like "did I generated this already?" :)
Little mod of your code, to handle situation like "I want 3 numbers from range 1 to 10":
Dim Numbers(1) as long
Generate(Numbers, 3, 1, 10)
msgbox 0, "Generated:"+Join$(Numbers, ",")
sub Generate( byref arr() as long, xNumbers as long, nFrom as long, nTo as long )
local i, r as long
Local iMax as long = nTo-nFrom+1
redim arr(iMax)
' -- Fill in all numbers
for i = nFrom to nTo
arr(i-nFrom+1) = i
next
' -- Rearrange
For i = 1 To iMax-1
r = Rnd(i,iMax)
Swap arr(i),arr(r)
Next
' -- In case we need less numbers than range
if iMax > xNumbers then reDim Preserve arr(xNumbers)
end sub
This code can be 10x faster than my original version, only in rare cases it is slower.
Good work!,
Petr
Good addition Petr! You are always thinking, thanks for sharing!!
Petr Schreiber
02-06-2008, 19:29
I am sure it could be boosted up by replacing:
for i = nFrom to nTo
arr(i-nFrom+1) = i
next
... with O2 or Asmosphere :)
Petr
Kent:
I was unable to get your version running because under the copy of thinBasic 1.6.0.8 I am running, the"PRINT" alias for "Console_WriteLine" does not seem to be working. After I replaced the PRINT statements in your code with Console_WriteLine statements it worked fine. What version of thinBasic are you using?
Don
Hmmmm, I don't know why as I have the same version. Maybe Eros or Roberto can figure it out.
I am using the latest preview version if that could be it?
Petr Schreiber
02-06-2008, 21:34
Hi GSAC3,
PRINT is there since version 1.6.0.6... so that is odd.
Try to put following:
#minversion 1.6.0.8
on the first line of the script. If it passes, it might be because of different Win98/NT version of Console module, but that is wild guess.
Petr
Michael Clease
02-06-2008, 22:27
I have seperated the section of code I was talking about.
Here are mine and Kent/Petr version for comparision.
%Numcount = 10
DIM sMsg as STRING
DIM N as WOrd VALUE = 1
DIM l(%Numcount) as LONG
DIM m(%NumCount) as LONG
DIm p,q as LONG VALUE = 1
DIM t1,t2,t3,t4 AS QUAD
dim Numbers(%NumCount) as long
'---Initialize hi resolution timer
RANDOMIZE ' reseed the radomiser
HiResTimer_Init
T1 = HiResTimer_Get
MyVersion()
T2 = HiResTimer_Get
sMsg = "Generated:"+$CRLF+join$(m, ",")+$CRLF
sMsg += "Elapsed time in microseconds: " & FORMAT$(T2-T1, "#0")
MSGBOX 0, sMSG
t3 = HIRESTIMER_GET
Generate '( Numbers, 10, 1, 10 )
t4 = HIRESTIMER_GET
sMsg = "Generated:"+$CRLF+join$(Numbers, ",")+$CRLF
sMsg += "Elapsed time in microseconds: " & FORMAT$(T4-T3, "#0")
MSGBOX 0, sMSG
stop
SUB MyVersion()
For n = 1 to (%Numcount) : l(n) = n : NEXT
DO
p = RND(1,%Numcount) ' Generate a random number
For n = 1 to %Numcount
if l(p) = 0 THEN EXIT FOR ' if the random number has been used generate a new number
m(q) = p : l(p) = 0 ' Store the random number and clear index
q += 1 ' Increase the counter
NEXT
LOOP UNTIL q => %Numcount+1
END SUB
sub Generate() '( byref arr() as long, xNumbers as long, nFrom as long, nTo as long )
local i, r as long
'Local iMax as long = nTo-nFrom+1
' -- Fill in all numbers
for i = 1 to %NumCount : Numbers(i) = i : next
' -- Rearrange
For i = 1 To %NumCount
r = Rnd(i,%NumCount)
Swap Numbers(i),Numbers(r)
Next
' -- In case we need less numbers than range
'if iMax > xNumbers then reDim Preserve arr(xNumbers)
end sub
ErosOlmi
03-06-2008, 10:08
GSAC3 problem is continuing in the following post:
http://community.thinbasic.com/index.php?topic=1813.msg13189#msg13189