Showing Multiple Numbers from RNG - vb.net

What I am trying to do is create an RNG button that will generate 5 unique numbers between 1-99. This is what I have so far:
Private Sub GenerateButton_Click(sender As Object, e As EventArgs) Handles GenerateButton.Click
Dim rand As New Random()
Dim rememberset As New HashSet(Of Integer)
Dim value As Integer
While rememberset.Count < 6
value = rand.Next(1, 99)
If rememberset.Add(value) Then
LotteryLabel.Text = value.ToString()
End If
End While
End Sub
Every time I click the generate button, I just get 1 number. I'm trying to get 5 to display in this format (1, 2, 3, 4, 5). Any ideas? Thanks.

Your LotteryLabel.Text is always set to the string of only one number ( I guess you will see only the last number)
You need to append the value: Easy (but maybe slow) solution should be
LotteryLabel.Text = LotteryLabel.Text & ", " & value.ToString()

Related

How can I output sequence of number in descending order when the first input is higher than the second input vice versa?

This one is working but it only output a sequence of number in ascending order even if the First Input is higher than the Second Input.
Here is what I want to happen
Ascending Order when
First Input: 2
Second Input: 8
Result 2, 3, 4, 5, 6, 7, 8
Descending Orden when
First Input: 9
Second Input: 6
Result: 9, 8, 7, 6
Private Sub btnAccept_Click(sender As Object, e As EventArgs) Handles btnAccept.Click
Dim A = txtstart.Text
Dim B = txtend.Text
Dim Start, Ending As Integer
If A < B Then
Start = A
Ending = B
Else
Start = B
Ending = A
End If
While Start <= Ending
lblbetween1.Text = lblbetween1.Text & Start & " , "
Start += 1
End While
End Sub
With a For loop, you can choose the increment, so you can check which order the numbers are in and set the increment appropriately, for example:
Option Strict On
Imports System.Text
' ....
Private Sub btnAccept_Click(sender As Object, e As EventArgs) Handles btnAccept.Click
Dim a = Integer.Parse(txtStart.Text)
Dim b = Integer.Parse(txtEnd.Text)
Dim inc As Integer = -1
If a < b Then
inc = 1
End If
Dim sb As New StringBuilder()
For i = a To b Step inc
sb.Append(i & " , ")
Next
lblbetween1.Text = sb.ToString()
End Sub
Fortunately, this still works if the numbers are equal, so there is no need for a special case for that.
It's better to use a StringBuilder to concatenate lots of strings, instead of just using & on lots of strings or the content of a control.
Option Strict On makes sure that the program doesn't try to do things with possibly unexpected results such as adding a number to a string. You should set it as the default for new projects.
You could do something like this:
Will need to add
Imports System.Linq
and then
Dim a = 10I
Dim b = 15I
Dim start = Math.Min(a, b)
Dim count = Math.Max(a, b) - start
Dim series = Enumerable.Range(start, count + 1).ToList
If b < a Then
series.Reverse()
End If
Dim result = String.Join(",", series)

create 1000, 8-character random ID's, all unique and display in a text box

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?"
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 !
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.
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)
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.

vb.net Line numbering in multi line Rich Text Box if line starts with specific condition

Let me start by saying that I'm new to any language of coding besides G-code, and I've researched this until my fingers hurt. I've actually been working on this project for a little over a year now on my own, and this is the first hurdle I haven't been able to find my way around.
I'm creating an editor for cnc G-code, and i'm trying to add a Re-number function to it. I'm using a multi line richtextbox to display the the G-code to the user. I'm trying to edit each line of code that starts with the character "N", and if a line doesn't start with that character then it's left alone.
I figured the best way to do this would be to loop thru the RTB and pass each line into an array. Then I could use an If statement to see if a cell in the array started with the char "N" or in my case "blockLetter". Then use the replace function to correct the line Number.
This is what I have so far.
Dim increment As Integer = txtLNIncrement.Text
Dim blockLetter As String = txtLNStartTxt.Text
Dim count As Integer = 0
Dim block As Integer = count + increment
For Each cell As String In frmNC.NcTextBox.Lines
If cell.StartsWith(blockLetter) Then
Dim newCell As String = cell.Replace(blockLetter, block)
block = block + increment
MessageBox.Show(newCell)
End If
Next
Example of G-code that needs to be renumbered:
N50 M01
N60 T0101 (TOOL NAME)
N70 M41
N80 G96 S350
N90 M03
N100 M08
This is what I want:
N10 M01
N20 T0101 (TOOL NAME)
N30 M41
N40 G96 S350
N50 M03
N60 M08
This is what I'm getting when I run the code above:
1050 M01
2060 T0101 (TOOL NAME)
3070 M41
4080 G96 S350
5090 M03
60100 M08
I believe my issue is that the cell.replace is splitting each cell at the "N" character, and dropping it all together. Thus adding what I want to see in front of the existing numbers, minus the "N" character. How can I overwrite the existing block number to the correct ascending block number, and retain the "N" character? Am I going about this in the correct way, or is there a better way? Any help is greatly appreciated.
Try something like this out:
Private increment As Integer = 10
Private blockLetter As String = "N"
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim newLine As String
Dim values() As String
Dim lineNumber As Integer = 0
Dim lines As New List(Of String)(NcTextBox.Lines)
For i As Integer = 0 To lines.Count - 1
If lines(i).TrimStart().StartsWith(blockLetter) Then
values = lines(i).TrimStart(" " & blockLetter.ToCharArray).Split(" ")
lineNumber = lineNumber + increment
values(0) = lineNumber
newLine = blockLetter & String.Join(" ", values)
lines(i) = newLine
End If
Next
NcTextBox.Lines = lines.ToArray
End Sub
it's very simple:
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim blockLetter As String = "N"
Dim increment As Integer = 1
For i As Integer = 0 To RichTextBox1.Lines.Length - 1 Step 1
Dim fullLine As String = RichTextBox1.Lines(i)
If fullLine.StartsWith(blockLetter) Then
Dim numbering As String = fullLine.Remove(RichTextBox1.Lines(i).IndexOf(" "))
Dim block As Integer = numbering.Substring(1)
Dim newCell As String = blockLetter & block + increment
MessageBox.Show(newCell)
End If
Next
End Sub
Result:
The Label1.Text will increase with button click.
It's all about Substring() starting from index 1 after 'N', so you will get the number.
Good luck with your coding!

Visual Basic Confusion

I have been required to create a program that asks me to find the maximum value of one particular array. I am using multiple forms in this project and have used a user-defined data type and created multiple array under it. There is a first form that is related to this, which defines my defined data type is gStudentRecord and the arrays that define it are last name, Id, and GPA. This second form is where I write all of the code to display what I want. My question is how to get the Max GPA out of that array. I'm sorry if this isn't in very good format, this is the first time I've used Stackoverflow
Public Class frmSecond
Private Sub frmSecond_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim Ctr As Integer
Dim Line As String
lstDisplay.Items.Clear()
lstDisplay.Items.Add("Name".PadRight(25) & "ID".PadRight(16) & "GPA".PadRight(20) & "Out of state".PadRight(10))
For Ctr = 0 To gIndex Step 1
Line = gCourseRoster(Ctr).LastName.PadRight(20) & gCourseRoster(Ctr).ID.PadRight(15) & gCourseRoster(Ctr).GPA.ToString.PadRight(15) & gCourseRoster(Ctr).OutOfState.ToString().PadLeft(5)
lstDisplay.Items.Add(Line)
Next
End Sub
Private Sub btnStats_Click(sender As Object, e As EventArgs) Handles btnStats.Click
Dim Ctr As Integer = 0
Dim Average As Double
Dim Sum As Double
Dim Found As Boolean = False
Dim Pass As Integer
Dim Index As Integer
lstDisplay.Items.Clear()
**For Ctr = 0 To gIndex Step 1
If gCourseRoster(Ctr).GPA > gCourseRoster(Ctr).GPA Then
lstDisplay.Items.Add(gCourseRoster(Ctr).GPA)
End If
Next**
Average = gComputeAverage(Sum)
lstDisplay.Items.Add("Number of Students: " & gNumberOfStudents)
lstDisplay.Items.Add("Average: " & Average)
End Sub
Private Function gComputeAverage(Sum As Double) As Double
Dim Ctr As Integer
Dim Average As Double
For Ctr = 0 To gIndex Step 1
Sum = Sum + gCourseRoster(Ctr).GPA
Next
Average = Sum / gNumberOfStudents
Return Average
End Function
End Class
You can use a Lambda expression to tease it out. The Cast part is converting from the gCourseRoster to a collection of Double by supplying the GPA to the Select statement.
Dim gList As New List(Of gCourseRoster)
gList.Add(New gCourseRoster With {.id = 1, .name = "Bob", .GPA = 3.9})
gList.Add(New gCourseRoster With {.id = 2, .name = "Sarah", .GPA = 3.2})
gList.Add(New gCourseRoster With {.id = 3, .name = "Frank", .GPA = 3.1})
Dim maxGPA = gList.Cast(Of gCourseRoster).Select(Function(c) c.GPA).ToList.Max
MessageBox.Show(maxGPA.ToString)
Output: 3.9

Loop through contents in the text file

New TechGuy on this site. Thought i'd make this resourceful since im getting ready to graduate and want more programming practice. I have a question:
I tried looping through a text file I created and I wanted to replace each multiple of 3 with the word "changed". I created a text file and entered numbers 1-15 on each line. My code is below but for some reason it would only change the number 3 and 13. I tried using this link as a resource (Loop through the lines of a text file in VB.NET) but that wasnt to helpful. Anyway here is my code, can someone help with what i'm doing wrong?
Public Class numbers
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim OpenFilePrompt As New OpenFileDialog
openFilePrompt.ShowDialog()
Dim currentReader As New System.IO.StreamReader(OpenFilePrompt.FileName)
txtInput.Text = currentReader.ReadToEnd
Dim a As String
Dim numbers As New List(Of String)
a = txtInput.Text
numbers.Add(a)
Dim b As Integer
For i = 0 To numbers.Count Step 3
b = b + 3
TextBox2.Text = (numbers.Item(i).Replace(b.ToString, "Changed"))
Next
End Sub
End Class
You are setting numbers (the first item) to a, which is txtInput.Text.
Then you have a one size list which is completely useless!
You should use Mod instead.
Divides two numbers and returns only the remainder.
So just check if Integer Mod 3 equals 0.
Also consider using File.ReadAllLines(String), Val(String), String.Join(String, String()) and File.WriteAllLines(String, String()).
Dim Content() As String = File.ReadAllLines(OpenFilePrompt.FileName)
For Index As Integer = 0 To Content.Length - 1
Dim Number As Integer = Val(Content(Index))
If Number Mod 3 = 0 Then
Content(Index) = "changed"
End If
Next
txtInput.Text = String.Join(vbCrLf, Content)
File.WriteAllLines(OpenFilePrompt.FileName, Content)