-1

enter image description hereWrite a program to display 1000 8-character random user IDs in a text box after you click a button. Make sure the program verifies that none of the IDs are identical. Each userid should include a mixture of alphabetic characters and numbers.

What I have so far, which could be enough to get by as a random ID generator alone, but it does not loop 1000 times to be displayed in the label, and doesn't check for repeated ID's.

Public Class Form1
    Private Sub btnGenerateRandomID_Click(sender As Object, e As EventArgs) Handles btnGenerateRandomID.Click
        Dim rand As New Random

        Dim char1 As String
        Dim char2 As String
        Dim char3 As String
        Dim char4 As String
        Dim char5 As String
        Dim char6 As String
        Dim char7 As String
        Dim char8 As String


        char1 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
        char2 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
        char3 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
        char4 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
        char5 = rand.Next(0, 9)
        char6 = rand.Next(0, 9)
        char7 = rand.Next(0, 9)
        char8 = rand.Next(0, 9)



        lblRandomId.Text = char1 + char2 + char3 + char4 + char5 + char6 + char7 + char8

    End Sub
End Class

Thanks.

EDIT:

Public Class Form1 'Write a program to display 1000 8-character random user IDs in a text 'box after you click a button. Make sure the program verifies that none Of the IDs are identical. 'Each userid should include a mixture Of alphabetic characters And numbers.

Private Sub btnGenerateRandomID_Click(sender As Object, e As EventArgs) Handles btnGenerateRandomID.Click

    Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
    Dim rand As New Random
    Dim strID As String = ""

    For count_ids As Integer = 0 To 999
        For count_chars As Integer = 0 To 7
            strID += strChar(rand.Next(0, 62))
        Next count_chars
        lblRandomId.Text = strID
    Next






End Sub

End Class

Here is the actual question "Q. Write a program to display 1000 8-character random user IDs in a text box after you click a button. Make sure the program verifies that none of the IDs are identical. Each userid should include a mixture of alphabetic characters and numbers.

Explain your program in your essay, with screenshots. Include a paragraph on the random number generator used in Visual Basic, and answer the question: how should the random number generator be best seeded?"

  • 1
    Is it an academic assignment? I ask because if we give some mindblowing LINQ based one line solution, and you hand it in as a response to a programming 101 task, it might be clear to your supervisor that stackoverflow did your homework for you.. – Caius Jard Jul 08 '20 at 10:09
  • I have posted a second answer based on your EDIT. Have a look. – Mary Jul 09 '20 at 01:02

4 Answers4

1

First of all, Welcome to StackOverflow, From what i understand from your post you want to generate 1000 8 Character long Unique ID's First of all we declare our variables

Dim Characters As String = "AZERTYUIOPQSDFGHJKLMWXCVBN0123456789" 'Declare All Characters on one string
Dim IDsList As New List(Of String) With {.Capacity = 1000} 'You can limit the capacity to 1000
Dim Id As String = ""
Dim Rand As New Random

Now we begin to genearte ID's and add them to IDsList using a nested loop

 For i As Integer = 0 To 999 'This is a Zero Based Index so 999 is actually 1000
            For _i As Integer = 0 To 7 'This also means 7 is 8
                Id += Characters(Rand.Next(0, 36))
            Next
            IDsList.Add(Id)
            Id = ""
        Next
            'You can Check for duplicates by adding this piece of code or use the next one instead
            Dim NoDupesIDsList As New List(Of String)
            NoDupesIDsList = IDsList.Distinct.ToList
 For i As Integer = 0 To 999 'This is a Zero Based Index so 999 is actually 1000
            For _i As Integer = 0 To 7 'This also means 7 is 8
                Id += Characters(Rand.Next(0, 36))
            Next
If not IDsList.contains(Id) then
            IDsList.Add(Id)
End if
            Id = ""
        Next

Use a Textbox with multiline and scroll bar for better experience Feel free to ask me anything via comments PS: I tested my method and it's working , enjoy it !

Anes Hamdani
  • 50
  • 1
  • 7
  • Where are you checking for duplicate Id? – Mary Jul 08 '20 at 00:10
  • I edited to show where I'm at. I'm not able to get a new line in order to separate the ID's. and also trouble incorporating the uniqueness of the ID's. This is for hw for my first vb.net class. – Dan Latcovich Jul 08 '20 at 20:47
  • For the line separate simply use `Textbox.text = String.join(vbcrlf,IdsList)` for the uniqueness see my edit i provided two ways to check for duplicates – Anes Hamdani Jul 08 '20 at 22:53
0

This will create the names:

Function RandomName(length As Integer) As String
    Shared rnd As New Random()
    Shared corpus() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray()
    Return New String(Enumerable.Range(0, length).Select(Function(c) corpus(rnd.Next(corpus.Length))).ToArray())
End Function

Iterator Function GetUniqueNames(length As Integer, count As Integer) As IEnumerable(Of String)
    Dim names As New HashSet(Of String)

    For i As Integer = 0 To count
       Dim name As String = RandomName(length)
       While names.Contains(name)
            'Potential (but unlikely) halting problem
            name = RandomName(length)
        End While
        names.Add(name)
        Yield name
    Next
End Function

Dim uniqueNames = GetUniqueNames(8, 1000)

But do you really want to display 1000 of them in a single label?

lblRandomId.Text = string.Join(vbCrLf, uniqueNames)
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • I edited to show where I'm at. I'm not able to get a new line in order to separate the ID's. and also trouble incorporating the uniqueness of the ID's. This is for hw for my first vb.net class. – Dan Latcovich Jul 08 '20 at 20:48
0

This function will return the ASCII characters between 48 an 122. That will include some characters that are not letters or numbers but this makes the ids even more unique and simplifies the code.

The For loop builds the ids with a length of 8. Then the id is checked for uniqueness with the .Contains method. Only if it is not in the list, it is added to the list and the counter is incremented.

Private Rnd As New Random

Private Function GetListOfIDs() As List(Of String)
    Dim Counter As Integer
    Dim lst As New List(Of String)
    Dim id As String = ""
    Do While Counter < 1000
        id = ""
        For i = 0 To 7
            id &= Chr(Rnd.Next(48, 123))
        Next
        If Not lst.Contains(id) Then
            lst.Add(id)
            Counter += 1
        End If
    Loop
    Return lst
End Function

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim lst = GetListOfIDs()
    TextBox1.Text = String.Join(vbCrLf, lst)
End Sub

EDIT

As per suggestion by Caius Jard in comments I have added a solution using a HashSet. Same idea only a HashSet will not accept duplicate entries. The .Add method returns a boolean telling you if the Add was successful.

Private Function GetListOfIDs() As HashSet(Of String)
    Dim hs As New HashSet(Of String)
    Dim id As String = ""
    Do While hs.Count < 1001
        id = ""
        For i = 0 To 7
            id &= Chr(Rnd.Next(48, 123))
        Next
        If hs.Add(id) Then
            Counter += 1
        End If
    Loop
    Return hs
End Function

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim hs = BuildHashSet()
    TextBox1.Text = String.Join(vbCrLf, hs)
End Sub

This method is probably more efficient because a HashSet is designed for hight performance. For 1000 items I did not notice any difference in the user interface. The text box updated immediately with both methods.

Mary
  • 14,926
  • 3
  • 18
  • 27
  • 1
    Oof.. I'm not sure I'd use a List to track repetitions. Aside from the Ocomplexity, it would be simpler to just use a HashSet and keep adding to it til its count reaches 1000 – Caius Jard Jul 08 '20 at 10:07
  • I edited to show where I'm at. I'm not able to get a new line in order to separate the ID's. and also trouble incorporating the uniqueness of the ID's. This is for hw for my first vb.net class. – Dan Latcovich Jul 08 '20 at 20:48
  • @CaiusJard I have added a HashSet solution. Do I have the right idea? – Mary Jul 08 '20 at 23:28
  • 1
    Sure.. or can forget the counter and just ask hashset for its count (While hashSet.Count < 1000) – Caius Jard Jul 09 '20 at 00:22
  • That's the first time in years I've seen a do loop! – Caius Jard Jul 09 '20 at 00:24
  • @CaiusJard I am an old coder (72 yrs old) so I use old methods. :-) – Mary Jul 09 '20 at 01:06
  • @DanLatcovich I have added a second answer that addresses your Edit. – Mary Jul 09 '20 at 01:07
  • Thanks for the help all. Its been about 6 weeks into my vb.net journey and I appreciate the help! – Dan Latcovich Jul 09 '20 at 02:34
0

Let's talk about your code.

    Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

This assignment will work in your loop because a String is really an array of Char. This is why you can refer to an index in the string.

Dim rand As New Random()

The .net Random class provides a seed for Random based on system time. Only rarely would you want to provide a seed. From the docs https://learn.microsoft.com/en-us/dotnet/api/system.random?view=netcore-3.1

CONSTRUCTORS

Random() Initializes a new instance of the Random class using a default seed value.

Random(Int32) Initializes a new instance of the Random class, using the specified seed value.

For count_ids As Integer = 0 To 999

A For loop is not appropriate for this problem. We only want to increment the counter if we get a unique ID. The above For loop will increment on every iteration.

Do While Counter < 1000
    'Code here
Loop

Notice in my code the counter is only incremented if the ID is unique.

The following loop should work fine but above this code we need to reset strID to an empty string. Otherwise we will have a very long string.

For count_chars As Integer = 0 To 7
    strID += strChar(rand.Next(0, 62))
Next count_chars

You should not update the user interface (the label) on each iteration of the loop. Repainting the screen is one of the slowest operations in code. This line will overwrite the string in the label on every iteration.

lblRandomId.Text = strID

Move the update of the UI to after both loops are complete

Your code never checks for duplicates.

Now let's fix it.

We use a List(Of T) to accumulate the IDs. The T stands for Type; in our case it is String. A List is like an array only you don't have to know ahead of time how many entries there will be. No ReDim Preserve required.

Moved Dim strID As String = "" to the beginning of the inner loop so we will get a new strID on each iteration of the outer loop.

Changed strID &= strChar(rand.Next(0, 62)). &= instead of +=. In VB.net we use the ampersand to concatenate strings although the plus sign will work. The .Next method of the Random class has an overload that takes 2 Integers. It is inclusive of the first and exclusive of the second which means (0, 62) will return numbers form 0 to 61. Your string with a length of 62 has indexes of 0 to 61.

Next we check for duplicates with the .Contains method of the List class. This method does just what you would expect. We pass the new ID to the method and it returns a Boolean telling if the string is already in the list.

If it is not in the list, we add it to the list and increment the counter. The counter is only incremented if we have a successful add.

Finally we update the user interface by using a method of the String class. the .Join method takes a separator and the list to join. The TextBox must be multiline and have scroll bars.

I changed the names of the controls so I could test it in my testing program.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim lst As New List(Of String)
    Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
    Dim rand As New Random()
    Dim counter As Integer
    Do While counter < 1000
        Dim strID As String = ""
        For count_chars = 0 To 7
            strID &= strChar(rand.Next(0, 62))
        Next
        If Not lst.Contains(strID) Then
            lst.Add(strID)
            counter += 1
        End If
    Loop
    TextBox1.Text = String.Join(vbCrLf, lst)
End Sub

EDIT

The official documentation for this method can be found here. https://learn.microsoft.com/en-us/dotnet/api/system.string.join?view=netcore-3.1 I know it will be difficult to read but just take a look. Eventually you will be able to understand it and will be using these docs a lot.

String.Join(separator, List(Of String))

The separator is what to put between the strings in the list. In our case that is vbCrLf which is a vb constant for new line. Cr = Carraiage Return and Lf = Line Feed. Other types of collections that contain strings can also use this method.

The method takes each string in the list and adds the separator. After it is done with the list it returns one long string which we display in the TextBox.

Mary
  • 14,926
  • 3
  • 18
  • 27
  • This is great, however I'm looking to have a list of 1000 ID's created at one time and displayed. This one will display one at a time and reset the text box. – Dan Latcovich Jul 09 '20 at 01:53
  • @DanLatcovich No, this will list 1000 unique IDs in the text box, one on a line. You must have copied the code incorrectly. I have tested this code. – Mary Jul 09 '20 at 02:00
  • I copied it and put it in the click procedure of the button, it's just displaying one each time I click. I looked to see if multiline is true, and it is. Would there be any other properties that could effect it, or could it be a bug with visual studio 2015? – Dan Latcovich Jul 09 '20 at 02:11
  • You would need scroll bar. Vertical i think. I always get Vertical and Horizontal mixed up. I would make the text box tall enough so you can see several lines. – Mary Jul 09 '20 at 02:14
  • I feel embarrassed that I likely had the correct answer for many different things I was trying, but I thought it was on autosize. Thanks! – Dan Latcovich Jul 09 '20 at 02:24
  • last thing. We haven't really learned the tostring.join method. could you explain what is happening there? or is there another method that can be used to go to the next line after the each ID? – Dan Latcovich Jul 09 '20 at 02:38
  • @DanLatcovich See Edit to above answer. – Mary Jul 09 '20 at 02:51