I have an array with 250 entries. Every time my function is called I need to
display the 250 entries in a random order. Every time the order needs to be
different, but I need to show all and each one exactly one time.
(Working with Xbase++ and XB2.NET)
Any ideas ?
Thanks for your input !
Stephan
for i = 1 to 250
? A[I[i]]
next
--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Include the date, time, secs, millisecs so it will be always unique.
We do our ID's the following way in tables.
YYMMDDSSSSSRRRRR
YY = Year [08]
MM = Month [06]
DD = Day [06]
SSSSS = Seconds from midnight 02:14:21 --> 2 * 3600 + 14*60 + 21
RRRRR = Record number when appended
So we can safely create 99999 records with unique ID's in 1 second.
Offcoarse you can keep a counter for this.
--
Grtz, Marc
"Joe Wright" <joeww...@comcast.net> schreef in bericht
news:CsSdnWSoqtkFU9TV...@comcast.com...
How would you shuffle if ?
Marc,
thanks. I am very familiar with adding date and time etc. But that does not
make it random. Also, its a web application and the xbase thread could be
called by many at the same time.
Date and time makes a seqence, but its always the same.
Each time the routine is called, I need to display ALL record, just in a
unique random sequence.
Thanks for all hints
Stephan
"Stephan Koenig" <S.Ko...@LaserPlus.de> wrote in message
news:484a73a4$0$7033$4c36...@roadrunner.com...
>
>> Include the date, time, secs, millisecs so it will
>> be always unique.
>
> thanks. I am very familiar with adding date and
> time etc. But that does not make it random.
> Also, its a web application and the xbase thread
> could be called by many at the same time.
You may want to review this thread...
http://www.dbforums.com/archive/index.php/t-554739.html
> Date and time makes a seqence, but its always
> the same.
Yes, I recall the various Basic versions had a "randomize"
function you could call, that would "mix things up a bit".
> Each time the routine is called, I need to display
> ALL record, just in a unique random sequence.
Define Array_Hits, Array_Records
Loop to generate random numbers in range
Is random number in Array_Hits?
If no,
populate Array_Hits position with true,
populate next Array_Records position with this number
endif
Try again, until Array_Records is filled.
David A. Smith
The following takes the 250 strings in an array and "mixes things up a
bit" :-)
"aardvark"
// --------------------------------------------------------------
FUNCTION Main()
LOCAL aTest := array(250)
LOCAl nTmp
FOR nTmp := 1 TO 250
aTest[nTmp] := str(nTmp,3)
NEXT
DO WHILE .T.
aTest := Shuffle(aTest)
FOR nTmp := 1 To 250
IF col() > 76
? aTest[nTmp] + ","
ELSE
?? aTest[nTmp] +","
ENDIF
NEXT
?
? "Press an key to Reshuffle or [Esc] to quit."
?
IF inkey(0) == 27
EXIT
ENDIF
ENDDO
RETURN
FUNCTION Shuffle(aInput)
LOCAL aOutput := {}
LOCAl nLen
LOCAL nTmp
DO WHILE .T.
nLen := len(aInput)
IF nLen < 2
EXIT
ENDIF
nTmp := NearlyRdm(nLen)
aadd(aOutput, aInput[nTmp])
adel(aInput, nTmp)
asize(aInput, nLen-1)
ENDDO
aadd(aOutput, aInput[1])
RETURN aOutput
FUNCTION NearlyRdm(nMax)
STATIC cSeed
LOCAL nReturn
LOCAL nMixMeth
LOCAL nMix
IF cSeed == nil
cSeed := str(seconds() + 1000000,7)
ENDIF
nReturn := val(cSeed) % nMax + 1
nMixMeth := int(val(left(cSeed,1))/3)
DO CASE
CASE nMixMeth == 0
nMix := nReturn
CASE nMixMeth == 1
nMix := val(right(str(seconds() + 1000000,7),1))
CASE nMixMeth == 2
nMix := asc(substr(cSeed,2,1))
OTHERWISE
nMix := 999 - asc(substr(cSeed,2,1))
ENDCASE
cSeed += ltrim(str(nMix, 15))
cSeed := right(cSeed, 7)
RETURN nReturn
// --------------------------------------------------------------
Untested code follows - I just entered it into the message
// From the link David supplied - routine by Ross McKenzie
Function Tam_num( a, b )
Return ( min( a, b ) + Ft_Rand1( max( a, b) - min( a, b) ) )
nSize := 250
ar1 := array(2,nSize)
// Element 1 is the sort order
// Element 2 is your data
do while true
// Fill array with your data (element2)
enddo
// sort the array
Shuffle( ar1 )
On subsequent calls all you need is
function shuffle( anArray )
local nSize := alen(anArray)
for i := 1 to nSize
anArray[nCount][1] := Tam_num( 1, nSize )
next
asort( anArray, {|x| x[1] < x[1] } )
return
CYA
Steve
Sorry a coupe of mixups
alen() should be len() // alen() is VO
i should be nCount
function shuffle( anArray )
local nSize := LEN( anArray )
local nCount
for nCount := 1 to nSize
anArray[ nCount ][1] := Tam_num( 1, nSize )
next
ASORT( anArray, {|x| x[1] < x[1] } )
return
CYA
Steve
>I have an array with 250 entries. Every time my function is called I need to
>display the 250 entries in a random order. Every time the order needs to be
>different, but I need to show all and each one exactly one time.
Here is a slightly different approach to this weekend's puzzle <g>
I liked Joe's idea to create a separate index and use it when deciding
in which order to display the array items. It can also be applied on
records in a table:
dbgoto( aIndex[i] )
? somefield
or on separate text files with sequential numbers in the file names:
cFileName := 'FileWithNumber' +;
strtran( str( aIndex[i], 4 ), ' ', '0' ) + '.txt.
cText := LF_MemoRead( cFileName )
? cText
Sorry, I just _had_ to make that a long file name <g>.
In the old thread that David looked up, and that some of us were
involved in back in 2002, Ross McKenzie responded to T M Tam's request
for random numbers between nMin and nMax and wrote a wrapper for the
Nanforum function FT_Rand1() that he called Tam_num() (for those who
didn't look it up, that explains the unusual name of the function
Steve quoted). But for this purpose we just need the raw random number
so I have skipped Tam_num() (sorry Ross, but we'll get back to you
when we need you again <g>). I also took the liberty to borrow the
core of FT_Rand1() and reuse it my function. Gary Baren wrote
FT_Rand1() for nanfor.lib using the Linear Congruential Method.
Here is my suggestion. It begins with a little test routine. Compile
it with /n, pass a number <=4096 on the commandline and redirect the
result to a text file to examine the result.
//---
function randtest( cNum )
local i, aIndex, nHowMany := val( cNum )
aIndex := RandomIndex( nHowMany )
for i := 1 to len( aIndex )
outstd( i, aIndex[ i ], chr(13) + chr(10) )
// Then apply aIndex[i] to the array of text items
next
return NIL
//---
function RandomIndex( nHowMany )
// Create a randomly sorted array of integers between 1 and
// <nHowMany> (inclusive). All integers in the interval will
// appear exactly once. The random generator was borrowed
// from Gary Baren's FT_Rand1() function in the Nanforum Toolkit
static nSeed
local m := 100000000, b := 31415621, i, j
local aArr1 := array( nHowMany )
local aArr2 := array( nHowMany )
// Insert argument check here
nSeed := iif( nSeed == NIL, seconds(), nSeed )
for i := 1 to nHowMany
j := ( nSeed := mod( ( nSeed * b ) + 1, m ) ) / m
aArr1[ i ] := { i, j }
next
asort( aArr1,,, { |x,y| x[2] < y[2] } )
for i := 1 to nHowMany
aArr2[ i ] := aArr1[ i, 1 ]
next
return aArr2
//---
Regards,
Klas
-------
klas dot engwall at engwall dot com
http://www.engwall.com/clipper/
The LFN Library for Clipper
The LanMan Library for Clipper
The NFPAT1A Timeslice release patch for the Nanforum Toolkit
Klas,
I am so sorry. As I said in my inital post, I am working with xbase++
Stephan
>> Sorry, I just _had_ to make that a long file name <g>.
>
>Klas,
>
>I am so sorry. As I said in my inital post, I am working with xbase++
Nothing to be sorry about, that was just an example of how it can be
used. The actual RandomIndex() function is plain and simple Clipper
code and should work in any xBase environment. And the RandTest()
function too if you make it a console app. Just compile the code I
posted and see what happens. Or change RandTest() to something that
works in Xbase++ GUI mode to display the array returned from
RandomIndex()
> (sorry Ross, but we'll get back to you when we need you again <g>).
>
>Regards,
>Klas
Thanks Klas,
Pleased to see that I am not forgotten entirely even when I slow down
on my postings.
Regards,
Ross McKenzie
ValuSoft
Melbourne Australia
valusoft AT optusnet DOT com DOT au
>> (sorry Ross, but we'll get back to you when we need you again <g>).
>>
>>Regards,
>>Klas
>
>Thanks Klas,
>
>Pleased to see that I am not forgotten entirely even when I slow down
>on my postings.
My comment was intended as a test to see if you were close enough to
feel the vibes when we talked about you <g>. I am pleased to see that
it worked.
Function ArrayRandom(aInArray)
*Returns randomized array
*Usage Newarray= ArrayRandom(Yourarray)
local nArraylen:=0
local i:=0
local aOutArray:={}
local aOrder:={}
local aOrder1:={}
local nNewvalue:=0
* only if array
if VALTYPE(aInArray) ="A"
*have array initialize
nArraylen = Len(aInArray)
aOutArray = ARRAY(nArraylen)
aOrder = ARRAY(nArraylen)
aOrder1 = ARRAY(nArraylen)
*rem populate order
for i = 1 to nArraylen
aOrder[i]=0
aOrder1[i]=i
next i
*randomize
for i = 1 to nArraylen
Do while aOrder[i]=0
nNewvalue = int(ft_rand1(nArraylen))+1
if (aOrder1[nNewvalue] <> 0) .and. (i != nNewvalue)
*not used and not same
aOrder[i]= nNewvalue
aOrder1[nNewvalue]= 0
Endif
Enddo
next i
* rem copy new order
for i = 1 to nArraylen
aOutArray[i] = aInArray[ aOrder[i]]
next i
endif
Return aOutArray
*from Nanforum 305
function ft_rand1(nMax)
static nSeed
local m := 100000000, b := 31415621
nSeed := iif( nSeed == NIL, seconds(), nSeed ) // init_seed()
return( nMax * ( ( nSeed := mod( nSeed*b+1, m ) ) / m ) )
I have it up and running now.