Why does ".Remove" affect all the items in a 2D structure assigned with a list? - vb.net

I'm currently trying to create a Sudoku Solver, and on the step of assigning some possible values to a box that is not already preoccupied. (Bit of background info for why I'm doing this shebang: Sudoku is a number game based on a 9x9 grid, its contextual rules allow certain boxes in the grid that are not preoccupied to hold possible values during the process of solving )
To do this I created a structure, defined it as two dimensional, and populated it with a predefined list of integers using a for-loop.
Now when I tried to remove one integer from the list of a particular item in the two dimensional structure, I found out that all the lists of the items in the structure have had that integer removed. There's probably a simple solution to this, but I've been really struggling to find it. Hope the code below clarifies the somewhat confusing verbal explanation.
Structure Element
Dim PossibleValues As List(Of Integer)
Dim ElementValue As Integer
End Structure
Sub Main()
Dim List as New List(Of Integer)({1,2,3})
Dim TDP(8,8) as Element
For x as integer = 0 to 8
For y as integer = 0 to 8
TDP(x,y).PossibleValues = List
Next
Next
TDP(0,0).PossibleValues.Remove(1)
End Sub
Now I expect only TDP(0,0) would have a list of "2,3" when print out its list of integers, but when I check other items , i.e. TDP(1,0), its list is of integer is also "2,3"

Look at the assignment here:
TDP(x,y).PossibleValues = List
List(Of T) is a reference type, so this assigns a reference to the same List object to each of the array elements.
If you want each item to have it's own list of possible items, you need to either deep copy the list or create a new list:
Sub Main()
Dim TDP(8,8) as Element
For x as integer = 0 to 8
For y as integer = 0 to 8
TDP(x,y).PossibleValues = New List(Of Integer)({1,2,3})
Next
Next
TDP(0,0).PossibleValues.Remove(1)
End Sub

Related

How do I add a string input to an array?

basically i need to add a name to an array of candidates for an election. the user enters the candidates names, and i want to store them in an array. so far i have this:
Dim CandidateNames(candidates) As String
Dim x As Integer
'entering the names of each candidate so students can vote for them.
For x = 1 To candidates
Console.WriteLine("Enter a candidates name:")
CandidateNames(candidates) = Console.ReadLine()
Next
For x = 0 To candidates - 1
Console.WriteLine(CandidateNames(candidates) & " is candidate " & x)
Next
i want to then output all the names, which is what the second for loop does, but it only outputs the last entered name.
im in my second GCSE year of computer science, having never done any programming before so go easy on me please.
Here is the working code:
Dim candidates as Integer
candidates=5
Dim CandidateNames(candidates) As String
Dim x As Integer
For x = 0 To candidates
Console.WriteLine("Enter a candidates name:")
CandidateNames(x) = Console.ReadLine()
Next
For x = 0 To candidates
Console.WriteLine(CandidateNames(x) & " is candidate ")
Next
In your code, you are not storing and accessing the strings correctly.
There are two issues with your code. The first is with your loop bounds: the first loop is this:
For x = 1 to candidates
And the second loop is this:
For x = 0 to candidates - 1
In .NET, the lower bound for one-dimensional arrays is always 0 (insert rant about .NET array indexing design choices here), so you should be starting from 0 as in the second loop. I can never remember if VB arrays specify the upper bound or the count when you declare them, but conceptually the second is correct for the final index: if you want an array of n items, then it will be indexed from 0 to n - 1.
The second issue is that inside each loop, you are referring to CandidateNames(candidates) instead of CandidateNames(x). Instead of moving through each item in the loop in turn, you are only operating on the last item in the array.
Unless this is for an assignment requiring to use arrays, I'd suggest you consider using List(Of String) instead. Arrays make sense for a more limited set of uses cases, and I don't think this is one of them. Usually, the number of candidates for an election will be variable; with a list, you can have the user enter candidates until they're done, and the list will automatically expand as you go. Then, you can use a For Each loop to write out the contents of the list (though note you could use a For Each loop with an array as well). A list can still be accessed by index like an array.

Getting values from a multi column listbox VBA

I am in need of help, I am trying to get all three columns of my multi column list box in a for loop, it should be pretty simple but I cannot figure it out,
I have googled for hours and to be honest haven't gotten anywhere as everyone wants it to be able to select and then loop through where as i just want to loop through all of them and take them to separate strings,
Hope this makes sense,
Thank you,
You can cycle through entries in the list by using the script below and fill a new array which can be pasted to an assigned range on the sheet of the same size as the array
dim arrayctr as integer, i as integer, myarray() as variant
With mylistbox
'below sizes array to size of list in listbox.
'use arrctr to populate selected items to array without blank entries in between.
redim myarray(1 to .listcount, 1 to 1) as variant
'.listcount gives total entries, but list starts from 0 so use i-1 to get values
For i = 1 to .listcount
if .selected(i-1) = true then myarray(arrayctr) = .list(i-1): _
arrctr = arrctr + 1
Next i
End with
you can use For next loop through entries and use Exit For when the value of the array = "" so it handles only entries with data in and avoids pointless calculations.
I have had similar troubles with finding online answers to some questions such as this, I hope it helps!

Create a dictionary out of a list vb.net

i have a list with 2 columns (clm1=StoreID and clmn2=ProductID).
i need to loop through this list and create a dictionary(StoreID , List(of ProductID))
i am using vb.net . can you please help me with the loop i have to make?
The list data is something like
StoreID ProductID
1 234
2 456
1 222
3 768
1 100
9 876
e.t.c.
I assume that your data is stored somewhat like this:
Structure Item
Public StoreID As Integer
Public ProductID As Integer
End Structure
Dim l As List(Of Item)
Then you have two options. The first one is to create the dictionary by hand:
Dim dictionary As New Dictionary(Of Integer, List(Of Integer))
For Each item As Item In l
Dim subList As List(Of Integer)
Dim keyExists = dictionary.TryGetValue(item.StoreID, subList)
If keyExists Then
subList.Add(item.ProductID)
Else
subList = New List(Of Integer)
subList.Add(item.ProductID)
dictionary.Add(item.StoreID, subList)
End If
Next
Here, you just iterate all items. Check the dictionary if it already contains an entry for the store id. If so, just add the product id. If not, create an entry and then add the product id.
If you're not overly concerned with performance, you can use the following LINQ expression to create the dictionary:
Dim dictionary = l.GroupBy(Function(item) item.StoreID) _
.ToDictionary(Function(group) group.Key, _
Function(group) group.Select(Function(item) item.ProductID) _
.ToList())
You first group the elements by their StoreID. Then, the ToDictionary() method creates the dictionary. It takes two parameters. The first one is a function that specifies the key of each element. In this case, we want to use the group's key as the dictionary key (which is the store id). The second parameter is the value that is inserted in the dictionary. First, we use Select to map each Item to its ProductID (because we want to store product ids and not entire items. Then we call ToList() to generate a list from the items in the group.

vb.net Pair Combinations to Create All Possible Sets

I need help figuring out how to go about programming this problem. I have an unknown number of pairs. Each pair is a Length x Width. I want to create sets of every possible combination of either a Length or Width from each pair. Here is an example of what I'm trying to do:
If I input 3 pairs, (1x2) (3x4) (5x6) I would get the following sets:
(1,3,5) (1,3,6) (1,4,5) (1,4,6) (2,3,5) (2,3,6) (2,4,5) (2,4,6)
So if I had 4 pairs, it would create a total of 16 sets, etc. I need to be able to input each pair and after all pairs have been entered, I need it to print out the sets. It can never include both numbers from a given pair in the same set. How do I create a loop or is there a built in math function that could produce all possible sets from a given number of pair inputs? I hope I described the problem well enough but if not, please ask questions. Thanks
This is called Cartesian product.
For example, if we have two sets A and B, such that
A = {1,2}
B = {3,4}
Then the result of the Cartesian product A x B is equal to
A x B = {(1,3),(1,4),(2,3),(2,4)}
If now we want to make the Cartesian product between the result obtained above and a new set, for example:
N = {5,6}
The result of the Cartesian product A x B x N, is equal to
A x B = {(1,3),(1,4),(2,3),(2,4)}
N = {5,6}
──────────────────────────────────────────────────
A x B x N = {(1,3,5),(1,3,6),(1,4,5),(1,4,6),(2,3,5),(2,3,6),(2,4,5),(2,4,6)}
Each element of the first set must be paired with each element of the second set.
I have developed 4 solutions to the Cartesian product:
Using a mathematical model, but without recursion. This solution
vectors using calculating for each combination number.
Using recursion, with the Collections class.
using the List (Of ...) class, also with recursion.
These three solutions seemed to me difficult to explain to you.
Furthermore, it is very difficult for me to explain my thoughts in English, because my native language is Castilian.
So I made the effort to create another solution that does not use recursion, which was more simple and friendly for any programmer.
Finally, I could create a satisfactory solution. Easy to understand and without recursion.
It is also very versatile. Any number of sets is accepted, as required, from 2 onwards.
You can also use any number of items. This depends on the requirements of each developer.
I hope this 4th. solution I devised, will please you, esteemed colleagues.
Only need a ListBox1 within Form4. Here it is:
Public Class Form4
Private Sub Form4_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
'┌─────────── Temporary code for example ───────────┐
Dim Set_1 As List(Of String) = New List(Of String)
Dim Set_2 As List(Of String) = New List(Of String)
Dim Set_3 As List(Of String) = New List(Of String)
Set_1.Add("1")
Set_1.Add("2")
Set_2.Add("3")
Set_2.Add("4")
Set_3.Add("5")
Set_3.Add("6")
'└──────────────────────────────────────────────────┘
Dim Sets As List(Of Object) = New List(Of Object)
Sets.Add(Set_1)
Sets.Add(Set_2)
Sets.Add(Set_3)
Dim product As List(Of String) = Sets(0)
For i = 1 To Sets.Count - 1
product = CartesianProduct(product, Sets(i))
Next
For Each element As String In product
Me.ListBox1.Items.Add(element)
Next
End Sub
Private Function CartesianProduct(ByVal Set_A As List(Of String), ByVal Set_B As List(Of String)) As List(Of String)
Dim product As List(Of String) = New List(Of String)
For Each a As String In Set_A
For Each b As String In Set_B
product.Add(a & b)
Next
Next
Return product
End Function
End Class
Have a nice day! :)

Code optimisation removing duplicates in VB

I'm looking to optimise my code. Specifically this process
Calculate a group of locations (basically squares on a grid)
Have a list of all the locations that have been calculated
Then I go through all these locations, 1 at a time.
The issue I'm having is removing or not including duplicate locations in the list. I've tried having a list of integers (integers to represent the location) but it's still very slow. To give you an idea of the numbers: I'm talking at least 15,000 different location calculations and around 1,000,000 possible locations.
Any help on this would be much appreciated!
Here is how I remove duplicates from an string array, perhaps it will be of help to you:
Dim OneDimensionalTable(1000) As String
....
OneDimensionalTable = RemoveDuplicates(OneDimensionalTable)
.....
Private Function RemoveDuplicates(ByVal items As String()) As String()
Dim noDupsArrList As New ArrayList()
For i As Integer = 0 To items.Length - 1
If Not noDupsArrList.Contains(items(i).Trim()) Then
noDupsArrList.Add(items(i).Trim())
End If
Next
Dim uniqueItems As String() = New String(noDupsArrList.Count - 1) {}
noDupsArrList.CopyTo(uniqueItems)
Return uniqueItems
End Function