Index textboxes value (from two textboxes) - vb.net

I have the two textboxes:
First:
Textbox1.lines(0) = 50
Textbox1.lines(1) = 65
Textbox1.lines(2) = 41
Textbox1.lines(3) = 27
Textbox1.lines(4) = 6
Textbox1.lines(5) = 6
Second:
Textbox2.lines(0) = 27
Textbox2.lines(1) = 41
Textbox2.lines(2) = 65
Textbox2.lines(3) = 6
Textbox2.lines(4) = 50
Textbox2.lines(5) = 6
in a third textbox I should display the index that contains the values ​​from the first textbox, but in the second.
Textbox3.lines(0) = 4 (50 of the first textbox is on the second line (lines4)
Textbox3.lines(1) = 2 (65 of the first textbox is on the second line (lines2)
Textbox3.lines(2) = 1 (41 of the first textbox is on the second line (lines1)
Textbox3.lines(3) = 0 (27 of the first textbox is on the second line (lines0)
Textbox3.lines(4) = 3 (6 of the first textbox is on the second line (lines4)
Textbox3.lines(5) = 5 (6 of the first textbox is on the second line (lines5)
although it already exists on line 4 (Number 6), we will move next line, because that line has already been considered. or both index can be displayed.
or somehow the line value becomes null (0) so that it is not taken.
Code: it doesn't work properly, unfortunately.
For Each line In TextBox1.Lines
For l As Integer = 1 To TextBox1.Lines.Length - 1
If TextBox2.Lines(l) = line Then
TextBox3.AppendText(l)
End If
Next
Next

This should work :
For Each line In TextBox1.Lines
Dim i As Integer = 0
While (i < TextBox1.Lines.Length)
If TextBox2.Lines(i) = line Then
TextBox3.AppendText(i & Environment.NewLine)
Continue For
End If
i += 1
End While
Next
With Continue For, the code go to the for's next loop.
Or if you want to display all iterations :
For Each line In TextBox1.Lines
Dim i As Integer = 0
While (i < TextBox1.Lines.Length)
If TextBox2.Lines(i) = line Then
TextBox3.AppendText(i & " ")
End If
i += 1
End While
TextBox3.AppendText(Environment.NewLine)
Next

This approach uses a Dictionary with the number as the key, and a Queue of indices as the value.
When we first encounter a number from TextBox1, we build a queue of all indices where the number occurs in TextBox2. Then each time we encounter that number, we dequeue the next available number where it occurred. If there are none left, then we return -1.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim results As New List(Of String)
Dim occurrences As New Dictionary(Of Integer, Queue(Of Integer))
For Each number As String In TextBox1.Lines
If Not occurrences.ContainsKey(number) Then
occurrences.Add(number, New Queue(Of Integer))
For i As Integer = 0 To TextBox2.Lines.Count - 1
If TextBox2.Lines(i) = number Then
occurrences(number).Enqueue(i)
End If
Next
End If
If occurrences(number).Count > 0 Then
results.Add(occurrences(number).Dequeue)
Else
results.Add("-1")
End If
Next
TextBox3.Lines = results.ToArray
End Sub

I managed to do that as well with the help of a list. In order to work, the number of lines must be equal.
Dim valI As New List(Of Integer)
For nIndex As Integer = 0 To Textbox2.Lines.Length -1
For i As Integer = 0 To TextBox1.Lines.Length - 1
If TextBox2.Lines(nIndex) = TextBox1.Lines(i) Then
If valI.Contains(i) Then
Else
valI.Add(i)
End If
End If
Next
Textbox3.AppendText(vbNewline & valI.Item(nIndex))
Next

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

Count a specific string in a multiline textbox (VB.Net)

I very much want to count the values in a multiline textbox each time each value appears in descending order> in ascending order. I tried a lot but nothing works as it should. (VB.Net)
Textbox1.Lines
2
3
2
2
4
7
7
7
28
28
Expected Output: Textbox2.Lines
2 = Count = 3
7 = Count = 3
28 = Count = 2
3 = Count = 1
4 = Count = 1
What i try and dind't worked.
#1
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
End If
Next
Return cnt
End Function
#2
Dim a As String = "this is test"
Dim pattern As String = "t"
Dim ex As New System.Text.RegularExpressions.Regex(pattern)
Dim m As System.Text.RegularExpressions.MatchCollection
m = ex.Matches(a)
MsgBox(m.Count.ToString())
#3
Public Shared Function StrCounter(str As String, CountStr As String) As Integer
Dim Ctr As Integer = 0
Dim Ptr As Integer = 1
While InStr(Ptr, str, CountStr) > 0
Ptr = InStr(Ptr, str, CountStr) + Len(CountStr)
Ctr += 1
End While
Return Ctr
End Function
You need to remember which strings have already appeared and then count them. To do that, you can use a dictionary.
Dim dict_strCount As Dictionary(Of String, Integer) = New Dictionary(Of String, Integer)()
' Run over each line in the input
For Each line As String In tb_yourTextBox.Text.Lines
' Check if we have already counted the string in this line
If dict_strCount.ContainsKey(line) Then
dict_strCount(line) += 1 ' if so, increment that count
Else
dict_strCount.Add(line, 1) ' if not, add it to the dictionary (with count of 1)
End If
Next
tb_yourOutputTextBox.Text = String.Empty ' clear the output
' run over all the elements in the dictionary in ascending order by value
' and output to the output textbox
For Each kvp As KeyValuePair(Of String, Integer) In dict_strCount.OrderBy(Function(x) x.Value)
tb_yourOutputTextBox.Text += kvp.Key & ": " & kvp.Value.ToString() & vbNewLine
Next
You may test it here

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

Could someone please explain this (VB)

I'm new to coding and have recently been curious about creating multiple permutations of a selection of characters. My solution had a lot of nested For Next loops which was clunky, so I searched other solutions and found the one below, however I cannot fully understand it.
Dim chars() As Char = "1234567890abcdefghijklmnopqrstuvwxyz".ToCharArray
Dim csize As Integer = chars.Length - 1
Dim upto As String
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
upto = " "
Dim max_length As Integer = 25
For i = 1 To max_length
bf_recursion(0, i)
Update()
Next
End Sub
Private Sub bf_recursion(ByVal index As Integer, ByVal depth As Integer)
Dim current() As Char = upto.ToCharArray()
For i = 0 To csize
current(index) = chars(i)
upto = CStr(current)
TextBox1.Text = (CStr(current))
TextBox1.Refresh()
Me.Refresh()
'\\lblOutput.Text = CStr(current)
If index <> (depth - 1) Then
bf_recursion(index + 1, depth)
End If
Next
End Sub
I do not understand the section where Current(Index) = Chars(i) since from my understanding it is making the Current(index) value stored in that index equal to the value in the characters, however somehow in the next line is creates a string from the Current(index) value that produces the correct result.
Help would be greatly appreciated, thank you.
Ok, I had to copy your code to see the result as I wasn't sure what you were trying to do, but let's get it explaining.
For the first cycle we have:
csize = 35
index = 0
depth = 1
The loop is easy enough: you loop from 0 to 35 (35 included)
For i = 0 To csize
At Index 0of context, you store the character at position i
current(index) = chars(i)
So when looping, this will give this result:
current(0) = "1" 'i = 1
current(0) = "2" 'i = 2
...
current(0) = "a" 'i = 11
current(0) = "b" 'i = 12
the CStr function changes the array current to a string by placing all elements one after each other:
upto = CStr(current)
Label1.Text = (CStr(current))
Label1.Refresh()
Me.Refresh()
Then comes the recursive part, but for the first loop, we don't need it...
If index <> (depth - 1) Then
bf_recursion(index + 1, depth)
End If
Next
Ok, now we finished the first cycle, let's go the the 2nd one:
csize = 35
index = 0
depth = 2
What's the difference? Nothing, until we reach this code:
If index <> (depth - 1) Then
bf_recursion(index + 1, depth)
End If
In the code above, index isn't the same as depth - 1 anymore, so we go recursive, and ->important<- instead of passing index = 0, we pass index + 1! What difference does this make?
This time, we don't store our character at current(0) but at current(1):
current(index) = chars(i)
which gives:
current(1) = "1" 'i = 1
current(1) = "2" 'i = 2
...
current(1) = "a" 'i = 11
current(1) = "b" 'i = 12
But, as the line before we did this:
Dim current() As Char = upto.ToCharArray()
current(0) is already filled in! Because upto contains the first character. That's what this line is for:
upto = CStr(current)
In short:
-> You store the characters you calculated in the upto string.
-> Each time you enter bf_recursion, you recover the characters you already have
-> index is 1 larger each time, so you change the NEXT character
One important note
With your application, you create a very very long loop that the user can't terminate without killing the process. You might want to look into that.

There's a glitch when adding numerals to a line CSV (VB.NET)

All of the number 6's in column 6 (Item(5)) should be deleted, and the rest of the numbers should be increased by 1. However, when the process is completed, I check the file and the file is unchanged.
Dim liness As New List(Of String)(File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv"))
For Each line As String In liness
Dim item() As String = line.Split(","c)
Do
If item(5) = 6 Then
liness.Remove(line)
Else : Exit Do
End If
Exit Do
Loop
Console.WriteLine("Have you already entered the next school years, year 3's? (y/n)")
Dim year3s As String = Console.ReadLine
If year3s = "Y" Or year3s = "y" Then
For i As Integer = 1 To liness.Count - 1 'this will read to the end of the array list once
If item(5) > 3 And item(5) < 6 Then
item(5) = item(5) + 1
End If
Next
ElseIf year3s = "N" Or year3s = "n" Then
For i As Integer = 1 To liness.Count - 1 'this will read to the end of the array list once
If item(5) > 2 And item(5) < 6 Then
item(5) = item(5) + 1
End If
Next
End If
File.WriteAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv", liness)
Exit For
Next
Exit Do
ElseIf enter.Key = ConsoleKey.End Then
Console.Clear()
adminmenu()
End If
You are updating the 'item' array, but not the 'liness' list. When you write the new 'liness' list to the file, any changes you made to the 'item' array are ignored.
Also, you are writing the 'liness' list back to the file for every loop iteration - this has to be wrong - you probably want to do that after the loop.
While I don't condone using the Split() function for parsing CSV data, I'll leave that part alone here in order to highlight other improvements in the code:
Dim minYear As Integer = 2
Console.WriteLine("Have you already entered the next school years, year 3's? (y/n)")
If Console.ReadLine().ToUpper().Trim() = "Y" Then minYear = 3
Dim NewLines = File.ReadLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv").
Select(Function(l) l.Split(","c) ).
Where(Function(l) Integer.Parse(l(5)) <> 6 ).
Select(Function(l)
Dim x As Integer = Integer.Parse(l(5))
If x >= minYear Then x += 1
l(5) = x.ToString()
Return String.Join(",", l)
End Function).ToList()
File.WriteAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv", NewLines)