×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
• Talk With Other Members
• Be Notified Of Responses
• Keyword Search
Favorite Forums
• Automated Signatures
• Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Theory Help4

Theory Help

(OP)
Hi All,
I'm having some difficulty getting my head around an "experiment" I'm trying to run. (This is just for some idea I have related to a thought experiment I'm working on and thought that I could generate a data set based on it, but I'm stuck on how to actually make it work).
The idea is based on Duffey & Saull's "Jar of Life" experiment, which has 25 white balls, and 5 black balls which are in a jar. Each of the 30 balls is drawn in succession. At the end you have a result that would look something like:

WWWWWBWWWWBWBWWWWWBBWWWWWWWWBW

Where W = W=white and B = black.
SO this sequence is a random sequence every time, but there will always be exactly 25 White and 5 Black (this is the part that is doing my head in).

I created a routine to randomize 0 and 1 (Where 0 represents white, and 1 represents black) This I will actually store in a text field in a table, C30 in length, so later I can just use SQL commands to pluck out the patterns that I want after I run about 1,000,000 iterations of the test.

So I can do something like:

CODE

White = 0
Black = 1
APPEND BLANK
FOR X = 1 to 30
REPLACE SEQUENCE WITH ALLTRIM(SEQUENCE)+ALLTRIM(STR((INT((White - BLACK + 1) * RAND( ) + Black))
ENDFOR 

I'll of course bury that into a loop that runs 1,000,000 iterations, but this is the idea.

The problem is, HOW do I get it to produce only 25 White outcomes and 5 black outcomes in an iteration???

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

Hi,

You may additionally want to check the occurrences of "W" and "B" in your sequence

CODE -->

pseudo code
for i = 1 to 30
...
if OCCURS("W", Sequence) = 25 or OCCURS("B", Sequence) = 5
if OCCURS("W", Sequence) = 25 - replace rest 5 with "B" - end loop if OCCURS("B", Sequence) = 5 - replace rest 25 with "W" - end loop endif
...
endfor 

hth
MK

RE: Theory Help

(OP)
Hi mjmksksr,
I explained the W and B for simplicty as that's the terms used by creator, but I just want to use 0 and 1 as it will be much simpler to deal with. This way I just have one value, and I don't have to do any converting. So a 0 will represent White and a 1 will represent Black.
If I REALLY wanted to after all the sequences were run, I could always do an STRTRAN to convert 0 to W and 1 to B, but really not necessary.

So the issue I still have is, how do I do the draw but ensure that only 25 0 and 5 1 are always produced?

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

Interesting question, Scott. It merits some deep thought.

But just off the top of my head, how about something like this:

1. Create a 2 col. x 30 row array.

2. Populate the first column with your 25 zeroes and 5 ones.

3. Populate the second column with a random number.

4. ASORT the array on the second column.

5. Concatenate the values in the first column - in the new sequence - into your string.

6. Repeat one million time.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

RE: Theory Help

Hi,

Please have a look at the code below

CODE -->

LOCAL Sequ
LOCAL ARRAY laSequ[1]

sequ = ""

FOR J = 1 TO 5
FOR X = 1 to 30
SEQU = ALLTRIM(SEQU) + ALLTRIM(STR((INT((1 - 0 + 1) * RAND( )) + 0)))

*!*		   WAIT WINDOW + sequ TIMEOUT .1

IF OCCURS("1", Sequ) >= 25
sequ = SEQU + REPLICATE("0", 30 - LEN(SEQU))
X = 30
ENDIF

IF OCCURS("0", Sequ) >= 5
sequ = SEQU + REPLICATE("1", 30 - LEN(SEQU))
X = 30
ENDIF

ENDFOR

DIMENSION laSequ[j]
laSequ[j] = sequ
sequ = ""
ENDFOR

DISPLAY MEMORY LIKE laS* 

hth

MK

RE: Theory Help

Scott

A quick code on this, by stuffing blues into whites:

CODE --> VFP

LOCAL Result AS String
LOCAL Whites AS Integer
LOCAL Blues AS Integer
LOCAL White AS Character
LOCAL Blue AS Character
LOCAL StoreBlue AS Integer

m.Blues = 5
m.Whites = 25

m.White = "0"
m.Blue = "1"

m.Result = REPLICATE(m.White, m.Blues + m.Whites)

FOR m.StoreBlue = 1 TO m.Blues
m.Result = STUFF(m.Result, AT(m.White, m.Result, 1 + RAND() * FLOOR((m.Blues + m.Whites) - m.StoreBlue)), 1, m.Blue)
ENDFOR

? TEXTMERGE("<<m.Result>> / Whites: <<OCCURS(m.White, m.Result)>> Blues: <<OCCURS(m.Blue, m.Result)>>") 

RE: Theory Help

Instead of randomly generating 0 and 1 and hoping you get 25 of one and 5 of the other, why not compute 5 distinct(!) positions where the 1 should go?

You can also fill 25 collection elementsĀ“, 20 with "0" and five with "1" and then draw from that like from a hat. That guarantees the amount you need.

CODE

Local lnI, lnItem

=Rand(-1) && randomize random number generator
loBitcollection = CreateObject("collection")

For lnI = 1 to 20
Endfor

For lnI = 1 to 5
Endfor

lcCombination = ""
For lnI = 1 to 30
lnItem = 1+Int(Rand()*loBitcollection.Count)
lcCombination = lcCombination + loBitcollection.Item(lnItem)
loBitcollection.Remove(lnItem)
EndFor

?lcCombination 

Notice, if you generate these combinations randomly, there is a likelyhood you generate the same sequence twice. 5 bits set in 30 bits has about 17 million possible combinations. (30 over 5)

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Theory Help

Computing the 5 positions is cheaper, as you only need to draw 5 positions of set bits:

CODE -->

Local lnI, lnItem, lnPos

=Rand(-1) && randomize random number generator
loBitcollection = CreateObject("collection")

For lnI = 1 to 30
Endfor

lcCombination = Replicate("0",30)
For lnI = 1 to 5
lnItem = 1+Int(Rand()*loBitcollection.Count)
lnPos = loBitcollection.item(lnItem)
loBitcollection.Remove(lnItem)
lcCombination = Stuff(lcCombination,lnPos,1,"1")
EndFor

?lcCombination 

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Theory Help

Even cheaper to pick 5 positions from a cursor with random order, since only a reindex is necessary to compute a new combination, once the cursor is created with 30 rows.

CODE

Local lnI
=Rand(-1)
Create Cursor crsBits (cBit C(1))
For lnI = 1 To 30
Insert Into crsBits Values (Iif(lnI<=25,"0","1"))
Endfor
Index On Rand() Tag xrandom

For lnI = 1 To 10 && compute 10 combinations
lcCombination = ""
Reindex
Scan
lcCombination = lcCombination + cBit
Endscan
? lcCombination
Endfor 

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Theory Help

Hi Scott,
I did it just based on a simple string not with 25 columns though.

CODE --> Foxpro

LOCAL lcString as Character
lcString = REPLICATE( [0] , 25 )
DO WHILE OCCURS( [1] , lcString ) < 5
lcString = STUFF( lcString , INT( RAND() * 25 ) , 1 , [1] )
ENDDO
?lcString 

It's based on the fact, that in the first lane there are 25 Ws and then we place random Bs until there are 5 Bs in the string.
As I just noticed, it is more or less the string based version of Olafs code :)

RE: Theory Help

Tom, in your case you don't need to replace, you need to use stuff to add a character without removing a 0.

And since the string length then grows from 25 to 30 you also need to compute int(rand()*len(lcString)+1, don't forget the +1. stuff works with start position =0, but then does the same as with start position 1. You are allowed to go to position length+1 to add the new string at the end, so you actually need int(rand()*(len(lcString)+1))+1.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Theory Help

2
Sorry, yes, the Replicate() has to be 30 not 25, otherwise there are only 20 Ws left :)

So changing the code to

CODE -->

LOCAL lcString as Character
lcString = REPLICATE( [0] , 30 ) && 25 changed to 30
DO WHILE OCCURS( [1] , lcString ) < 5
lcString = STUFF( lcString , INT( RAND() * 30 ) , 1 , [1] )
ENDDO
?lcString 

should be enough.

-Tom
https://www.blogger.com/profile/089031659767875220...

RE: Theory Help

#Define crlf Chr(12)+Chr(10)
Local lcReturn, lcX, lnX
m.lcReturn = []
Rand(-1)
For m.lnX = 1 To 10
Do While .T.
m.lcX = Num2bin30(2 ** 30 * Rand())
If Occurs([1], m.lcX ) = 5
m.lcReturn = m.lcReturn + m.lcX + crlf
Exit
Endif
Enddo
Endfor
Messagebox( m.lcReturn)

Function Num2bin30
Lparameters tnValue
Local lcValue, lnX
m.lcValue = []
For m.lnX = 0 To 29
m.lcValue = m.lcValue + Iif(Bittest(m.tnValue, m.lnX), [1], [0])
Endfor
Return m.lcValue 

Update: corrected a minor error. I forgot that Bittest() is 0-based.

RE: Theory Help

I like Mike's suggestion, don't sort the numbers - shuffle the pigeon holes

Regards

Griff
Keep ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

RE: Theory Help

Coming back for a correction to allow the last position to be chosen as a place to stuff some Blue:

CODE --> VFP

m.Result = STUFF(m.Result, AT(m.White, m.Result, 1 + RAND() * ((m.Blues + m.Whites + 1) - m.StoreBlue)), 1, m.Blue)

RE: Theory Help

@Griff,

well, ASORT would also sort the "0" and "1", but just like a cursor sorted by INDEX ON Rand() you can use that universally no matter what characters or bits you want in which combination and the count will match.

Chances you create a 30 bit number with 5 bits set are about 17 million: 2^30 and that is quite bad, as high as 17 million sounds, 2^30 is ~1 billion. So it comes down to 2% only, so you'd generate 50 numbers in average before you get one matching the conditions. It's not that bad as the other solutions also generate 30 random numbers, but it gets far worse with other conditions, eg there only are 30 combinations with just 1 bit set in 2^30. Hit or miss is almost always a miss. Same as 29 bits set = 1 bit unset. But these cases are simple just computing 1 position.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Theory Help

My thinking was just that the simplicity of his answer and the clarity with which the execution could be enabled was thus a truly elegant solution.

Regards

Griff
Keep ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

RE: Theory Help

Thank you for those kind words, Griff. I hope Scott will at least consider my solution - along with all the others, of course.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

RE: Theory Help

(OP)
WOW
I wasn't expecting there to be SO many amazing answers to this! I posted this up about 12 hours ago, and then went off forgetting about it for a while, and just came back to Tek-Tips and found all these replies!
First, thanks to all, totally cool, and I love how there are so many approaches to this.
I will try several of them, and see what comes up from this.
Just to mention some context, I'm looking at simulating "failure" scenarios, and wanted to look at the stochastic distribution of failures. Some of you may know, I'm in the thesis phase of my doctorate, and I had this crazy idea last night, and tried to model it, just to get a glimpse of what the result would look like. My "thinking" is major catastrophe are represented by not the appearance of the black, but the appearance of all 5 black in a row. But I'm going to be testing this theory, so the number of white and number of black may change, until I can find a typical occurrence. I just wanted to start with a million iterations as a point to see how often this will occur.
When I win the Nobel Prize, I'll make sure to thank everyone here in the acceptance speech. ><

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

(OP)
Ok, Very interesting results here.
The 1,000,000 iterations only take about 20 seconds to run using Tom Borgamanns very elegant solution.
Thought you guys might like to know, of the first test set of 1,000,000 there were 187 were all 5 occur in a row.
But a quick look at the result set shows this may not be giving me the randomness I need. One interesting thing is the occurrence of 5 1's in a row at the start appeared 17 times, but the appearance of all 5 1's at the end occurs 0 times.
So that's the first test, but I can see this isn't giving me a stochastic distribution. So next, I think I'll give one of Olaf's solutions a try.

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

Scott

I tried my code for 1,000,000 iterations, it runs in my computer for aproximattely 8 seconds (including storing the results in a cursor).

These are my benchmarks for you to compare against your findings (I ran the generator 4 times, marked from R1 to R4)

CODE

Runs		R1	R2	R3	R4
-----------------------------------------------
Time		8	9	8	8
%11111%		172	192	185	181
11111%		6	2	9	9
%11111		7	11	7	7 

RE: Theory Help

I don't see how stuffing in 5 ones into 30 zeros would get a stronger tendency towards one end, that's totally random.
But of course, there are only 26 combinations with all 1s in one rows, out of the 17,100,720. As you rarelyget them even in a million tries there will be a bulking, you just have to do more to get that evenly. Up to simply creating all combinations.

And Tom, I thought of changing the way to stuff, you can start with the 25 "O"s:

CODE

=Rand(-1)
LOCAL lcString, lnI, lnRows

Create Cursor crsCombinations (cCombination C(30))

For lnRows = 1 to 1000000
lcString = REPLICATE( [0] , 25 )
For lnI = 1 to 5
lcString = STUFF( lcString , INT( RAND() * (Len(lcString)+1))+1, 0 , [1])
EndFor lnI
Insert into crsCombinations values (lcString)
EndFor lnRows

Browse for "11111" \$ cCombination 
I didn't see a preference for the 1s bulking together more often at the start. There might be a small tendency because of what I said, you can stuff at position 0 and 1, both stuff before the first character of the string, and to get after the last position you have to stuff at position len(string)+1, i.e.:

CODE

Clear
lcString = "abc"
For lnPos = 0 to 4
? Stuff(lcString,lnPos,0,"z")
EndFor
*result:
zabc
zabc
azbc
abzc
abcz 

So:
1. Avoid using position 0, your random number result should be 1 at minimum.
2. go up to LEN(lcString)+1 to also add a 1 at the right end
3. notice RAND() never is 1, it's always <1. Besides that INT always rounds down, so INT(RAND()*5) will create numbers 0 to 4.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Theory Help

(OP)
Hi All,
So the next update.
I was running Olaf's Second solution, and it was interesting... after a few minutes, I killed it, as it was still running. Wasn't sure why. So I put an update in to show how often 1,000 results were produced MOD(X,1000) = 0 and for a while it was about 1,000 every 6 seconds. I got tired, let it run while I was asleep, and 8 hours later, it was at 314,000. I watched, and the time to increase from 314,000 to 315,000 was about 5 minutes! So it gets slower and slower and slower as it runs. So I decided to terminate that one, and use another approach. So that was amusing.
I'm now testing Olaf's latest approach, and I'm going to re-run Tom's original approach with 17,000,000 iterations and see if I get any 11111 at the end...

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

(OP)
So thought you might like to hear some of the findings.
I can now identify that there are 142,506 possible combinations. 1,000,000 iterations doesn't result in all the combinations, but gets close. But 2 million iterations will.
So this helps with my first phase, which is to get this to work. And then I need to determine the number of variables involved, versus number of failure opportunities. THEN I'm on to something.
Many thanks everyone.

Mike Lewis,
I'm still going to run your test as well. I quite like that idea.
I think it may be faster.

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

(OP)
And by the way Tom, there is something wrong with your solution.
Sequences of 11111 leading occurred 306 times in 17 million iterations, but ending in 11111 resulted in 0 outcomes, and the total distribution was 118,755 unique outcomes, and we know there are 142,506 possible results, so that solution isn't a good random distribution.

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

Hi,

Quote (And by the way Tom, there is something wrong with your solution.)

I don't think it has to do with Tom's solution but with the way he implemented the RAND() function. Nevertheless there remain chances that duplicates occur. Please read below form Hacker's Guide to VFP 7.0

Quote:

All random-number functions need a seed value based on which the function computes a random result. Passing the same number should (and does, in FoxPro) return the same "random" number. This ability allows you to test on the same data set.

To get the most random results, pass a negative number or zero as the initial seed. That seeds the function based on the system clock. On subsequent calls, omit the seed and FoxPro uses the previous number as a seed. You'll always get the same sequence if you start with the same value, but with a negative initial seed, that's very unlikely.

To mathematicians, a "random number" is always between 0 and 1, and that's what RAND() returns. Since you'll usually want a random integer in some range, you need to scale the result appropriately. The formula to convert the result to an integer between 0 and some boundary seems simple:

INT(nBoundary*RAND())

but things are seldom what they seem.

In all versions of FoxPro before VFP 5, RAND() returns both 0 and 1, but very rarely. Using the formula above, you get many fewer occurrences of nBoundary from a sequence of calls to RAND() then any other number in the range. You can fix that by adding 1 to the result (INT(nBoundary*RAND())+1), but then you get too few zeroes. There's no good solution to the problem. The best solution is for RAND() to never return one or the other of the endpoints (that is, RAND() should either never return 0 or never return 1).

Good news. Starting in VFP 5, that's exactly how it's done. RAND() never returns 1, so you can use INT(nBoundary * RAND()) to get values from 0 to nBoundary-1 or INT(nBoundary * RAND()) + 1 to go from 1 to nBoundary. No more ugly correction code that fouls up statistics.

One question you'd think we'd hear a lot is "How random are the results of RAND()?" There are various tests you can run to test the randomness of a sequence of random numbers. The downloads (www.hentzenwerke.com) contains two tests. Each generates a sequence of random numbers and then computes a statistic about it. The first is the Chi-Squared test. It returns a value you can look up in a table (try a statistics textbook, or check out Excel's CHIDIST() function) to see how random RAND() is. The second test is called the "Coupon Collectors" test. The return value is the average number of random numbers you have to generate in order to be sure you've gotten at least one of each value in a range.

If you want you may delete the multiples (code based on Tom's solution)

CODE -->

LOCAL lcString as Character

CLOSE ALL

CREATE CURSOR csrSequences (cSequenz c(30))

RAND(-1)

FOR i = 1 TO 10000
lcString = REPLICATE( [1] , 30 )

DO WHILE OCCURS( [0] , lcString ) < 5
lcString = STUFF( lcString , INT( RAND() * 30 ) , 1 , [0] )
ENDDO

Insert into csrSequences VALUES (lcString)
ENDFOR

DELETE FROM csrSequences where cSequenz in (SELECT cSequenz FROM csrSequences GROUP BY cSequenz HAVING COUNT(cSequenz ) > 1)

= MESSAGEBOX("NĀ° of duplicates " + TRANSFORM(_Tally), 0, "Duplicates generated by RAND()", 2000)

BROWSE

USE 

hth

MK

RE: Theory Help

142,506 possible results you're right. The 17 million resulting from being able to put the first 1 on 30 positions, the second on 29, the third on 28, overall 30*29*28*27*26 have to be reduced by the fact the same 5 bits can be set in differing sequences.

142,506 is a number resulting from combinations calculators, yes. You have to divide by 5!=5*4*3*2*1=120 as that is the number of different sequences of the 5 bits.

And sure, using a collection to compute a combination is slower. My cursor solution would be faster.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Theory Help

Even with 2,000,000 iterations, one may find occasionally a run that misses all possible combinations.

I don't see an evident pattern biasing the results one way or another, but having a fast generator will provide more data to analyze.

Code + more 4 runs stats:

CODE --> VFP

LOCAL NumResults AS Integer
LOCAL ARRAY Stats(1)

m.NumResults = 2000000

CREATE CURSOR Results (Result Char(30))

LOCAL Start AS Datetime
LOCAL Lapsed AS Integer

LOCAL Iteration AS Integer

m.Start = DATETIME()

FOR m.Iteration = 1 TO m.NumResults
INSERT INTO Results VALUES (CalcResult())
ENDFOR

m.Lapsed = DATETIME() - m.Start

? "Sample size:", m.NumResults
? "Time to calculate:", m.Lapsed
SELECT COUNT(*) FROM Results WHERE Result LIKE '%11111%' INTO ARRAY Stats
? "11111 sequences:", m.Stats
SELECT COUNT(*) FROM Results WHERE Result LIKE '11111%' INTO ARRAY Stats
? "11111 sequences at the beginning:", m.Stats
SELECT COUNT(*) FROM Results WHERE Result LIKE '%11111' INTO ARRAY Stats
? "11111 sequences at the end:", m.Stats
SELECT DISTINCT * FROM Results INTO ARRAY Stats
? "Distinct sequences:", ALEN(m.Stats)
SELECT TOP 1 Result, COUNT(*) FROM Results GROUP BY Result ORDER BY 2 DESC INTO ARRAY Stats
? "Most frequent sequence:", m.Stats(1)
SELECT TOP 1 Result, COUNT(*) FROM Results GROUP BY Result ORDER BY 2 INTO ARRAY Stats
? "Least frequent sequence:", m.Stats(1)

FUNCTION CalcResult

LOCAL Result AS String
LOCAL Whites AS Integer
LOCAL Blues AS Integer
LOCAL White AS Character
LOCAL Blue AS Character
LOCAL StoreBlue AS Integer

m.Blues = 5
m.Whites = 25

m.White = "0"
m.Blue = "1"

m.Result = REPLICATE(m.White, m.Blues + m.Whites)

FOR m.StoreBlue = 1 TO m.Blues
m.Result = STUFF(m.Result, AT(m.White, m.Result, 1 + RAND() * ((m.Blues + m.Whites + 1) - m.StoreBlue)), 1, m.Blue)
ENDFOR

RETURN m.Result

ENDFUNC 

RE: Theory Help

(OP)
atlopes,
You got the important one... that it should generate 142506 in 2,000,000 iterations, which is the maximum number of unique results. I see your last one is missing 1, and I agree that's within a reasonable "variation" for only 2,000,000. In 17 million, as Olaf mentiones 2^30, it should always provide the full range. I see the frequency of leading 11111 and trailing 11111 is reasonably the same as well, so I'm comfortable/confident that the randomness is reasonable. That's the critical point here.

My next step is to determine the number of factors that result in a major outage, and the frequency of events before an outage occurs. That frequency will then be represented by the 0's, and the number of incidents leading to an outage will be the 1's. Then I can change the 25 0's and the 5 1's and begin to predict some data about the outages (human errors) I'm looking to model and predict.

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

> I'm comfortable/confident that the randomness is reasonable. That's the critical point here.

mjcmkrsr quoted about the random number generator. You can seed it in a way you always get a repeatable random sequence:

CODE

Clear
? nonrandomsequence(1)
? nonrandomsequence(1)
? nonrandomsequence(1)
? nonrandomsequence(2)
? nonrandomsequence(2)
? nonrandomsequence(2)

Function nonrandomsequence(tnSeed)
Local lcSequence
Rand(tnSeed)
lcSequence = ""
For lnI = 1 to 10
lcSequence = lcSequence+Transform(Int(Rand()*10))
EndFor
Return lcSequence 
This outputs:
2740197506
2740197506
2740197506
0637474573
0637474573
0637474573 

So this is a typical random number generator that can only be randomized. RAND(-1) makes the seed depend on system time, so do that once and you get different sequences, but only call RAND(-1) once with that -1 seed. System time does not change that fast, so it's also no good idea to always call RAND(-1), this is what happens then:

CODE

Local lnJ
For lnJ = 1 to 100
Clear
? nonrandomsequence()
Wait '' timeout 0.01
Wait clear
EndFor

Function nonrandomsequence()
Local lcSequence
lcSequence = ""
For lnI = 1 to 1000
lcSequence = lcSequence+Transform(Int(Rand(-1)*10))
EndFor
Return lcSequence 

For certain scientific experiments with real randomness needed there are specific hardware devices for that, TRNG. No programming language I know has a true random number generator. See https://www.random.org/randomness/

It's good enough if you only use it for generating 0s and 1s. It might lack to ever create a longer sequence of same bits as a TRNG would do, albeit as seldom as that happens. The characteristic of PRNG is to use integer arithmetic which covers a whole range of integer, say 2 billion 32bit numbers and then repeats. but the aftermath of converting that to a number range 0..1 and then taking only a few values like 1-6 or just 0s and 1s you can forget that nature, it's random enough.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Theory Help

(OP)
Hi Olaf,
Yes, I was aware of the non-randomness of the RAND() function, and particularly TRNG not being software based, but for what I need, this will do fine. The idea here is to examine generally speaking how often the 5 1's would actually "clump" together. My "test" to see if it was giving a reasonable distribution was to look at leading and trailing clumps, and Tom's solution made it clear that it was not giving a distribution that would be reasonable. (It in fact, never comes up with all 5 1's at the end, even when I ran 17 million iterations against it).
I'm not sure why, but I moved on with the other solutions to see if I could get a better result, and I did.
Ironically, part of my simulation is about human error, which isn't "truly random" either. And we can even be quite predictable about it. For instance, any high skill task requires someone with high skill at that task. I can assure you that despite having read recently a great book on brain surgery, I would still have a 100% failure rate should I try to perform brain surgery on you or one of your friends at your choosing.

I'm working to assign particular "elements" to the 1's now, and working to determine how many of these I need to assign to progress my theory. So one may represent skill, another attitude, another concentration, another involuntary reaction, etc. Then when they align... we have big failures. BUt I need to work out "opportunities" which represents the 0's. I'm not sure yet if 25 is enough. I may need to increase it.

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

>I would still have a 100% failure rate should I try to perform brain surgery on you or one of your friends at your choosing.
Has been done already. Not on me, not on a close friend or family member, but from a brain surgeon.

Tom's first solution has that error of choosing too low range of random numbers, to get a 1 at the right end you have to allows length+1 for the position of stuff, that's all. I had written about that.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

RE: Theory Help

(OP)
Olaf,
Hahahaha... yes, lots of brain surgery done, but not by people who just "read about it".
I hope it turned out good.

Sorry I missed that point about the stuff+1.
I will modify it and try again, as it was the fastest method.

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCP, CDCS, CDCE, CTDC, CTIA, ATS

"Everything should be made as simple as possible, and no simpler."

RE: Theory Help

Quote (Scott24x7)

as it was the fastest method.

Not entering in racing mode, but mine, Tom's and Olaf's methods are variations of the same method.

In fact, Tom's would be the slowest since it admits uneffective STUFF() calls, that is, STUFF() in which a blue goes over a blue. That adds about 7% to calculations (roughly the number of innocuous calls).

STUFF() to insert seems also to be a tiny bit slower than STUFF() to replace, so starting with a 30-character string would be marginally faster than with a 25-character string.

Finally, using variables instead of constants adds time to each run of the experiment (but using variables is the base of experimenting, right?). Change from variables to constants in code, and the gain of speed may be in the order of one third.

RE: Theory Help

>I will modify it and try again, as it was the fastest method.
It's already done by Tom, atlopes and me in variations of Tom's original idea.

If you're after performance you'd not use string operations, STUFF does not operate on the memory of an existing string, also not when used to replace instead of insert.
You'd need to use SYS(2600) with 30 bytes allocated or better create a DLL in C++.

Bye, Olaf.

Olaf Doschke Software Engineering
https://www.doschke.name

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

• Talk To Other Members
• Notification Of Responses To Questions
• Favorite Forums One Click Access
• Keyword Search Of All Posts, And More...

Register now while it's still free!