Author Topic: Random number help  (Read 1048 times)

rickus

  • Full Member
  • ***
  • Posts: 122
Random number help
« on: January 07, 2017, 04:11:18 pm »
This may have a simple solution but, alas, it's been a puzzler and it eludes me.

I'm generating a random list of 5 whole numbers, say, between 1 and 100. When the numbers are generated, I do not want any of the numbers to be within -5 or +5 of any other number. For example, if the number 45 is generated there should not be any other number generated between 39 and 51, as though I am creating a numeric buffer around each randomly-generated number. Maybe the solution is so simple that I can't get it! Thanks!

SkyCharger001

  • Hero Member
  • *****
  • Posts: 2388
Re: Random number help
« Reply #1 on: January 07, 2017, 07:02:29 pm »
A. a simple solution:
split the range into separate blocks and pick something from between the 1/4th and the 3/4th of each

B. a bit more involved solution (effectively throws away candidates that have become ineligible) :
Code: [Select]
DIM t(99) AS INTEGER
DIM r(5) AS INTEGER
CONST mindev = 12
FOR p = 0 TO 99
    t(p) = p + 1
NEXT p
z = 100
FOR x = 0 TO 4
    a = INT(RND * z)
    r(x) = t(a)
    q = 0
    FOR g = a + mindev TO a - mindev STEP -1

        IF g >= 0 AND g < z THEN
            n = ABS(t(g) - r(x)) 'does it count as less
            IF n <= mindev THEN 'than mindev deviation?
                q = q + 1
                FOR p = g TO z - 2
                    SWAP t(p), t(p + 1)

                NEXT p
            END IF
        END IF
    NEXT g
    PRINT r(x)
    z = z - q
NEXT x
discovered and fixed a minor oversight in what to throw away
« Last Edit: January 07, 2017, 07:24:58 pm by SkyCharger001 »

STxAxTIC

  • Guest
Re: Random number help
« Reply #2 on: January 07, 2017, 08:26:28 pm »
You can make things easier by picking a random number between 0 and 20 and then multiplying by 5. That'll prolly get you what you need, just check (like sky said) that you don't get the same result twice.

(Play with the numbers to taste but consider the idea conveyed.)

Pete

  • Hero Member
  • *****
  • Posts: 7324
  • Cuz I sez so varmint!
Re: Random number help
« Reply #3 on: January 08, 2017, 12:52:24 am »
You can make things easier by picking a random number between 0 and 20 and then multiplying by 5. That'll prolly get you what you need, just check (like sky said) that you don't get the same result twice.

(Play with the numbers to taste but consider the idea conveyed.)

Argh. Never send a theoretical physicist to do a real physicist's job.

Code: [Select]
RANDOMIZE TIMER
DIM x%(100)
DO
    x% = INT(RND * 100) + 1 ' Number range 1 to 100
    IF x%(x%) = 0 THEN
        FOR i% = -5 TO 5
            IF x% + i% >= 0 AND x% + i% <= 100 THEN x%(x% + i%) = -1
        NEXT
        PRINT x%;
        FOR i% = 1 TO 100
            IF x%(i%) = 0 THEN EXIT FOR
        NEXT
        IF i% > 100 THEN EXIT DO
    END IF
LOOP
 
Give a man a program, and he does one thing for a day. Teach a man to program, and he does one thing for a lifetime.

waltersmind

  • QB64 Partner Site Owner
  • Hero Member
  • *
  • Posts: 645
  • TheJoyfulProgrammer.com
    • The Joyful Programmer
Re: Random number help
« Reply #4 on: January 08, 2017, 03:07:02 am »
rickus,

Here is a demo that I personally belive gives you exactly what you are wanting, plus some.

With the following demo, you define at the top the minimum number wanted, the maximum number wanted, how many numbers you want found (by sizing the RndNumbers array to how ever many you want), and the size of the margin you want. Please note, the margin definition is for one side (where you two sides to make your buffer - see the code for details).

Then the rest of the code takes care of everything.

If you set the min to max distance to close to each other, the demo we adjust the number of numbers it will provide you at the end. For example, if you set the min value to 1 and the max value to 5, then run it, the demo will only return one number.

This demo does use a little brute force, but I believe it is cut down to a bare minimum.

With no further ado, here is the code:

Code: [Select]
CONST MinNumber = 1
CONST MaxNumber = 100
CONST Margin = 5 '  DEFINED AS ONE-SIDED

DIM RndNumbers(5) AS LONG
DIM Index AS INTEGER
DIM InSideANumMargin AS _BYTE
DIM NotInRangeCount AS LONG

Index = LBOUND(RndNumbers)

SCREEN _NEWIMAGE(600, 800, 32)

T% = TIMER
RANDOMIZE T%
PRINT "T%: "; T%

'  GET INTEGER NUMBERS
DO

    RndNumbers(Index) = RND * (ABS(MaxNumber) - ABS(MinNumber)) + 1
    InSideANumMargin = 0

    '  IT'S NOT THE FIRST SO LET'S LOOP FROM THE FIRST ARRAY INDEX TO THE ONE BEFORE THE CURRENT INDEX
    '  TO MAKE SURE THE CURRENT ARRAY VALUE ISN'T WITHIN THE MARGINS OF THE OTHERS
    FOR i = LBOUND(RndNumbers) TO Index - 1
        IF RndNumbers(Index) >= (RndNumbers(i) - Margin) AND RndNumbers(Index) <= (RndNumbers(i) + Margin) THEN
            InSideANumMargin = 1
        END IF
    NEXT

    IF InSideANumMargin = 0 THEN
        Index = Index + 1
    END IF

    '  MAKE SURE THIS ISN'T THE FIRST ARRAY INDEX OR THE LAST. IF SO, SKIP IT.
    IF (Index - 1) >= LBOUND(RndNumbers) AND Index <= UBOUND(RndNumbers) THEN

        '  DEFINE THE CurrentIndex TO THE MINIMUM NUMBER
        CurrentIndex = MinNumber

        DO

            '  RESET SOME VALUES
            MatchesAvailable = 0
            NotInRangeCount = 0


            '  SEARCH THROUGH ALL ARRAY VALUES TO SEE IF CurrentIndex IS WITHIN THEIR MARGINS
            FOR I2 = LBOUND(rndnumbers) TO Index - 1
                '  CHECK TO SEE IF CurrentIndex IS WITHIN THE MARGINS OF THE CURRENT ARRAY VALUE
                IF CurrentIndex < (RndNumbers(I2) - Margin) OR CurrentIndex > (RndNumbers(I2) + Margin) THEN
                    '  INCREMENT NOT-IN-RANGE-COUNT IF CurrentIndex IS OUTSIDE OF CURRENT ARRAY VALUE'S MARGINS
                    NotInRangeCount = NotInRangeCount + 1
                END IF
            NEXT

            '  CHECK TO SEE IF CurrentIndex IS NOT IN RANGE OF ANY OF THE VALUES IN THE ARRAY.
            '  FOR THIS TO BE TRUE, THE NotInRangeCount MUST EQUAL THE NUMBER ARRAY VALUES DEFINED.
            '  IF CurrentIndex IS FOUND TO BE INSIDE ANY OF THE DEFINED ARRAY VALUE MARGINS, THEN
            '  THE CURRENT INDEX IS NOT USABLE.
            IF NotInRangeCount = (Index - LBOUND(rndnumbers)) THEN
                '  WE HAVE A MATACH TO AN OPEN INDEX SLOT
                MatchesAvailable = 1
                '  LEAVE THIS LOOP
                EXIT DO
            END IF

            '  IF WE MADE IT HERE, THEN WE NEED INCREMENT THE CurrentIndex
            CurrentIndex = CurrentIndex + 1

            '  IF THE CurrentIndex IS LESS THAN THE MAXNUMBER, CONTINUE THE LOOP UNTIL THE END

        LOOP WHILE CurrentIndex <= MaxNumber


        '  WE NEED TO CHECK TO SEE IF WE HAVE SCANNED THE ENTIRE SPECTRUM
        IF MatchesAvailable = 0 THEN
            '  AT THIS POINT, THERE ARE NO MORE POSSIBLE MATCHES, SO THERE IS NO NEED TO CONTINUE ON.
            Index = Index - 1
            EXIT DO
        END IF

    END IF

LOOP WHILE Index <= UBOUND(rndnumbers)


PRINT


IF Index > UBOUND(rndnumbers) THEN Index = UBOUND(rndnumbers)

'  DISPLAY ALL THE NUMBERS WE WERE ABLE TO FIND WITHIN GIVEN RANGE WITH GIVEN MARGINS
IF Index = UBOUND(rndnumbers) THEN

    PRINT "ALL "; (UBOUND(rndnumbers) + 1); " ARRAY INDEX'S HAVE BEEN DEFINED!"
ELSE
    PRINT "ONLY "; (Index + 1); " OUT OF "; (UBOUND(rndnumbers) + 1); " ARRAY INDEX'S WERE DEFINED!"
END IF

PRINT

FOR i = LBOUND(rndnumbers) TO Index
    PRINT "RndNumbers("; i; "): "; RndNumbers(i)
NEXT

_DISPLAY



Let me know close this is to what you are wanting.


Happy Coding!

Walter Whitman
The Joyful Programmer
www.TheJoyfulProgrammer.com
www.TheJoyfulProgrammer.com/qb64/forum/
Please visit my QB64 programming forum located at http://www.TheJoyfulProgrammer.com and my YouTube Channel: https://www.youtube.com/c/Thejoyfulprogrammer

rickus

  • Full Member
  • ***
  • Posts: 122
Re: Random number help
« Reply #5 on: January 08, 2017, 01:09:26 pm »
Thanks, coders, for the different examples that achieve the solution. I'll need to dissect each one and see how they work. -rickus

TempodiBasic

  • Hero Member
  • *****
  • Posts: 532
Re: Random number help
« Reply #6 on: January 11, 2017, 05:21:58 pm »
Hi Rickus

your question is a real mathematical issue... but I need some more information....

1. if we must generate at random 5 integer with a positive value  between 1 and 100 and no common value in the range n-5 and n+5 we use 11 numbers, so in 100 numbers it is possible to generate 100/11   numbers with that feature, but to preserve range around each number  we must generate a number from 6 to 94,

2.  it seems that math calculation 's result is  strange  in fact if 45 is the first number then 45-5 = 40 and not 39, 45+5 = 50 and not 51!

So
flowchart:
randomize timer
choose number
add to list of number used 

See again
FOR eachProblem% = 1 TO Max%
    IF NOT solution%(EachProblem%) THEN
         goto Solved
    ELSE
       PRINT "Solution in coming"
   END IF
NEXT
Solved:
PRINT "Smile!"

SMcNeill

  • Moderator
  • Hero Member
  • *****
  • Posts: 6143
Re: Random number help
« Reply #7 on: January 11, 2017, 08:38:26 pm »
For this, I'd just set an array of answers and then shuffle it.

Dim Result(20)
For I = 1 TO 20
    Result(I) = 5 * I
NEXT

FOR J = 1 to 5 'only need 5 numbers, no need to swap the rest
    SWAP Result(J), Result(INT(RND * 20) + 1)
NEXT

FOR I = 1 TO 5
   PRINT Result(I)
NEXT

********************

You've got such a small dataset here, I think simply assigning the possible values to an array and then shuffling it once would be the most efficient method to be certain you got unique results suitable to your needs.
http://bit.ly/Color32BI -- A set of color CONST for use in 32 bit mode, as a BI library.

Pete

  • Hero Member
  • *****
  • Posts: 7324
  • Cuz I sez so varmint!
Re: Random number help
« Reply #8 on: January 11, 2017, 08:54:32 pm »
Well you're wrong, but it's nice to see you back. Hope the X-mas trees sold like hotcakes this year!

To clarify, you and Bill only have solutions that work in multiples of 5. Your code works fine for that but numbers other than multiples of 5 can have a lower and upper bounds of 5 between them. Run my example to see what I mean. Of course maybe I misunderstood what the OP wanted. One of us did.

Clippy's furry friend: http://www.network54.com/Forum/183705/message/1483222907

Pete  ;D
Give a man a program, and he does one thing for a day. Teach a man to program, and he does one thing for a lifetime.

rickus

  • Full Member
  • ***
  • Posts: 122
Re: Random number help
« Reply #9 on: January 11, 2017, 08:59:42 pm »
No, Pete, you were right on the money about what I was trying to create. Steve's solution looks like what STxAxTIC (above) had proposed. I find it fascinating that, in coding, there are so many ways to achieve a desired result. Thanks again, all.

SMcNeill

  • Moderator
  • Hero Member
  • *****
  • Posts: 6143
Re: Random number help
« Reply #10 on: January 11, 2017, 09:05:09 pm »
Aye, I read the problem wrong.  I still think simply creating a list (array) and making use of it is the simplest solution.

Code: [Select]
DEFLNG A-Z
DIM SHARED Results(1 TO 5)
RANDOMIZE TIMER

FOR c = 1 TO 20
    GenerateNumbers
    FOR i = 1 TO 5: PRINT Results(i),: NEXT 'Remember to read our result from left to right for each 5 numbers in our answer set
    PRINT
NEXT



SUB GenerateNumbers
    DIM L(1 TO 100): LC = 100 'initialize list of possible numbers, set original list count to 100
    TC = 0 'temporary counter to be updated as we check the list for valid possible answers
    FOR i = 1 TO 100: L(i) = i: NEXT 'create the initial list

    FOR i = 1 TO 5 'do a loop 5 times to get the 5 values we want
        Results(i) = L(INT(RND * LC) + 1) 'Get the result from our list
        TC = 0 'Reset the temp list counter
        FOR j = 1 TO LC 'Check all the values in our current list
            IF L(j) <= Results(i) - 5 OR L(j) >= Results(i) + 5 THEN 'if the values in our list are still valid
                TC = TC + 1
                L(TC) = L(j) 'keep them in the new list
            ELSE
                'Else we don't add the invalid answers back to the update list of possible answers
            END IF
        NEXT
        LC = TC 'our list of possible answers is now narrowed down from what it was before it ONLY the values that are still valid for our purposes
    NEXT
END SUB

For the above, we start with a list of 100 possible values (1 to 100).   
Then we get a random number from that list.
A quick check of the list and we remove all values that no longer fit our criteria.
And we get the next answer.
Repeat and Rinse a few more times...

:P

Easiest way I can think to do as was originally suggested.  ;)
http://bit.ly/Color32BI -- A set of color CONST for use in 32 bit mode, as a BI library.

waltersmind

  • QB64 Partner Site Owner
  • Hero Member
  • *
  • Posts: 645
  • TheJoyfulProgrammer.com
    • The Joyful Programmer
Re: Random number help
« Reply #11 on: January 12, 2017, 10:10:42 am »
Has anyone looked at the code I provided? It does exactly what he wants plus some. If rickus decided to change the upper value to a lower number, say 10, my code provides the total number of choices it finds, which could be between 1 to 2 depending on the what the RND function returns. My demo also checks to see if there are any other possible values available through brute force, but only looks for the first available number if there is one.

You can adjust the marginal space wanted, the upper and lower bounds to search for, and it stores the numbers in array. To change the amount of numbers to return, all you need to do is change the array size. The code is heavily commented as well, so you can understand what I am doing

Please have a look at my demo and see if it is what you wanted. Oh, it has been heavily tested as well.

Steve, welcome back! I missed you being around.


Happy Coding!

Walter Whitman
The Joyful Programmer
www.TheJoyfulProgrammer.com
www.TheJoyfulProgrammer.com/qb64/forum/
Please visit my QB64 programming forum located at http://www.TheJoyfulProgrammer.com and my YouTube Channel: https://www.youtube.com/c/Thejoyfulprogrammer

SkyCharger001

  • Hero Member
  • *****
  • Posts: 2388
Re: Random number help
« Reply #12 on: January 12, 2017, 10:15:09 am »
SMcNeill: That's basically the same as my B. suggestion, but I believe that mine is a bit more efficient.
For example: Your version seems to check the entire array list for the new count, mine merely subtracts the positions that have become ineligible from the count of the previous iteration. (can save a few cycles)

Pete

  • Hero Member
  • *****
  • Posts: 7324
  • Cuz I sez so varmint!
Re: Random number help
« Reply #13 on: January 12, 2017, 10:17:00 am »
My code's better than your code
My code's better than yours
My code's better 'cause I say it's better 'cause
My codes better than yours

Pete  ;D

https://www.youtube.com/watch?v=Oi84maqHgxg
Give a man a program, and he does one thing for a day. Teach a man to program, and he does one thing for a lifetime.

waltersmind

  • QB64 Partner Site Owner
  • Hero Member
  • *
  • Posts: 645
  • TheJoyfulProgrammer.com
    • The Joyful Programmer
Re: Random number help
« Reply #14 on: January 12, 2017, 12:31:54 pm »
I am by no means stating that my version is better than anyone else's, but I would like to get a little feedback on it. At this point, no one has commented on my project.

I spent several hours on it coming up with the algorithm, coding it, and thoroughly testing it.


Happy Coding!

Walter Whitman
The Joyful Programmer
www.TheJoyfulProgrammer.com
www.TheJoyfulProgrammer.com/qb64/forum/
Please visit my QB64 programming forum located at http://www.TheJoyfulProgrammer.com and my YouTube Channel: https://www.youtube.com/c/Thejoyfulprogrammer