How do I assign a default property to a FunctionProcedureName() in VB.NET? - vb.net

I have done extensive research on using recursion in VB.NET (I am using 2015) in order complete a homework assignment. In my desperation, I even asked my professor for help!
I am trying to write a program that will calculate 1! through 12!, and post the results in a list box. The method I am using is based on the following example (sent to me by my prof):
var integer n, result
n = 0
For 1 to 12 do
n = n + 1
write (n, ‘! equals ‘, Fact(n)
End For
Function Fact (ByVal n as Integer)
if (n = 0) then Fact = 1
else Fact = n * Fact (n-1)
End If
End Function
http://www.softwareandfinance.com/VB/Factorial_Recursion.html
My issue is with my call statement for the function (I named it Factorial). Here is the section of the code where I am getting the error message:
For intN = 1 To 12
intFact = Factorial()
lstFactorialsAnswers.Items.Add(intN & "! = " & intFact)
Next
Thank you for your insights.
In response, I removed the "Dim Factorial as Int64" declaration. I also added "intN" as a parameter in the function call. The new error message is "Argument not specified for parameter 'intFact' of 'Public Function Factorial(intN As Integer, intFact As Integer) As Long'.
Here is the revised code:
Public Class frmFactorialMath
Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnCalculate.Click
Dim intN As Integer
Dim intFact As Integer
intN = Convert.ToInt32(txtN)
For intN = 1 To 12
If intN = 1 Then
lstFactorialsAnswers.Items.Add(intN & "! = " & 1)
Else
intFact = Factorial(intN)
lstFactorialsAnswers.Items.Add(intN & "! = " & intFact)
End If
Next
End Sub
Function Factorial(ByVal intN As Integer, intFact As Integer) As Long
If (intN = 0) Then
Return 1
Else
intFact = intN * Factorial(intN - 1)
Return intFact
End If
End Function
Here is the solution to the issue(s) I was having:
Option Strict On
Public Class frmFactorialMath
' This event handler calculates the factorials for numbers 1 through 12.
' A list showing the answers is compiled and displayed.
Private Sub btnCalculate_Click(sender As Object, e As EventArgs) Handles btnCalculate.Click
Dim intN, intFact As Integer
For intN = 1 To 12
intFact = Factorial(intN)
lstFactorialsAnswers.Items.Add(intN.ToString() & "! = " & intFact.ToString())
Next
End Sub
' This Function performs the calculations using recursion.
Function Factorial(ByVal intFact As Integer) As Integer
If intFact = 1 Then
Return 1
Else
' This "Do While" loop ends the recursion, eliminating an infinite loop.
Do While intFact > 1
Return intFact * Factorial(intFact - 1)
Loop
End If
End Function

Related

VB.NET Compare each item in collection to every other item in collection - Threading

this is my first time posting so please accept my apologies if im not doing this right and please feel free to correct me for any formatting or posting guidelines. I am doing this in VB.Net with .NET Framework 4.5.2.
I have a large collection called gBoard in a class.
Private gBoard As Collection
It contains roughly 2000 instances of a class.
What i am trying to achieve is for each item in the class, i want to look at each other item in the class and then update the first item based on variables in the second.
Currently i have the following code:
In the main class:
Private gBoard As New Collection ' This is populated elsewhere in the code
Private Sub CheckSurroundings()
For i As Integer = 1 To (xBoxes)
For j As Integer = 1 To (yBoxes)
For x = 1 As Integer To (xBoxes)
For y = 1 As Integer To (yBoxes)
Tile(New Point(i, j)).CheckDistance(Tile(New Point(x, y)))
Next y
Next x
Next j
Next i
End Sub
Private Function Tile(ByVal aPoint As Point) As clsTile
Return gBoard.Item("r" & aPoint.Y & "c" & aPoint.X)
End Function
In clsTile i have the following (as well as other items):
Private Function SurroundingTerrain(ByVal aTer As String) As clsTerrain
Return mySurroundings.Item(aTer) ' a small collection (6 items of clsTerrain type)
End Function
Public Sub CheckDistance(ByRef aTile As clsTile)
SurroundingTerrain(aTile.Terrain).CheckDistance(CalcDistance(Location, aTile.Location))
End Sub
Private Function CalcDistance(ByVal myPoint As Point, ByVal aPoint As Point) As Double
Dim myReturn As Double = 0
Dim xDiff As Integer = 0
Dim yDiff As Integer = 0
Dim tDiff As Integer = 0
xDiff = Math.Abs(myPoint.X - aPoint.X)
yDiff = Math.Abs(myPoint.Y - aPoint.Y)
tDiff = xDiff + yDiff
myReturn = (MinInt(xDiff, yDiff) * 1.4) + (tDiff - MinInt(xDiff, yDiff))
Return myReturn
End Function
Private Function MinInt(ByVal a As Integer, ByVal b As Integer) As Integer
Dim myReturn As Integer = a
If b < myReturn Then
myReturn = b
End If
Return myReturn
End Function
in clsTerrain i have the following sub that is called:
Public Sub CheckDistance(ByVal aDist As Double)
If aDist < Distance Then
Distance = aDist
End If
End Sub
This runs and works file but as you can guess it runs so slow... I have been trying to work out how to make this run faster and i looked into threading/tasks but it doesnt seem to work. There are no errors but the objects don't appear to update correctly (or at all). The code i tried was:
In the main class:
Private Sub CheckSurroundings()
Dim tasks As New List(Of Task)
Dim pTile As clsTile
For Each pTile In gBoard
tasks.Add(Task.Run(Sub() TileToCheck(pTile)))
Next
Task.WaitAll(tasks.ToArray())
End Sub
Private Sub TileToCheck(ByRef aTile As clsTile)
For x As Integer = 1 To (xBoxes)
For y As Integer = 1 To (yBoxes)
aTile.CheckDistance(Tile(New Point(x, y)))
Next y
Next x
End Sub
Does anyone have any suggestions or ideas for how to get this to work?
Sorry for any headaches or facepalms caused...

What is wrong with my prime function

I'm a beginner in vb and I'm wondering why this code doesn't work.
I wrote the function which I can't seem to find why it doesn't. When I run the program, it seems to print out nothing.
I am supposed to find all the prime numbers between 1 and the input
Option Strict On
Public Class Lab4
Dim endCounter As Integer
Dim sum As Integer
Dim msg As String
Dim input As Integer
Public Function isPrime(input As Integer) As Boolean
endCounter = input - 1
For primeCounter As Integer = 1 To endCounter
If input Mod primeCounter <> 0 Then
Return True
Else
Return False
End If
Next
Return False
End Function
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
Me.Close()
End Sub
Private Sub btnPrime_Click(sender As Object, e As EventArgs) Handles btnPrime.Click
input = Convert.ToInt32(txtNumber.Text)
msg = "The prime numbers are: "
If input < 0 Then
msg = "Number cannot be negative!"
For inputCounter As Integer = 1 To input
If isPrime(inputCounter) = True Then
msg += inputCounter & " "
End If
Next
MsgBox(msg, , "Prime Number")
End Sub
End If
End Class
This test will always immediately return something on the very first test:
Public Function isPrime(input As Integer) As Boolean
endCounter = input - 1
For primeCounter As Integer = 1 To endCounter
If input Mod primeCounter <> 0 Then
Return True
Else
Return False
End If
Next
Return False
End Function
because you use Return immediately after the 'has modulus' line. Remove the Return True and else lines, so it only returns False if a modulus value is found. The very last line should be Return True – no modulus values are found, so it is a prime.
For this to work, you need to change your test to
If input Mod primeCounter == 0 Then
and change the start test from 1 to 2.
You don't need to test against 1, and you don't need to test all the way up to input or (you probably misunderstood something there) input - 1. The most logical endpoint is ceil(sqrt(input)), the next higher number of the square root of your starting value.

Count number of characters after specific character in textbox

using winforms / vb.net
I am trying to count how many characters exist in "textbox3" after a specific character "." in a textbox.
examples:
2adf = 0 (no "." exists)
2adf. = 0
2adf.2 = 1
2adf.2a = 2
2adf.2af = 3
2adf.2afe = 4
I already have a function to search if there is a "."
if (CountCharacter(TextBox3.Text, ".") = 1) then
'a "." exists so count number of characters after "."
end if
Public Function CountCharacter(ByVal value As String, ByVal ch As Char) As Integer
Dim cnt As Integer = 0
For Each c As Char In value
If c = ch Then cnt += 1
Next
Return cnt
End Function
I am not sure how to check the count after the "." though
You could use the string.IndexOf method for this task
Sub Main
Dim test = "2adf.2afe"
Dim result = CountCharsAfter(test, "."c)
Console.WriteLine(result)
End Sub
Public Function CountCharsAfter(input as string, charToSearch as Char) as Integer
DIm pos = input.LastIndexOf(charToSearch)
if pos = -1 then
return 0
else
return input.Length - (pos + 1)
End if
End Function
Try this
Dim NoChar As Integer = CalculateChra("12adf.2afe", ".")
Private Function CalculateChra(ByVal V_String As String, ByVal LastChar As Char) As Integer
Dim Start As String = Split(V_String, LastChar)(0) & "."
Dim M As String = V_String.Substring(Start.Length)
Return M.Length
End Function
dim n,cnt as integer
n=0
cnt=0
Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
If e.KeyChar = Chr(46) Then
n = Len(TextBox1.Text)
End If
If n <> 0 Then
cnt += 1
End If
MsgBox(" no.of charectors after '.' is/are : " & cnt - 1)
End Sub

vb .net permutation of string. permutation or combination?

i've got arary of string like this C - F - A - M. i want to create a combination from that with condition:
each other item beside last character has to be combined with last character
there's not allowed a same combination, even the order is different. for example
FC - M
CF - M
if the string array contains >=3 element it will generate 2 & 3 itemset, if 2 element then it will generate only 2 itemset
below is my code. my code generate the result like right part of the picture
my question is what method should i use? is it permutation, combination, or other things?
and in pseudocode, what is my case would be like?
here's my code
Public Class permute
Dim ItemUsed() As Boolean
Dim pno As Long, pString As String
Dim inChars() As Char = {"c", "f", "a", "m"}
Private Sub permute_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Sub Permute(ByVal K As Long)
ReDim ItemUsed(K)
pno = 0
Dim i As Integer
For i = 2 To K
Permutate(i, 1)
tb.Text = K
Next
End Sub
Private Sub Permutate(ByVal K As Long, ByVal pLevel As Long)
Dim i As Long, Perm As String
Perm = pString
For i = 0 To K - 1
If Not ItemUsed(i) Then
If pLevel = 1 Then
pString = inChars(i)
Else
pString += inChars(i)
End If
If pLevel = K Then
pno = pno + 1
Results.Text += _
pno & " " & " = " & " " & pString & vbCrLf
Exit Sub
End If
ItemUsed(i) = True
Permutate(K, pLevel + 1)
ItemUsed(i) = False
pString = Perm
End If
Next
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Permute(tb.Text)
End Sub
Private Sub tb_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tb.TextChanged
If tb.Text = "" Then
Results.Text = ""
Else
Permute(tb.Text)
End If
End Sub
End Class
here's the requirement screenshot
and here's the program screenshot
Add this class to your project:
Public NotInheritable Class Permutation
Public Shared Function Create(array As Char()) As List(Of String)
Return Permutation.Create(array, False)
End Function
Public Shared Function Create(array As Char(), sort As Boolean) As List(Of String)
If (array Is Nothing) Then
Throw New ArgumentNullException("array")
ElseIf ((array.Length < 0) OrElse (array.Length > 13)) Then
Throw New ArgumentOutOfRangeException("array")
End If
Dim list As New List(Of String)
Dim n As Integer = array.Length
Permutation.Permute(list, array, 0, array.Length)
If (sort) Then
list.Sort()
End If
Return list
End Function
Private Shared Sub Permute(list As List(Of String), array As Char(), start As Integer, n As Integer)
Permutation.Print(list, array, n)
If (start < n) Then
Dim i, j As Integer
For i = (n - 2) To start Step -1
For j = (i + 1) To (n - 1)
Permutation.Swap(array, i, j)
Permutation.Permute(list, array, (i + 1), n)
Next
Permutation.RotateLeft(array, i, n)
Next
End If
End Sub
Private Shared Sub Print(list As List(Of String), array As Char(), size As Integer)
If (array.Length <> 0) Then
Dim s As Char() = New Char(size - 1) {}
For i As Integer = 0 To (size - 1)
s(i) = array(i)
Next
list.Add(s)
End If
End Sub
Private Shared Sub RotateLeft(array As Char(), start As Integer, n As Integer)
Dim tmp As Char = array(start)
For i As Integer = start To (n - 2)
array(i) = array(i + 1)
Next
array(n - 1) = tmp
End Sub
Private Shared Sub Swap(array As Char(), i As Integer, j As Integer)
Dim tmp As Char
tmp = array(i)
array(i) = array(j)
array(j) = tmp
End Sub
End Class
Because of the Int32.MaxValue limit this class will support levels 1 through 13.
s=1, n=1
s=2, n=2
s=3, n=6
s=4, n=24
s=5, n=120
s=6, n=720
s=7, n=5040
s=8, n=40320
s=9, n=362880
s=10, n=3628800
s=11, n=39916800
s=12, n=479001600
s=13, n=6227020800
Usage:
Me.TextBox1.Text = String.Join(Environment.NewLine, Permutation.Create({"c"c, "f"c, "a"c, "m"c}, sort:=False))
Output:
cfam
cfma
cafm
camf
cmfa
cmaf
fcam
fcma
facm
famc
fmca
fmac
acfm
acmf
afcm
afmc
amcf
amfc
mcfa
mcaf
mfca
mfac
macf
mafc
The class is based on C++ code from the following link:
Calculating Permutations and Job Interview Questions
This seems to be a Combination problem rather than Permutation :
"In mathematics, a combination is a way of selecting several things out of a larger group, where (unlike permutations) order does not matter". [Wikipedia]
Try to solve this by doing Combination to all item in array except the last item. Or in other words, do Combination operations nCk for all k, with
n = size of input array minus the last item
k = size of the output itemset, minimum k is 1 and maximum is n
Then append each Combination result with the last item. Following is the pseudocode code, using C# syntax :p
var input = new char[] {'C', 'F', 'A', 'M'};
//save last char
var lastChar = input[input.Length - 1];
//combinationInput is input member without the last character
var combinationInput = new char[input.Length - 1];
Array.Copy(input, 0, combinationInput, 0, combinationInput.Length);
//generate output with itemset size 1 to combinationInput.Length
for (int i = 1; i <= combinationInput.Length; i++)
{
//generate combination with size i
var combinationOutput = combinationInput.Combinations(i);
foreach (var combinedChar in combinationOutput)
{
//print output as: combinationOutput item + lastChar
Console.WriteLine(string.Join(", ", combinedChar) + ", " + lastChar);
}
}
References :
Array.Copy(...). [How to copy part of an array to another array]
.Combinations(int outputSize) extension method. [How to Generate Combinations of Elements of a List in .NET 4.0]

My program is assigning a value to ALL objects in an array. What's happening and how do I prevent it ? (VB 2008)

I have exhausted all of my options and am very desperate for help since I cannot figure out where the bug in my code is, or if there is something I don't understand.
I'm trying to create a "methinks it is a weasel!" mimmick from Richard Dawkins' late 80s documentary about evolution. The goal is to progress through a genetic algorithm until the algorithm guesses the correct answer through mutation and fitness tournaments.
Now, here's the problem:
Private Function fitnessTourney(ByVal editGuess() As Guess, ByVal popIndex As Integer, ByVal tourneySize As Integer, ByVal popNum As Integer)
Dim randInt(tourneySize - 1) As Integer
Dim loopCount1 As Integer = 0
Dim fitnessWinner As New Guess
fitnessWinner.setFitness(-50)
...
And, this loop is where I am experiencing the critical error
...
For i = 0 To tourneySize - 1
Randomize()
randInt(i) = Int(Rnd() * popNum)
While editGuess(randInt(i)).Used = True
If loopCount1 > tourneySize Then
loopCount1 = 0
For i2 = 0 To popNum - 1
editGuess(i2).setUsed(False)
Next
i = -1
Continue For
End If
loopCount1 += 1
randInt(i) = Int(Rnd() * popNum)
End While
editGuess(randInt(i)).determineFitness(correctPhrase)
editGuess(randInt(i)).setUsed(True)
Next
For i = 0 To popNum - 1
editGuess(i).setUsed(False)
Next
What this loop is trying to do is pick out four random instances of the editGuess array of objects. This loop tries to prevent one from being used multiple times, as the population is competing to one of the 10 members (highest fitness of the 4 chosen candidates is supposed to win).
The critical error is that I mysteriously get an endless loop where any instances of editGuess(randInt(i)).Used will always evaluate to true. I have tried to fix this by resetting all instances to False if it loops too many times.
The stumper is that I'll have all instances evaluate to False in the debugger. Then, when I reach "editGuess(randInt(i)).setUsed(True)" (the exact same thing as "editGuess(randInt(i)).Used = True"), it sets this value for EVERY member of the array.
Is there anyone who can see what is happening? I am so close to completing this!
Here's the Guess class:
Public Class Guess
Dim Fitness As Integer
Dim strLength As Integer
Dim strArray(30) As String
Dim guessStr As String
Dim Used As Boolean
Public Sub New()
Fitness = 0
guessStr = ""
strLength = 0
Used = 0
End Sub
Public Sub determineFitness(ByVal correctPhrase As String)
Dim lowerVal
If guessStr.Length <= correctPhrase.Length Then
lowerVal = guessStr.Length
Else
lowerVal = correctPhrase.Length
End If
strArray = guessStr.Split("")
Fitness = 0 - Math.Abs(correctPhrase.Length - guessStr.Length)
For i = 0 To lowerVal - 1
If correctPhrase(i) = guessStr(i) Then
Fitness = Fitness + 1
End If
Next
End Sub
Public Sub Mutate(ByVal mutatepercentage As Decimal, ByVal goodLetters As String)
If mutatepercentage > 100 Then
mutatepercentage = 100
End If
If mutatepercentage < 0 Then
mutatepercentage = 0
End If
mutatepercentage = mutatepercentage / 100
If Rnd() < mutatepercentage Then
strLength = Int(Rnd() * 25) + 5
If strLength < guessStr.Length Then
guessStr = guessStr.Remove(strLength - 1)
End If
End If
For i = 0 To strLength - 1
If Rnd() < mutatepercentage Then
If i < guessStr.Length Then
guessStr = guessStr.Remove(i, 1).Insert(i, goodLetters(Int(Rnd() * goodLetters.Length)))
Else
guessStr = guessStr & goodLetters(Int(Rnd() * goodLetters.Length))
End If
End If
Next
End Sub
Public Sub setFitness(ByVal num As Integer)
Fitness = num
End Sub
Public Sub setStrLength(ByVal num As Integer)
strLength = num
End Sub
Public Sub initializeText()
End Sub
Public Sub setUsed(ByVal bVal As Boolean)
Used = bVal
End Sub
End Class
And, finally, here's where and how the function is called
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
population1(counter) = fitnessTourney(population1, counter, 4, 10)
population2(counter) = fitnessTourney(population2, counter, 4, 10)
population1(counter).Mutate(2, goodLetters)
population2(counter).Mutate(20, goodLetters)
Label1.Text = population1(counter).guessStr
Label2.Text = population2(counter).guessStr
counter += 1
If counter > 9 Then
counter = 0
End If
End Sub
End Class
EDIT 1:
Thank you guys for your comments.
Here is the custom constructor I use to the form. This is used to populate the population arrays that are passed to the fitnessTourney function with editGuess.
Public Sub New()
InitializeComponent()
Randomize()
For i = 0 To 9
population1(i) = New Guess
population2(i) = New Guess
Next
counter = 0
correctPhrase = "Methinks it is a weasel!"
goodLetters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ !##$%^&*()_+-=?></.,;\|`'~"
goodLettersArr = goodLetters.Split("")
For i = 0 To 9
population1(i).setStrLength(Int(Rnd() * 25) + 5)
population2(i).setStrLength(Int(Rnd() * 25) + 5)
For i2 = 0 To population1(i).strLength
population1(i).guessStr = population1(i).guessStr & goodLetters(Int(Rnd() * goodLetters.Length))
Next
For i2 = 0 To population2(i).strLength
population2(i).guessStr = population2(i).guessStr & goodLetters(Int(Rnd() * goodLetters.Length))
Next
Label1.Text = population1(i).guessStr
Label2.Text = population2(i).guessStr
Next
population1(0).guessStr = correctPhrase
population1(0).determineFitness(correctPhrase)
End Sub
I haven't studied all of your code thoroughly, but one big problem is that you are calling Randomize from within the loop. Every time you call Randomize, it re-seeds the random numbers with the current time. Therefore, if you call it multiple times before the clock changes, you will keep getting the first "random" number in the sequence using that time which will always evaluate to the same number. When generating "random" numbers, you want to re-seed your random number generator as few times as possible. Preferably, you'd only seed it once when the application starts.
As a side note, you shouldn't be using the old VB6 style Randomize and Rnd methods. Those are only provided in VB.NET for backwards compatibility. You should instead be using the Random class. It's easier to use too. With the Random class, you don't even need to call a randomize-like method, since it automatically seeds itself at the point in time when you instantiate the object. So, in the case of the Random class, the thing to be careful is to make sure that you only instantiate the object once before entering any loop where you might be using it. If you create a new Random object inside a loop, it will similarly keep generating the same numbers.