Visual Basic - Counting the occurrence of numbers from a random array - vb.net

I need to use arrays and strings. The program should just search for 1 number which the user will enter (0-9). Here is my code below. It uses an array to get a random number, and it's testing the occurrences for each number. However it's not working, but I don't need it to test for every number anyway.
The program must only test for the 1 number that the user requests. So if the random number that's generated is say.. '7417', and user user has chosen '7', then the program will report back there have been two sevens. I'm going to use a textbox 'txtEnter' to get the users number to search for. Can anyone help me? Thanks!
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Randomize()
Dim ArrayNum(1) As Integer
ArrayNum(0) = Int(Rnd() * 100000)
lblDisplayNumber.Text = ArrayNum(0)
Dim num As Integer
txtEnter.Text = num
Dim counts = From c In num.ToString()
Group By c Into Group
Select DigitGroup = New With {.Count = Group.Count(),
.Digit = c, .Group = Group}
Order By DigitGroup.Count Descending
Select String.Format("There are {0} number {1}'s found.",
DigitGroup.Count, DigitGroup.Digit)
Dim message = String.Join(Environment.NewLine, counts)
End Sub

If you want to use Linq, it's short and readable:
Dim counts = From c In num.ToString()
Group By c Into Group
Select DigitGroup = New With {.Count = Group.Count(), .Digit = c, .Group = Group }
Order By DigitGroup.Count Descending
Select String.Format("There are {0} number {1}'s found.",
DigitGroup.Count, DigitGroup.Digit)
Dim message = String.Join(Environment.NewLine, counts)
Update: Here is a complete sample which shows the result of the entered number and a summary:
Dim rnd As New Random()
Dim randomInt = rnd.Next(0, 100000)
lblDisplayNumber.Text = randomInt.ToString()
Dim num As Integer
If Int32.TryParse(txtEnter.Text, num) AndAlso num >= 0 AndAlso num < 10 Then
Dim counts = From c In randomInt.ToString()
Group By c Into Group
Select DigitGroup = New With {.Count = Group.Count(), .Digit = c, .Group = Group}
Order By DigitGroup.Count Descending, DigitGroup.Digit
Dim numCount = counts.FirstOrDefault(Function(grp) grp.Digit.ToString() = num.ToString())
If numCount IsNot Nothing Then
Dim numMessage = String.Format("There are {0} number {1}'s found.", numCount.Count, num)
MessageBox.Show(numMessage)
Else
MessageBox.Show("Number does not contain " & num)
End If
Dim summaryCount = From grp In counts
Select String.Format("There are {0} number {1}'s found.", grp.Count, grp.Digit)
Dim summaryMessage = String.Join(Environment.NewLine, summaryCount)
MessageBox.Show("Summary:" & Environment.NewLine & summaryMessage)
Else
MessageBox.Show("Please enter a number between 0 and 9.")
End If

Your code has several issues, but to give you an answer directly to what is missing:
you should convert your random number to a string first
Number= Int(Rnd() * 100000)
NumberString = Number.ToString()
convert that string to an array of characters
DigitArray = NumberString.ToCharArray()
then loop over all characters of the array and convert each character c back to an integer
For Each c As Char In DigitArray
num = c - "0"C`
Then use that num as index for your counts array
count(num)+=1
instead of that horrible switch statement. I let you figure out the correct Dimstatements for those variables.

The solutions presented earlier seem a bit complicated if you just need to find how many times the entered number is in the random digits.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' create the data
Dim nDigits As Integer = 5
Dim digits(nDigits - 1) As String
For i = 0 To nDigits - 1
digits(i) = CInt(Rnd() * 10).ToString
Next
' show the data
TextBox1.Text = String.Join("", digits)
Dim inp = InputBox("Enter a number from 0 to 9")
' count the occurrences of the entered number
Dim nFound = digits.Count(Function(d) d = inp)
MsgBox(String.Format("There are {0} occurrences of {1}.", nFound, inp))
End Sub

Related

Splitting string every 100 characters not working

I am having a problem where I just can't seem to get it to split or even display the message. The message variable is predefined in another part of my code and I have debugged to make sure that the value comes through. I am trying to get it so that every 100 characters it goes onto a new line and with every message it also goes onto a new line.
y = y - 13
messagearray.AddRange(Message.Split(ChrW(100)))
Dim k = messagearray.Count - 1
Dim messagefin As String
messagefin = ""
While k > -1
messagefin = messagefin + vbCrLf + messagearray(k)
k = k - 1
End While
k = 0
Label1.Text = Label1.Text & vbCrLf & messagefin
Label1.Location = New Point(5, 398 + y)
You can use regular expression. It will create the array of strings where every string contains 100 characters. If the amount of remained characters is less than 100, it will match all of them.
Dim input = New String("A", 310)
Dim mc = Regex.Matches(input, ".{1,100}")
For Each m As Match In mc
'// Do something
MsgBox(m.Value)
Next
You can use LINQ to do that.
When you do a Select you can get the index of the item by including a second parameter. Then group the characters by that index divided by the line length so, the first character has index 0, and 0 \ 100 = 0, all the way up to the hundredth char which has index 99: 99 \ 100 = 0. The next hundred chars have 100 \ 100 = 1 to 199 \ 100 = 1, and so on (\ is the integer division operator in VB.NET).
Dim message = New String("A"c, 100)
message &= New String("B"c, 100)
message &= New String("C"c, 99)
Dim lineLength = 100
Dim q = message.Select(Function(c, i) New With {.Char = c, .Idx = i}).
GroupBy(Function(a) a.Idx \ lineLength).
Select(Function(b) String.Join("", b.Select(Function(d) d.Char)))
TextBox1.AppendText(vbCrLf & String.Join(vbCrLf, q))
It is easy to see how to change the line length because it is in a variable with a meaningful name, for example I set it to 50 to get the output
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
You can use String.SubString to do that. Like this
Dim Message As String = "your message here"
Dim MessageList As New List (Of String)
For i As Integer = 0 To Message.Length Step 100
If (Message.Length < i + 100) Then
MessageList.Add(Message.SubString (i, Message.Length - i)
Exit For
Else
MessageList.Add(Message.SubString (i, 100))
End If
Next
Dim k = MessageList.Count - 1
...
Here is what your code produced with a bit of clean up. I ignored the new position of the label.
Private Sub OpCode()
Dim messagearray As New List(Of String) 'I guessed that messagearray was a List(Of T)
messagearray.AddRange(Message.Split(ChrW(100))) 'ChrW(100) is lowercase d
Dim k = messagearray.Count - 1
Dim messagefin As String
messagefin = ""
While k > -1
messagefin = messagefin + vbCrLf + messagearray(k)
k = k - 1
End While
k = 0 'Why reset k? It falls out of scope at End Sub
Label1.Text = Label1.Text & vbCrLf & messagefin
End Sub
I am not sure why you think that splitting a string by lowercase d would have anything to do with getting 100 characters. As you can see the code reversed the order of the list items. It also added a blank line between the existing text in the label (In this case Label1) and the new text.
To accomplish your goal, I first created a List(Of String) to store the chunks. The For loop starts at the beginning of the input string and keeps going to the end increasing by 10 on each iteration.
To avoid an index out of range which would happen at the end. Say, we only had 6 characters left from start index. If we tried to retrieve 10 characters we would have an index out of range.
At the end we join the elements of the string with the separated of new line.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
BreakInto10CharacterChunks("The quick brown fox jumped over the lazy dogs.")
End Sub
Private Sub BreakInto10CharacterChunks(input As String)
Dim output As New List(Of String)
Dim chunk As String
For StartIndex = 0 To input.Length Step 10
If StartIndex + 10 > input.Length Then
chunk = input.Substring(StartIndex, input.Length - StartIndex)
Else
chunk = input.Substring(StartIndex, 10)
End If
output.Add(chunk)
Next
Label1.Text &= vbCrLf & String.Join(vbCrLf, output)
End Sub
Be sure to look up String.SubString and String.Join to fully understand how these methods work.
https://learn.microsoft.com/en-us/dotnet/api/system.string.substring?view=netframework-4.8
and https://learn.microsoft.com/en-us/dotnet/api/system.string.join?view=netframework-4.8

Lottery Program - Visual Basic

Have to create a lottery program, getting the random numbers and such easily enough. However I'm stumped. Essentially I have 2 buttons. One to display a checked list box with numbers 1-100, along with the 5 lotto numbers. I have a 2nd button that checks 2 things, to make sure that more than 5 numbers are not checked matching numbers. I'm lost on how to check for a match between the selected numbers between the RNG numbers.
Public Class Form1
Private Sub displayBtn_Click(sender As Object, e As EventArgs) Handles displayBtn.Click
Dim lottoNumbers(5) As Integer
Dim counter As Integer = 0
Dim number As Integer
Dim randomGenerator As New Random(Now.Millisecond)
'This will randomly select 5 unique numbers'
Do While counter < 5
number = randomGenerator.Next(0, 98)
If Array.IndexOf(lottoNumbers, number) = -1 Then
lottoNumbers(counter) = number
counter += 1
End If
Loop
'Display the lottery numbers in the label.'
Label1.Text = String.Empty
Array.Sort(lottoNumbers)
For Each num As Integer In lottoNumbers
Label2.Text = "Lottery Numbers"
Label1.Text &= CStr(num) & " "
Next num
For x = 0 To 98
CheckedListBox1.Items.Add(x + 1)
Next
End Sub
Private Sub checkBtn_Click(sender As Object, e As EventArgs) Handles checkBtn.Click
Dim count As Integer = 0
Dim x As Integer
'Checks to see if user checked more than 5'
For x = 0 To CheckedListBox1.Items.Count - 1
If (CheckedListBox1.CheckedItems.Count > 5) Then
MessageBox.Show("You cannot select more than 5 numbers.")
Return
Else
If (CheckedListBox1.GetItemChecked(x) = True) Then
count = count + 1
ListBox1.Items.Add(CheckedListBox1.Items(x))
End If
End If
Next
End Sub

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

Vb.net Random Number generator repeats same numbers

What should i add to random number generator coding, so numbers wont repeat themselves more times in a row?
My random number generator looks like this:
Dim rn As New Random
TextBox1.Text = rn.Next(1, 4)
If TextBox1.Text = 1 Then
Form4.Show()
Form4.Timer1.Start()
End If
If TextBox1.Text = 2 Then
Form7.Show()
Form7.Timer1.Start()
End If
If TextBox1.Text = 3 Then
Form8.Show()
Form8.Timer1.Start()
End If
Given N (at present N = 3 but it could be something else, as you say), try to construct a random permutation of 1, ..., N, then open the text boxes in the order that is generated. Note that that means you're generating N numbers at a time and using them all up, then generating N more. Search for "random permutation" to find an algorithm.
Move your Random instance, "rn", out to Class (Form) level so it only gets created ONCE for the Form, and the same instance gets used over and over:
Public Class Form1
Private rn As New Random
Private Sub SomeMethod()
TextBox1.Text = rn.Next(1, 4)
If TextBox1.Text = 1 Then
Form4.Show()
Form4.Timer1.Start()
End If
If TextBox1.Text = 2 Then
Form7.Show()
Form7.Timer1.Start()
End If
If TextBox1.Text = 3 Then
Form8.Show()
Form8.Timer1.Start()
End If
End Sub
End Class
To get a random integer value between 1 and N (inclusive) you can use the following.
CInt(Math.Ceiling(Rnd() * n))
If you want each number only used once, you need to do something like this:
Const FirstNumber As Integer = 1
Const LastNumber As Integer = 5
' Fill the list with numbers
Dim numberList as New List(Of Integer)
For i As Integer = FirstNumber To LastNumber Step 1
numberList.Add(i)
Next i
Dim rand as New Random()
While numberList.Count > 0
' draw a random number from the list
Dim randomIndex As Integer = rand.Next(0, numberList.Count - 1)
Dim randomNumber As Integer = numberList(randomIndex)
' Do stuff with the number here
TextBox1.Text = randomNumber
' remove the number from the list so it can't be used again
numberList.RemoveAt(randomIndex)
End While

Visual Basic - Looping an array 100 times not working?

I'm trying to loop this array 100 times (gets a number from 0-99,999). I've tried it several different ways with no luck. I've got it set up so you click a button and it generates the array. The user will then enter a number and hit the other button to check how many times that number shows up in the group of a 100 numbers. Any thoughts how to fix it? I'm stuck.
Dim i As Integer
Dim rnd As New Random()
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnter.Click
Dim num As Integer
If Int32.TryParse(txtEnter.Text, num) AndAlso num >= 0 AndAlso num < 10 Then
lblNumber.Text = i.ToString()
Dim counts = From c In i.ToString()
Group By c Into Group
Select DigitGroup = New With {.Count = Group.Count(), .Digit = c, .Group = Group}
Order By DigitGroup.Count Descending, DigitGroup.Digit
Dim numCount = counts.FirstOrDefault(Function(grp) grp.Digit.ToString() = num.ToString())
If numCount IsNot Nothing Then
Dim numMessage = String.Format("There are {0} number {1}'s found.", numCount.Count, num)
MessageBox.Show(numMessage)
Else
MessageBox.Show("Your number does not contain a " & num)
End If
Else
MessageBox.Show("Please enter a number between 0 and 9.")
End If
End Sub
Private Sub btnGetNumber_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGetNumber.Click
btnEnter.Enabled = True
i = 0
Do Until i > 100
Dim randomInt = rnd.Next(0, 100000)
i = i + 1
i = rnd.Next(0, 100000)
Loop
End Sub
End Class
First of all, it is common to use For Loops when you know the number of loops.
Secondly, you forgot to increment i in the until loop
Finally, you don't need to redeclare rnd in every loop. Something like that sounds better to me :
Dim rnd As New Random()
For i = 1 To 100
Dim randomInt = rnd.Next( 0 , 100000 )
Next
Move the New Random() out of that loop. Make it global and create the instance just one time.
(The Random generator starts using a seed obtained from the current time. Declaring a Random variable inside a loop result in the same seed used again and again. This gives back the same number defeating the randomness of the function) It is like: http://xkcd.com/221/
See another explanation here
Of course, if you don't increment the variable i used to control the loop, you will loop forever
Dim i As Integer
Dim rnd As New Random()
.....
i = 0
Do Until i > 100
Dim randomInt = rnd.Next(0, 100000)
i = i + 1
Loop
Said that, now I can't get what are you trying to do here. There is no array to check and you do not use the value obtained from the Random generator, simply, your i variable exits with value 101.
Now I am just guessing what are your intentions, but perhaps you want just this?
i = rnd.Next(0, 100000)
This will give to the variable i a random number and your subsequent code checks how many, of the required digit, are present in i
I see that you are not adding the variable "i" to increment:
i = 1
Do Until i > 100
Dim rnd As New Random()
Dim randomInt = rnd.Next(0, 100000)
i+=1 'Increment value of i by 1, same as i = i + 1
Loop
The variable of "i" will always be 1 if not incremented. Check that and let me know if that solves the problem!