PDA

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

kryton9
02-06-2008, 19:05
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

kryton9
02-06-2008, 19:25
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

GSAC3
02-06-2008, 20:23
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

kryton9
02-06-2008, 21:14
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