Adding items to a multidimensional array from a textfile in Visual Basic - vb.net

I have this textfile:
Paul George|2.87|29
Stephen Curry|2.85|28
Jamal Murray|2.72|21
PJ Tucker|2.72|11
Kyle Lowry|2.61|15
Game
Paul George|g2d|g2p
Stephen Curry|g2d|g2p
Jamal Murray|g2d|g2p
PJ Tucker|g2d|g2p
Kyle Lowry|g2d|g2p
Game
Paul George|g3d|g3p
Stephen Curry|g3d|g3p
Jamal Murray|g3d|g3p
PJ Tucker|g3d|g3p
Kyle Lowry|g3d|g3p
Game
Paul George|g4d|g4p
Stephen Curry|g4d|g4p
Jamal Murray|g4d|g4p
PJ Tucker|g4d|g4p
Kyle Lowry|g4d|g4p
I want to add the items to the arrays
Names(name, gamenumber)
Distance(distance, gamenumber)
Points(Points, gamenumber)
with the first index being the data for the player, and the second being the game that data is from
For example,
distance(1, 0) = 2.87
distance(5, 0) = 2.61
distance(1, 1) = g2d
So that the indexes match up with the player for the given game number.
So far I have:
Private Sub openFile_Click(sender As Object, e As EventArgs) Handles openFile.Click
OpenFileDialog.ShowDialog()
Dim strFileName = OpenFileDialog.FileName
Dim objReader As New System.IO.StreamReader(strFileName)
Dim textline As String
Dim Names(100, 3) As String
Dim Distance(100, 3) As String
Dim Points(100, 3) As String
Dim Count As Integer = 0
Dim GameNumber As Integer = 0
Do While objReader.Peek() <> -1
textline = objReader.ReadLine() & vbNewLine
If textline = "Game" Then
GameNumber = GameNumber + 1
Else
Dim parts() As String = textline.Split("|")
Names(Count, GameNumber) = parts(0)
Distance(Count, GameNumber) = parts(1)
Points(Count, GameNumber) = parts(2)
Count = Count + 1
End If
Loop
End Sub
The parts of each line are split up by |, putting them into "parts", it then assigns the three parts it gets from the line (the player name, distance, and points) into there separate arrays as
Names(<Name>, 0)
Distance(<Distance>, 0)
Points(<Points>, 0)
It continues down the textfile but IF the line = "Game" it should, increment GameNumber, and then move to the next line, continuing to add the data, instead as
Names(<Name>, 1)
Distance(<Distance>, 1)
Points(<Points>, 1)
and so on, but it my code isn't working. After getting this working, I wont it to print the desired Game statistics for the players on the page in a listbox with something like:
For n = 0 To Count - 1
lstNames.Items.Add(Names(n, GameWanted))
lstNames.Items.Add(" ")
lstDistance.Items.Add(Distance(n, GameWanted) + " Miles")
lstDistance.Items.Add(" ")
lstPoints.Items.Add(Points(n, GameWanted))
lstPoints.Items.Add(" ")
Next

This would become a lot easier if you create a class representing your player and index them with a dictionary
Class Player
Public Property Distances as List(Of Decimal)
Public Property Points as List(Of Integer)
Public Property Name as String
Public Sub New(n as String)
Name = n
Distances = New List(of Decimal)
Points = New List(of Integer)
End sub
End class
And then in your method that reads your file:
Dim d as new Dictionary(of String, Person)
ForEach line as String in File.ReadAllLines(...)
Dim bits = line.Split("|"c)
If bits.Length < 3 Then Continue For
If Not d.ContainsKey Then d.Add(bits(0), New Person(bits(0))
Dim p = d(bits(0)) 'retrieve the old or just added person
p.Distances.Add(decimal.parse(bits(1)))
p.Points.Add(integer.parse(bits(2)))
Next line
Note; I'm a c# programmer and seldom do vb any more. I code with array indexes starting at 0, if you're on 1 base indexing, add one to the indexes above. This code should probably be treated as pseudocode; it was written on a cellphone from a 5 year old memory of what vb looks like and might have a raft of vb syntax errors(sorry) or take the long way round to do things that we have shorter sybtaxes for these days (list initializers etc)
At the end of this loop through all the file you will have a dictionary of your people, one per name encountered. Each person will have a list of scores and distances. If you want to add them up or average them add a Function to person class that iterates the list and returns the result, and to print them all out do a
foreach s as string in d.Keys
Console.Write(d(s).Name & " got avg distance " & d(s).GetAverageDist())
Or similar
To print out all their distances:
foreach s as string in d.Keys
foreach dis as decimal in d(s).Distances
Console.Write(d(s).Name & " got distance " & dis)
This is object oriented programming; we model the world using classes to represent things and do useful stuff. We don't try to collect data together in 20 different arrays and tie it all together with indexes etc - that's a very procedural code mindset and the opposite of what vb.net was invented for
It's likely actually that this falls short of a proper solution and is also somewhat hypocritical because I use two lists to track distance and points and assert that the list indexes are equal - the distance at index 3 and the points at index 3 are from game 4 (zero based indexing note)
What we really should do is also define a GameResult class and it have properties of distance, points and gamenumber, then each person class has a single List(of GameResult) - person could have a function that returns a nicely formatted score card for that person - that's proper OO :)

Related

Vb.net Data is not being incremented and added to list

I'm having an issue trying to create a program that takes user input for a text file's location containing medical records. The diseases and number of patients are being added to a list. I'm having an issue where my console is printing 0 for both the total of XX unique diseases and YYY patient encounters. I am not getting any errors, just not the correct output.
I believe my issue is in my processData() sub, however I am unsure why it's printing back 0. Also, how do I go about keeping track of duplicate diseases that are added to the list as I'm trying to add a counter next to each time the disease is seen.
Sample from Disease.txt
3710079 JUDITH CLOUTIER 2012-08-04 Spastic Colonitis
3680080 VIRGINIA ALMOND 2012-07-25 Chronic Phlegm
3660068 ELLEN ENGLEHARDT 2012-04-06 Whooping Cough
3810076 LILLIAN KEMMER 2014-07-04 Scurvy
3630055 TERESA BANASZAK 2012-06-15 Scurvy
Output:
There were a total of 0 unique diseases observed.
A total of 0 patient encounters were held
Main():
' Global variables
Dim inputFile As String
Dim patientCounter = 0
Dim diseaseList As New List(Of String)
Dim dateList As New List(Of Date)
Sub Main()
Dim reportFile As String
Dim yn As String
Console.ForegroundColor = ConsoleColor.Yellow
Console.BackgroundColor = ConsoleColor.Blue
Console.Title = "Medical Practice Data Analysis Application"
Console.Clear()
Console.WriteLine("Please enter the path and name of the file to process:")
inputFile = Console.ReadLine
If (File.Exists(inputFile)) Then
' Call to processData sub if input file exists
processData()
Console.WriteLine(vbCrLf & "Processing Completed...")
Console.WriteLine(vbCrLf & "Please enter the path and name of the report file to generate")
reportFile = Console.ReadLine
File.Create(reportFile).Dispose()
If (File.Exists(reportFile)) Then
Console.WriteLine(vbCrLf & "Report File Generation Completed...")
Else
' Call to sub to end program if directory does not exist
closeProgram()
End If
' Get user input to see report
Console.WriteLine(vbCrLf & "Would you like to see the report file [Y/n]")
yn = Console.ReadLine
' If user inputs "y" or "Y" then print report
' Otherwise close the program
If (yn = "y" OrElse "Y") Then
printFile()
Else
closeProgram()
End If
Else
' Call to sub to end program if file does not exist
closeProgram()
End If
Console.ReadLine()
End Sub
processData Sub():
Public Sub processData()
Dim lines As String() = File.ReadAllLines(inputFile)
Dim tab
Dim dates
Dim diseaseCounter = 0
For Each line As String In lines
tab = line.Split(vbTab)
patientCounter += 1
dates = Date.Parse(line(3))
dateList.Add(dates)
'diseaseList.Add(line(4))
Dim disease As New disease(line(4))
diseaseList.Add(disease.ToString)
'diseaseList(line(4)).
For Each value In diseaseList
'If value.Equals(line(4)) Then disease.counter += 1
Next
Next
Dim uniqueDiseases As String() = diseaseList.Distinct().ToArray
End Sub
Disease.class
Class disease
Dim counter As Integer = 0
Dim name As String = ""
Sub New(newDisease As String)
name = newDisease
counter = 0
End Sub
End Class
printFile()
Sub printFile()
Dim muchoMedical As String = "MuchoMedical Health Center"
Dim diseaseReport As String = "Disease Report For the Period " & "earliest_date" & " through " & "latest_date"
Console.WriteLine(vbCrLf & muchoMedical.PadLeft(Console.WindowWidth / 2))
Console.WriteLine(diseaseReport.PadLeft(Console.WindowWidth / 2))
Console.WriteLine(vbCrLf & "There were a total of " & diseaseList.Count & " unique diseases observed")
Console.WriteLine("A total of " & patientCounter & " patient encounters were held")
Console.WriteLine(vbCrLf & "Relative Histogram of each disease")
For Each disease As String In diseaseList
Console.WriteLine(vbCrLf & disease & vbTab & " ")
Next
End Sub
closeProgram()
Sub closeProgram()
Console.WriteLine(vbCrLf & "File does not exist")
Console.WriteLine("Press Enter to exit the program...")
Console.ReadLine()
End Sub
You don't need a disease class, really, if the most complicated thing you are doing is counting disease occurrences (your disease class had no public members so I don't know what you were doing there anyway). You can simply do everything with a little LINQ.
' processing section
Dim lines = File.ReadAllLines(inputFile)
Dim splitLines = lines.Select(Function(l) l.Split({vbTab}, StringSplitOptions.RemoveEmptyEntries))
Dim diseaseGrouping = splitLines.GroupBy(Function(s) s(3))
Dim patients = splitLines.Select(Function(s) s(1))
Dim dates = splitLines.Select(Function(s) DateTime.Parse(s(2)))
' report section
Dim padAmount = CInt(Console.WindowWidth / 2)
Dim muchoMedical As String = "MuchoMedical Health Center"
Dim diseaseReport As String = $"Disease Report For the Period {dates.Min():d} through {dates.Max():d}"
Console.WriteLine()
Console.WriteLine(muchoMedical.PadLeft(padAmount))
Console.WriteLine(diseaseReport.PadLeft(padAmount))
Console.WriteLine()
Console.WriteLine($"There were a total of {diseaseGrouping.Count()} unique diseases observed.")
Console.WriteLine($"A total of {patients.Count()} patient encounters were held")
For Each diseaseAndCount In diseaseGrouping
Console.WriteLine()
Console.WriteLine($"{diseaseAndCount.Key}{vbTab}{diseaseAndCount.Count()}")
Next
I think your disease name is in index 3. You were looking at 4 originally. Maybe you have a tab between first and last name? Change it if I was wrong. This may apply to any or all of the indices.
Output:
MuchoMedical Health Center
Disease Report For the Period 4/6/2012 through 7/4/2014
There were a total of 4 unique diseases observed.
A total of 5 patient encounters were held
Spastic Colonitis 1
Chronic Phlegm 1
Whooping Cough 1
Scurvy 2
I think the main issue with your code as listed above is that in the processData sub you have:
For Each line As String In lines
tab = line.Split(vbTab)
patientCounter += 1
dates = Date.Parse(line(3))
dateList.Add(dates)
'diseaseList.Add(line(4))
Dim disease As New disease(line(4))
diseaseList.Add(disease.ToString)
'diseaseList(line(4)).
For Each value In diseaseList
'If value.Equals(line(4)) Then disease.counter += 1
Next
Next
I think you more likely mean to use tab(3) and tab(4) instead of line(3) and line(4) etc. You split the line into the "tab" variable but then don't use it. While you could rewrite everything and handle it differently, if you want to go with what you've got, I think that's your core error.
I liked your idea of a class. You can wrap up all your data in one list. I enhanced your class so it could contain all the data in the file. Public Properties are automatic properties that have Get, Set, and the Private fields that hold the data written by the compiler. I have added an Overrides of the .ToString because you were not getting the results you expected. We have the parameterized constructor like you have except expanded to include all the properties.
The magic comes in the Linq query. The d stands for an item in the diseaseList which is an instance of the Disease class. Then I added an order by clause which will produce the results in alphabetical order by DiseaseName which is a string. Grouping by the unique DiseaseName into a Group with Count.
Notice in the second For Each loop we have all the properties of the class available.
I happened to be in a Windows Forms app so I used Debug.Print. Just replace with Console.WriteLine. I leave to you the fancy formatting if you desire.
Public Class Disease
Public Property Name As String
Public Property DiagnosisDate As Date
Public Property DiseaseName As String
Public Property ID As Integer
Public Sub New(PatientID As Integer, PatientName As String, dDate As Date, sDisease As String)
ID = PatientID
Name = PatientName
DiagnosisDate = dDate
DiseaseName = sDisease
End Sub
'If you don't override ToString you will get the fully qualified name of the class
'You can return any combination of the Properties as long as the end
'result is a string
Public Overrides Function ToString() As String
Return Name
End Function
End Class
Public Sub processData()
Dim lines As String() = File.ReadAllLines(inputFile)
Dim diseaseList As New List(Of Disease)
For Each line As String In lines
'I was having trouble with the tabs so I changed it to a comma in the file
'3710079,JUDITH CLOUTIER,2012-08-04,Spastic Colonitis
'the small c following the "," tells the compiler that this is a Char
Dim tab = line.Split(","c)
Dim inputDate = Date.ParseExact(tab(2), "yyyy-MM-dd", CultureInfo.InvariantCulture)
Dim Studentdisease As New Disease(CInt(tab(0)), tab(1), inputDate, tab(3))
diseaseList.Add(Studentdisease)
Next
Dim diseaseGrouping = From d In diseaseList
Order By d.DiseaseName
Group By d.DiseaseName
Into Group, Count
For Each diseaseAndCount In diseaseGrouping
Debug.Print($"{diseaseAndCount.DiseaseName} {diseaseAndCount.Count()} ")
For Each d In diseaseAndCount.Group
Debug.Print($" {d.Name}, {d.DiagnosisDate.ToShortDateString}")
Next
Next
End Sub

Poker Hand evaluation through LINQ

I am creating a poker game - Texas Holdem (5 cards on the table and 2 cards for myself).
I've already created flush, straight and straight flush functions and I got stuck on evaluating if the hand has a:
1. Four of a kind
2. Three of a kind
3. Full house
4. Two pairs
5. One pair
I believe I can write one function for all of the above, that will return a corresponding string.
I have created a list that holds list of Cards (7 cards)
Class Card has a property cardNumber of Integer type (Ace = 1, Two = 2, Three = 3 etc)
Here is my function:
Public Shared Function ofAKind(hand As List(Of Card)) As String
Dim result As String = ""
Dim counter As Integer
Dim IntegerList As New List(Of Integer)
'creating a list of integers that are representing faces of cards
Do
IntegerList.Add(hand.Item(counter).cardNumber)
counter += 1
Loop Until counter = hand.Count
Dim groupedIntegers = From Int In IntegerList
Group By Int
Into grouping = Group, Count()
'and here is my problem: how can I make such a grouping? below is just pseudocode.
'When using a debugger, I see that it groups them well. It is just that I do not know
'how to use LINQ to extract that grouping into the below if statement and get a corresponding string.
'if grouping = 4 Then
'result = "Four of a kind"
'if grouping = 3 andAlso grouping = 2 Then
'result = "Full House"
'if grouping = 2 andAlso grouping = 2 Then
'result = "Two Pairs"
'if grouping = 2 Then
'result = "Pair"
Return result
End Function
For the lack of being able to comment.
Possibly String.Concat all of the card Values together (with whitespace in-between each) and use a Regex.Matches(...) with match code "\d" to match the Numbers
Then Array.ForEach(...) for the Groups() with an in-line If[...] to count the occurrences in each group and test if it has particular combinations of matches.
It may be a little tedious, and a long in-line Linq, but just a thought :p
I figured it out. I am sure it can be done in a cleaner way, but it worked for me. At this phase of my programming discovery - this is a next milestone achieved. Thanks to Plutonix. Appreciate it.
Public Function ofAKind(IntegerList As List(Of Integer)) As String
Dim result As String = "YES"
Dim groupedIntegerList As New List(Of Integer)
Dim groupedIntegers = From Int In IntegerList
Group By Int
Into LOL = Group, Count()
'creating another list (I am sure there is a cleaner way, but I don't know it yet)
For Each e In groupedIntegers
groupedIntegerList.Add(e.Count)
Next
If groupedIntegerList.Contains(3) And groupedIntegerList.Contains(2) Then
result = "Fullhouse!"
ElseIf groupedIntegerList.Contains(4) Then
result = "Four of a kind!"
ElseIf groupedIntegerList.Contains(3) Then
result = "Three of a kind"
ElseIf groupedIntegerList.Contains(2) Then
result = "Pair!"
End If
'ugly way to search for two pairs (but it works)
If result = "Pair!" Then
Dim searchingForTwoPairs = From int In groupedIntegerList
Where int > 1
Group By int
Into LOL2 = Group, Count()
Dim twoPairsList As New List(Of Integer)
For Each e In searchingForTwoPairs
twoPairsList.Add(e.Count)
Next
If twoPairsList.Contains(2) Or twoPairsList.Contains(3) Then
result = "Two pairs!"
End If
End If
Return result
End Function

Jagged Array Sorting w/ Primary,Secondary,Tertiary Criterion

Disclaimer: My background as a programmer is limitted to 1 university course in C++, and hobbyist vb.net macro programming.
My goal is to be able to take a bunch of data from a BOM, sort it conditionally, and then return a simple list with the document names.
I've come across some good information on LINQ and iComparable for structures/strings but could use some further guidance in what I need to do to make this happen.
Essentially it will be a multi level sort with some logic like:
-> Put objects with 'Drawing' = True first.
-> Sort then by ComponentDefinition/Secondary document desciber;
(ie; assemblies and weldments, then plate, then structural steel, then hardware).
-> Sort Assemblies and weldments by Renamed vs Matl'l Spec then by weight
-> Sort Structural by type, then by size
-> Sort hardware by nomial size, then by type, then by thread unc/unf, then by length
-> Put the remainder last (ie; virtual components.
From what I've read, it seems like I can accomplish this by multiple sets of linq's if I can get it working,
Or I can use a Compare function and just compare each line in its entirety to the next (as my understand of it would suggest?)
So at the end of the day, I would want a list to spit out something like:
1) Drawing - Weldment - Named - Weight
2) Drawing - Assembly - Named - Weight
3) Drawing - Assembly - Unnamed - Weight
4) Drawing - Weldment - unnamed - weight
5) Drawing - Plate - 1" Thick x 48 sq in.
6) Drawing - Plate - 1" Thick x 36 sq in.
7) No Drawing - Plate - 1" Thick X 52 in
8) No Drawing - Plate - 1/2" thick X 52 in
9) No Drawing - 1/2" Bolt - UNC - 3"
10) No Drawing - 1/2" Bolt - UNC - 2"
11) No Drawing - 1/2" Nut - UNC
12) No Drawing - 1/2" Washer
13) No Drawing - 1/4" Bolt - UNC - 2"
14) No Drawing - Virtual Component
By using the Case 0 as the next level, and making a tree sort seems like the right way to do it, as long as I can get the basic tree working.
That way, I'm only sorting items based on how they ended up in the previous sort. (No need to go any further if I'm comparing an assembly to hardware as would be the secondary level of my sort after the Drawing/NoDrawing sort)
This is as far as I have gotten, and If I can figure out how to get this working, I'm thinking I'm likely set to go on from here
'Jagged Array Sorting with Tag Array
Sub Main()
Dim oBOMRowCount As Integer = 4
Dim oBOMFactorArray As Double(oBOMRowCount-1)(){}
oBOMFactorArray(0) = {"2", "5"}
oBOMFactorArray(1) = {"1", "5"}
oBOMFactorArray(2) = {"1", "2"}
oBOMFactorArray(3) = {"2", "7"}
Dim tagArray() As Integer = {0, 1, 2, 3}
' Initialize the comparer and sort
Dim myComparer As New RectangularComparer(oBOMFactorArray)
Array.Sort(tagArray, myComparer)
Dim i As Integer
For j = 0 To 3
oLine = ""
For i = 0 To 1
If oLine = ""
oLine = "oList[" & (oBOMFactorArray(j)(i)) & "]"
Else
oLine = oLine & "[" & (oBOMFactorArray(j)(i)) & "]"
End If
Next
oStr = oStr & vbLf & oLine
Next
MsgBox(oStr)
End Sub()
Class RectangularComparer
Implements IComparer
' maintain a reference to the 2-dimensional array being sorted
Private sortArray(,) As Integer
' constructor initializes the sortArray reference
Public Sub New(ByVal theArray(,) As Double)
sortArray = theArray
End Sub
Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
' x and y are integer row numbers into the sortArray
Dim i1 As Integer = DirectCast(x, Integer)
Dim i2 As Integer = DirectCast(y, Integer)
Select Case sortArray(i1, 0).CompareTo(sortArray(i2, 0))
Case -1
Case 1
Case 0
Return sortArray(i1, 1).CompareTo(sortArray(i2, 1))
End Select
' compare the items in the sortArray
End Function
End Class

Help Visual Basic mixing characters

I'm making an application that will change position of two characters in Word.
Imports System.IO
Module Module1
Sub Main()
Dim str As String = File.ReadAllText("File.txt")
Dim str2 As String() = Split(str, " ")
For i As Integer = 0 To str2.Length - 1
Dim arr As Char() = CType(str2(i), Char())
For ia As Integer = 0 To arr.Length() - 1 Step 2
Dim pa As String
pa = arr(ia + 1)
arr(ia + 1) = arr(ia)
arr(ia) = pa
Next ia
For ib As Integer = 0 To arr.Length - 1
Console.Write(arr(ib))
File.WriteAllText("File2.txt", arr(ib))
Next ib
File.WriteAllText("File2.txt", " ")
Console.Write(" ")
Next i
Console.Read()
End Sub
End Module
For example:
Input: ab
Output: ba
Input: asdasd asdasd
Output: saadds saadds
Program works good, it is mixing characters good, but it doesn't write text to the file. It will write text in console, but not in file.
Note: Program is working only with words that are divisible by 2, but it's not a problem.
Also, it does not return any error message.
Your code is overwriting the file that you have already written with a single space (" ") each time round.
You should only open the file once, and append to it using a stream writer:
Using output = File.CreateText("file2.txt")
' Put the for loop here.
End Using
There are some other things wrong with your code. Firstly, use For Each instead of For, this makes your code much more simple and readable. Secondly, try to avoid For loops altogether where possible. For instance, instead of iterating over the characters to output them one at a time, just create a new string from the char array, and write that:
Dim shuffledWord As New String(arr)
output.Write(shuffledWord)
Some of your types are plain wrong, i.e. you are using String in places instead of Char. You should always use Option Strict On. Then the compiler will not tolerate such code.
You should also prefer to use framework methods over VB-specific methods. This makes it easier to understand for C# programmers, and also makes it easier to translate and change (that is, use the Split method of strings instead of a free function, use ToCharArray instead of a cast to Char() …).
Finally, use meaningful variable names. str, str2 and arr are particularly cryptic because they don’t tell the reader of the code anything of interest about the variables.
Sub Main()
Dim text As String = File.ReadAllText("File.txt")
Dim words As String() = str.Split(" "c)
Using output = File.CreateText("file2.txt")
For Each word In words
dim wordChars = word.ToCharArray()
For i As Integer = 0 To wordChars.Length - 1 Step 2
Dim tmp As Char = wordChars(i + 1)
wordChars(i + 1) = wordChars(i)
arr(i) = tmp
Next
Dim shuffledWord As New String(wordChars)
output.Write(shuffledWord + " ")
Console.Write(huffledWord + " ")
Next
End Using
Console.Read()
End Sub

string combinations

I would like to generate a combination of words. For example if I had the following list:
{cat, dog, horse, ape, hen, mouse}
then the result would be n(n-1)/2
cat dog horse ape hen mouse
(cat dog) (dog horse) (horse ape) (ape hen) (hen mouse)
(cat dog horse) (dog horse ape) (horse ape hen) etc
Hope this makes sense...everything I found involves permutations
The list I have would be a 500 long
Try this! :
Public Sub test()
Dim myAnimals As String = "cat dog horse ape hen mouse"
Dim myAnimalCombinations As String() = BuildCombinations(myAnimals)
For Each combination As String In myAnimalCombinations
'Look on the Output Tab for the results!
Console.WriteLine("(" & combination & ")")
Next combination
End Sub
Public Function BuildCombinations(ByVal inputString As String) As String()
'Separate the sentence into useable words.
Dim wordsArray As String() = inputString.Split(" ".ToCharArray)
'A plase to store the results as we build them
Dim returnArray() As String = New String() {""}
'The 'combination level' that we're up to
Dim wordDistance As Integer = 1
'Go through all the combination levels...
For wordDistance = 1 To wordsArray.GetUpperBound(0)
'Go through all the words at this combination level...
For wordIndex As Integer = 0 To wordsArray.GetUpperBound(0) - wordDistance
'Get the first word of this combination level
Dim combination As New System.Text.StringBuilder(wordsArray(wordIndex))
'And all all the remaining words a this combination level
For combinationIndex As Integer = 1 To wordDistance
combination.Append(" " & wordsArray(wordIndex + combinationIndex))
Next combinationIndex
'Add this combination to the results
returnArray(returnArray.GetUpperBound(0)) = combination.ToString
'Add a new row to the results, ready for the next combination
ReDim Preserve returnArray(returnArray.GetUpperBound(0) + 1)
Next wordIndex
Next wordDistance
'Get rid of the last, blank row.
ReDim Preserve returnArray(returnArray.GetUpperBound(0) - 1)
'Return combinations to the calling method.
Return returnArray
End Function
The first function is just something that shows you how to call the second function. It really depends on how you get your 500 list - you can copy and paste it over the animal names, or you can load a file with the words in it. If it doesn't fit on one line you can try:
Dim myAnimals As New StringBulder
myAnimals.Append("dog cat ... animal49 animal50")
myAnimals.Append(" ")
myAnimals.Append("animal51 ... animal99")
myAnimals.Append(" ")
myAnimals.Append("animal100 ... animal150")
etc.
then
Dim myAnimalCombinations As String() = BuildCombinations(myAnimals.ToString)
Say your list is arr = {cat, dog, horse, ape, hen, mouse}
Then you can do:
for i = 0; i < arr.size; i++)
for j = i; j < arr.size; j++)
print i,j;
The idea is basically - for each item, pair it with every other item on the list. However, to avoid the duplication (e.g. 1,2 and 2,1) you don't start the internal loop from the beginning every time but from your current index of the outer loop.