tags:

views:

147

answers:

2

I want to generate 10 different numbers from a range of 0-9. the desired output may look like this, 9 0 8 6 5 3 2 4 1 7

Dim arraynum(9) As Integer
Dim crmd As Boolean
Dim rmd as integer

For i = 0 To 9
    arraynum(i) = -1
Next i

crmd = True
Randomize Timer
For i = 0 To 9
    rmd = Int(Rnd * 10)
    For j = 0 To 9
        If arraynum(j) = rmd Then
            j = 9
            If crmd = False Then
                i = i - 1
            End If
            crmd = True
        Else
            crmd = False
        End If
    Next j
    If crmd = False Then
        arraynum(i) = rmd
        QuestionILabel.Caption = QuestionILabel.Caption + Str(arraynum(i))
    End If
Next i
+1  A: 

you need a random permutation over an array of 0 to 9.

I forgot how to write basic.. something like:

dim a(10)
for i=0 to 9 do a(i) = i
rem do random permute over a:
for i=0 to 9 do 
  j = rand() mod (i+1)
  tmp = a(j)
  a(i) = a(j)
  a(j) = tmp
next i
Yin Zhu
+1 You should also dim the variables i,j,tmp if `Option Explicit` is in use
Sune Rievers
Some theory: http://stackoverflow.com/questions/910215/need-for-predictable-random-generator/910340#910340 - look at the shuffle bag link.
tanascius
+5  A: 

Choosing random values and then throwing away those that you've already used is a bad idea. It makes the run-times longer as the pool of available numbers gets less since you're throwing away more and more.

What you want is a shuffle list which I would implement with the following code (pseudo-code since it's homework):

dim n[10]                 // gives n[0] through n[9]
for each i in 0..9:
    n[i] = i              // initialize them to their indexes
nsize = 10                // starting pool size
do 10 times:
    i = rnd(nsize)        // give a number between 0 and nsize-1
    print n[i]
    nsize = nsize - 1     // these two lines effectively remove the used number
    n[i] = n[nsize]

By simply selecting a random number from the pool then replacing it with the top number from that pool and reducing the size of the pool, you get a shuffle without having to worry about a large number of swaps up front. This is important if the number is high in that it doesn't introduce an unnecessary startup delay.

For example, examine the following bench-check:

<------ n[] ------>
0 1 2 3 4 5 6 7 8 9  nsize  rnd(nsize)  output
-------------------  -----  ----------  ------
0 1 2 3 4 5 6 7 8 9     10           4       4
0 1 2 3 9 5 6 7 8        9           7       7
0 1 2 3 9 5 6 8          8           2       2
0 1 8 3 9 5 6            7           6       6
0 1 8 3 9 5              6           0       0
5 1 8 3 9                5           2       8
5 1 9 3                  4           1       1
5 3 9                    3           0       5
9 3                      2           1       3
9                        1           0       9

You can see the pool reducing as you go and, because you're always replacing the used one with an unused one, you'll never have a repeat.

And now your homework consists of turning that into VB :-)


And, since this homework is now almost certainly overdue (about a year ago), I'll post a VBA solution showing how to do it, for completeness.

Option Explicit
Option Base 0
Sub Macro1()
    Randomize
    Dim list(10) As Integer
    Dim i As Integer
    Dim size As Integer
    Dim pos As Integer
    Dim result As String

    For i = 0 To 9
        list(i) = i
    Next

    size = 10
    result = ":"
    For i = 1 To 10
        pos = Int(Rnd() * size)
        result = result & list(pos) & ":"
        size = size - 1
        list(pos) = list(size)
    Next

    MsgBox result
End Sub

This generated, on three separate runs:

:5:7:4:2:9:1:0:8:3:6:
:3:9:6:0:7:8:5:4:2:1:
:7:6:3:5:1:8:9:0:4:2:
paxdiablo
error on a random number 0
gibz357
You are using `i` as the loop counter and then for storing random values inside the loop - got it running by storing the random number in another `int j;` and replacing `i` with `j` inside the loop. +1 for the algorithm. Is there any specific name for this?
Amarghosh
Found the name - Fisher-Yates shuffle. http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Amarghosh
@studentnoob35783, if you're getting errors, you haven't translated it correctly from pseudo-code :-) Post your source code and I'll have a look.
paxdiablo
I like the name. 20+ years ago, learning to, horror of horrors, count cards, I 'invented' (OK, implemented) this same sort of method - it's the only way to write a card playing game where memory of cards drawn is important. Basically, pick a random number for 0 to X, pull that card value at that locationfrom the queue, move everything below it up a spot.Or, if you're really sharp, just a linked list :)
KevinDTimm