Finding the average of an array after dropping lowest value? (VB) - vb.net

I'm developing a program that asks the user to input 5 numbers. The lowest of the 5 numbers will be dropped, and then the other 4 numbers are to be averaged.
I'm quite new to VB, but I believe I'm currently on the right path here...
I've sorted the array to help identify the lowest number, but I do not know how to exclude the lowest number and to then average the other remaining 4.
Here is my code so far:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim IntArr(4) As Integer
Dim i As Integer
For i = 1 To 5
IntArr(4) = InputBox("Enter Number" & i)
Next
Array.Sort(IntArr)
'textbox1.text = ???
End Sub
End Class
Can anyone please assist or at least point me in the right direction?

In keeping with the spirit of your code, something like the following would work.
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim IntArr(4) As Integer
Dim OutArr(3) As Integer
For i = 0 To 4
IntArr(i) = InputBox("Enter Number " & i)
Next
Array.Sort(IntArr)
Array.Copy(IntArr, 1, OutArr, 0, 4) 'exclude the lowest number
TextBox1.Text = OutArr.Average()
End Sub
End Class

Using built in LINQ functions
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim numberOfItems = 5
Dim numberOfItemsToRemove = 1
Dim inArray(numberOfItems - 1) As Integer
Dim outArray(numberOfItems - 1 - numberOfItemsToRemove) As Integer
Dim i As Integer
For i = 0 To numberOfItems - 1
While Not Integer.TryParse(InputBox("Enter Number " & i + 1), inArray(i))
MessageBox.Show("Invalid input!")
End While
Next
outArray = inArray.OrderBy(Function(j) j).Skip(numberOfItemsToRemove).ToArray()
MessageBox.Show(
String.Format(
"Input: [{0}], Output: [{1}], average: {2:0.0}",
String.Join(", ", inArray),
String.Join(", ", outArray),
outArray.Average))
End Sub

Your code as it is above will continue to simply change the value of index 4 with each box if I'm not mistaken. I would do something like this (I will use your variable names for your convenience).
Button1_Click(procedure junk that is auto-inserted)
Dim intArr(4) As Integer
Dim OutArr(3) As Integer
Dim intCounter, intAverage, intLowest, intLowIndex As Integer
'populate all indexes of intArr()
For intCounter = 0 to 4
intArr(intCounter) = InputBox("Please enter a number.")
Next intCounter
intCounter = 1 'reset counter for check
intLowest = intArr(intLowIndex) 'start with index 0
'find lowest number and its index
For intCounter = 1 to 4
If intLowest > intArr(intCounter) Then 'defaults to previous
intLowest = intArr(intCounter)
intLowIndex = intCounter
End If
Next intCounter
intCounter = 0 'reset counter again for possible For...Next loops
Select Case intLowIndex
Case = 0
For intCounter = 0 to 3
OutArr(intCounter) = intArr(intCounter + 1)
Next intCounter
Case = 1
OutArr(0) = intArr(0)
OutArr(1) = intArr(2)
OutArr(2) = intArr(3)
OutArr(3) = intArr(4)
Case = 2
OutArr(0) = intArr(0)
OutArr(1) = intArr(1)
OutArr(2) = intArr(3)
OutArr(3) = intArr(4)
Case = 3
OutArr(0) = intArr(0)
OutArr(1) = intArr(1)
OutArr(2) = intArr(2)
OutArr(3) = intArr(4)
Case = 4
For intCounter = 0 to 3
OutArr(intCounter) = intArr(intCounter)
Next intCounter
End Select
intAverage = (OutArr(0) + OutArr(1) + OutArr(2) + OutArr(3)) / 4
'insert your preferred method to display OutArr() and intAverage

Related

Dynamic Arrays in VB

Struggling student here... I've been asked to find the min, max and mid-point value. However, I cannot figure this out; arrays/data storage is 3 chapters away. So, I'm hoping someone could help me out with this conundrum.
-I need to get the data from an individual element within an array in decimal. Any ideas? I've largely been unsuccessful with the 'array.getvalue' method & with the 'array.min' methods.
Dim numberOfInvoices As Integer
Dim totalOfInvoices As Decimal
Dim invoiceAverage As Decimal
Private Sub BtnCalculate_Click(sender As Object, e As EventArgs) Handles btnCalculate.Click
Dim subtotal As Decimal = CDec(txtEnterSubtotal.Text)
Dim discountPercent As Decimal = 0.25D
Dim discountAmount As Decimal = Math.Round(subtotal * discountPercent, 2)
Dim invoiceTotal As Decimal = subtotal - discountAmount
Dim minimum, maximum, middle, i As Decimal
Dim array(1) As Decimal
Dim midpoint As Integer
txtSubtotal.Text = FormatCurrency(subtotal)
txtDiscountPercent.Text = FormatPercent(discountPercent, 1)
txtDiscountAmount.Text = FormatCurrency(discountAmount)
txtTotal.Text = FormatCurrency(invoiceTotal)
numberOfInvoices += 1
totalOfInvoices += invoiceTotal
invoiceAverage = totalOfInvoices / numberOfInvoices
For i = 0 To numberOfInvoices - 1
array(i) = i
ReDim Preserve array(0 To numberOfInvoices - 1)
Next i
If numberOfInvoices = 1 Then
minimum = totalOfInvoices
middle = totalOfInvoices
maximum = totalOfInvoices
End If
If numberOfInvoices > 1 Then
midpoint = numberOfInvoices / 2
middle = array.GetValue(midpoint)
For Each i In array
If i < UBound(array) - 1 Then If array(i) > array(i + 1) Then maximum = array(i)
If i < UBound(array) - 1 Then If array(i) < array(i + 1) Then minimum = array(i)
Next i
End If
txtLargestInvoice.Text = maximum.ToString
txtSmallestInvoice.Text = minimum.ToString
txtMidPoint.Text = middle.ToString
txtNumberOfInvoices.Text = numberOfInvoices.ToString
txtTotalOfInvoices.Text = FormatCurrency(totalOfInvoices)
txtInvoiceAverage.Text = FormatCurrency(invoiceAverage)
txtEnterSubtotal.Text = ""
txtEnterSubtotal.Select()
End Sub
Private Sub BtnClearTotals_Click(sender As Object,
e As EventArgs) Handles btnClearTotals.Click
numberOfInvoices = 0
totalOfInvoices = 0
invoiceAverage = 0
txtNumberOfInvoices.Text = ""
txtTotalOfInvoices.Text = ""
txtInvoiceAverage.Text = ""
txtEnterSubtotal.Select()
End Sub
Private Sub BtnExit_Click(sender As Object,
e As EventArgs) Handles btnExit.Click
Me.Close()
End Sub
Comments and explanations in-line
Private Sub OPCode2()
'You can declare and initialize an array in one line
Dim arr() As Double = {13.5, 18.0, 6.2, 11.8, 13.6}
'Just check intellisense for a list of methods and properties of arrays
Dim myAverage As Double = arr.Average()
Dim myMin As Double = arr.Min
Dim myMax As Double = arr.Max
Dim myMedian As Double
'The original array is lost when .Sort is applied
Array.Sort(arr)
Dim myLength As Integer = arr.Length
'If the lenght of the array is even you could also average
'the middle two values And return that number which
'may not be a value in the original array
myMedian = arr(CInt(myLength / 2)) 'returns the higher of the middle two if length is even
'or the actual middle value in the sorted array
MessageBox.Show($" The Average value is {myAverage}
The Maximum value is {myMax}
The Minimum value is {myMin}
The Median value is {myMedian}")
End Sub

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

how to exit a loop to another loop?

Anyone know why I can not get a new word when the "for" loop reaches the limit?
the intention is that the loop rotate every new word
but something very wrong'm doing
================================
Private Sub getWord()
Static wordCount As Integer
Dim txtLines As String()
txtLines = TextBox1.Text.Split(CChar(vbCrLf))
If (wordCount < txtLines.Count) Then
WebBrowser1.Navigate("http://www.bing.com/search?q=" & txtLines(wordCount) & "&first=1&FORM=PERE")
wordCount = wordCount + 1
End If
End Sub
Dim i As Integer
Dim max As Integer = 40
Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
If i >= max Then
getWord()
End If
If (WebBrowser1.ReadyState = WebBrowserReadyState.Complete) Then
For i As Integer = 1 To 40 Step 10
WebBrowser1.Navigate("http://www.bing.com/search?q=" & txtLines(wordCount) & "&first=" & i & "&FORM=PERE")
Next
Dim PageElement As HtmlElementCollection = WebBrowser1.Document.GetElementsByTagName("a")
Dim lk As String
For Each lks As HtmlElement In PageElement
lk = lks.GetAttribute("href")
ListBox1.Items.Add(lk)
Next
End If
End Sub
I'm not entirely sure that I understand your question, but I'll take a stab at it.
If you're not getting the expect values from the loop could it be that when you use For i As Integer = 1 To 40 Step 10 that you only get 1, 11, 21, 31, but that you're expecting five values? Perhaps you need to do this:
For i As Integer = 1 To 41 Step 10

Code is clean but when running it will not display

Public Class Form1
Private Sub GenerateAndSearch(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGenerate.Click, btnSearch.Click
Static intDataArray(-1) As Integer
Dim btnButtonClicked As Button = sender
Select Case btnButtonClicked.Tag
Case "Generate Array"
Call GenerateSortedArray(intDataArray)
Me.lstListArrayElements.Items.Clear()
Call DisplayData(intDataArray, Me.lstListArrayElements, "Sorted array:")
Case "Search Array"
Dim intNumToFind As Integer = Val(Me.txtNumToFind.Text)
Dim intNumFoundIndex As Integer
intNumFoundIndex = BinarySearch(intDataArray, intNumToFind)
If intNumFoundIndex = -1 Then
Me.lblFoundMessage.Text = "Number not found."
Else
Me.lblFoundMessage.Text = "Number found at index" & intNumFoundIndex
End If
End Select
End Sub
Sub GenerateSortedArray(ByRef intArray() As Integer)
Const intNUMELEMENTS As Integer = 50
Const intMAXNUMBER As Integer = 100
ReDim intArray(intNumElements - 1)
Randomize()
Dim intIndex As Integer
For intIndex = 0 To intArray.Length - 1
intArray(intIndex) = Int(intMAXNUMBER * Rnd()) + 1
Next intIndex
Call InsertionSort(intArray)
End Sub
Sub InsertionSort(ByRef intArray() As Integer)
Dim intIndex, intPreviousIndex, intTempItem As Integer
For intIndex = 1 To intArray.Length - 1
intTempItem = intArray(intIndex)
intPreviousIndex = intIndex - 1
Do While intPreviousIndex > 0 And
intArray(intPreviousIndex) > intTempItem
intArray(intPreviousIndex + 1) = intArray(intPreviousIndex)
intPreviousIndex = intPreviousIndex - 1
Loop
If intArray(intPreviousIndex) > intTempItem Then
intArray(intPreviousIndex + 1) = intArray(intPreviousIndex)
intArray(intPreviousIndex) = intTempItem
Else
intArray(intPreviousIndex + 1) = intTempItem
End If
Next intIndex
End Sub
Sub DisplayData(ByRef intArray() As Integer, ByRef lstList As ListBox, ByVal strTitle As String)
lstList.Items.Add(strTitle)
Dim intIndex As Integer
For intIndex = 0 To intArray.Length - 1
lstList.Items.Add(intIndex & vbTab & intArray(intIndex))
Next intIndex
End Sub
Function BinarySearch(ByRef intArray() As Integer, ByVal intNumToFind As Integer) As Integer
Dim intHighIndex As Integer = intArray.Length - 1
Dim intMidIndex As Integer
Dim intLowIndex As Integer = 0
Dim blnFound As Boolean = False
Do While (Not blnFound) And (intLowIndex <= intHighIndex)
intMidIndex = (intMidIndex + intLowIndex) / 2
If intArray(intMidIndex) = intNumToFind Then
blnFound = True
ElseIf intArray(intMidIndex) > intNumToFind Then
intHighIndex = intMidIndex - 1
Else
intLowIndex = intMidIndex + 1
End If
Loop
If blnFound Then
Return intMidIndex
Else
Return -1
End If
End Function
Private Sub NewData_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtNumtoFind.TextChanged, btnGenerate.Click
Me.lblFoundMessage.text = Nothing
End Sub
End Class
My problem is I cannot get my code to display a list of arrays to find. I cant see where im going wrong any ideas? Also my sort button is not working but that may be due to the fact nothing shows up when i click button btnGenerate.
Your biggest problem appears to be in your BinarySearch function. The reason you weren't getting any display is the BinarySearch function had an infinite loop. Here's some corrected code with explanations and is tested and working:
Function BinarySearch(ByRef intArray() As Integer, ByVal intNumToFind As Integer) As Integer
Dim intHighIndex As Integer = intArray.Length - 1
Dim intMidIndex As Integer
Dim intLowIndex As Integer = 0
Dim blnFound As Boolean = False
Do While (Not blnFound) And (intLowIndex <= intHighIndex)
'This should add high and low then divide by 2 not mid and low
'Also you should use the integer division sign to return an integer result
intMidIndex = (intHighIndex + intLowIndex) \ 2
If intArray(intMidIndex) = intNumToFind Then
blnFound = True
'mid should become the new limit without any inc/decrement
ElseIf intArray(intMidIndex) > intNumToFind Then
intHighIndex = intMidIndex
Else
intLowIndex = intMidIndex
End If
Loop
If blnFound Then
Return intMidIndex
Else
Return -1
End If
End Function
A couple of other corrections that should be made:
Select Case btnButtonClicked.Tag should be Select Case btnButtonClicked.Tag.ToString()
intArray(intIndex) = Int(intMAXNUMBER * Rnd()) + 1 should be intArray(intIndex) = CInt(intMAXNUMBER * Rnd()) + 1
One other thought, you might want to put a check in the generate routine to only generate unique numbers. Binary search will only find one element but not any of the others if there are more.
The NewData_TextChanged method erases your search results:
Me.lblFoundMessage.text = Nothing
Remove that line of code and the results should be displayed.

Bubble Sort logical error VB.NET

This program suppose to sort records(in arySort) in ascending order by last name(index 1 in aryTemp and aryTemp2) and place the result in the list box over the old, preloaded, unsorted records.
It sorts them strangely, I have to click multiple times the Ascending button to get the actual sort result that I suppose to get from clicking the button once.
Why doesn't it sort items with a single mouse click?
The source:
Public Class Form1
Dim FILE_NAME As String = "Students.txt"
Dim numberOfRecords As Integer 'total number of records
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If System.IO.File.Exists(FILE_NAME) = True Then
Dim objReader As New System.IO.StreamReader(FILE_NAME)
Do While objReader.Peek() <> -1
lstBox.Items.Add(objReader.ReadLine)
numberOfRecords += 1
Loop
objReader.Close()
End If
End Sub
Private Sub btnAscending_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAscending.Click
'load all students into array
Dim arySort(numberOfRecords - 1) As String
Dim aryTemp() As String 'holds first record's last name
Dim aryTemp2() As String 'holds second record's last name
For i = 0 To numberOfRecords - 1
arySort(i) = lstBox.Items(i)
Next
Dim temp As String 'holds temporary record
Dim k As Integer
For i = 0 To arySort.Length - 2
aryTemp = Split(arySort(i), " ")
For k = i + 1 To arySort.Length - 1
aryTemp2 = Split(arySort(k), " ")
If aryTemp(1) < aryTemp2(1) Then
temp = arySort(k)
arySort(k) = arySort(i)
arySort(i) = temp
End If
Next
Next
lstBox.Items.Clear()
numberOfRecords = 0
For i = 0 To arySort.Length - 1
lstBox.Items.Add(arySort(i))
numberOfRecords += 1
Next
End Sub
End Class
If you just need to sort your list (as you say in the comment), don't implement your own sort mechanism but use the one of .NET:
' Define how we want to compare items '
Function compareByLastName(ByVal item1 As String, ByVal item2 As String) As Integer
Return String.Compare(item1.Split(" ")(1), item2.Split(" ")(1))
End Function
Private Sub btnAscending_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAscending.Click
' load all students into array '
Dim arySort(numberOfRecords - 1) As String
For i = 0 To numberOfRecords - 1
arySort(i) = lstBox.Items(i)
Next
' Use built-in .NET magic '
Array.Sort(arySort, AddressOf compareByLastName)
' Write the values back into your list box '
lstBox.Items.Clear()
numberOfRecords = 0
For i = 0 To arySort.Length - 1
lstBox.Items.Add(arySort(i))
numberOfRecords += 1
Next
End Sub
This uses the built-in quicksort algorithm of the .NET class library. Here's the documentation of the method we are using: Array.Sort(T(), Comparison(Of T)).
compare with my working bubble sort:
Public Sub BubbleSort(ByVal arr() As Integer)
Dim flag As Boolean = False
For i As Integer = 0 To arr.Length - 1
For j As Integer = 0 To arr.Length - 2 - i
If arr(j + 1) < arr(j) Then
flag = True
Dim temp As Integer = arr(j)
arr(j) = arr(j + 1)
arr(j + 1) = temp
End If
Next
If flag = False Then Return ' no swaps =>already sorted
Next
End Sub
I see a two major issues with your algorithm:
It's not bubble sort. Bubble sort swaps adjacent elements, i.e., it swaps i with i+1. You, on the other hand, swap some element i with the first j > i where name(i) < name(j). Maybe you should show us, in pseudo code, which algorithm you are actually trying to implement?
aryTemp contains element i and aryTemp2 contains some element j > i. Why do you swap the elements if aryTemp(1) < aryTemp2(1)? Isn't that already the correct order if you want your elements to be sorted ascending?