So,
I have a set of string (Connector_String) which contains strings (which represent network-like nodes connections) that show all possible connections. The Connector_String has the following format (which I thought would help me but I can change it if needed):
- Starts and ends with
"-" - The nodes connected (always 2) represented as
String1*String2 - The node before
"*"indicate the direction. So, for that above, direction isString1-->String2 - Connected nodes separated by
"-"
For instance,
-RANDIAC*RANDACBD-RANDV*RANDIF-...-RANDA*RANDACAC-
Which means RANDIAC connects with RANDACBD etc. Also note that RANDIAC could be connected with another node.
I'm trying to list all possible path between the nodes given a starting and ending point. For that, I have two strings which include all the starting (Start_String) and ending nodes (End_String). The format is as follow:
-RAND26RD-RAND06RD-...-RAND12RD-
I started writing a for loop code to iterate through the Connector_String but I soon realized that I have to write the same loop many times (which I do not know how to define how many). I then wrote a Do While loop code (first time ever for me to use it) which ended up not running at all (I don't understand why). Then, I tried to write a Function with the same for loop I use on the Sub and then run the Function in the Sub and in the 'Function' (hoping that will do the same job as the Do While loop).
None of my code have worked, but I'm adding my last attempt as it is recommended to have it on the question (although I doubt if an experienced person will read it as it is not well written - plus doesn't work).
Public Function Str_Search(a As String) As String
Dim i As Long
Debug.Print "Func " & a
If InStr(End_Str, Split(a, "-")(UBound(Split(a, "-")))) > 0 Then
Str_Search = a
Exit Function
End If
For i = 1 To UBound(Split(Connector_String, "-")) - 1
If Split(a, "-")(UBound(Split(a, "-"))) = Split(Split(Connector_String, "-")(i), "*")(0) Then
a = a & "-" & Split(Split(Connector_String, "-")(i), "*")(1)
Str_Search (a)
End If
Next i
End Function
Sub test_V4()
Dim a As String
Dim i As Long
a = ""
For i = 1 To UBound(Split(Connector_String, "-")) - 1
If InStr(Start_String, Split(Split(Connector_String, "-")(i), "*")(0)) > 0 Then
a = Replace(Split(Connector_String, "-")(i), "*", "-")
ElseIf a <> "" Then
Str_Search (a)
ElseIf InStr(End_String, Split(a, "-")(UBound(Split(a, "-")))) > 0 Then
Exit Sub
End If
Next
End Sub
Lastly, another tricky problem with my nodes is that there are nodes are bidirectional (so, I might have String1*String2 and String2*String1), which impose the problem to create infinite loop (I haven't not try to address that on my code as I can't even get a few paths).
See below the strings:
Start_String
-RAND_VW_E-RAND_VG_E-RAND_VG_F-RAND_M_2C-RAND_M_3A-RAND_VW_D-RAND_VW_V-RAND_M_1E-RAND_M_4E-RAND_VG_V-RAND_M_2D-RAND_M_3B-RAND_VW_C-RAND_VG_D-RAND_M_1F-RAND_M_4F-RAND_I_LINE-RAND_M_1E & RAND_M_4E-RAND_M_1F & RAND_M_4F
End_String
-RAND26RD-RAND06RD-RAND08RD-RAND12RD-RAND06RD-RAND02RD-RAND07RD-RAND01RD-RAND05RD-RAND03RD-RAND09RD-RAND04RD-RAND10RD-RAND20RD-RAND21RD-RAND22RD-RAND23RD-
Connector_String
-RANDIAC*RANDACBD-RANDV*RANDIF-RANDV*RANDIBD-RANDBD*RAND26RD-RANDACBD*RANDBD-RAND67F*RAND06RD-RAND89AC*RAND08RD-RANDACAC*RAND89AC-RANDA*RANDACAC-RAND_VW_E*RANDE-RAND_VG_E*RANDE-RAND_VG_F*RANDF-RAND_M_2C*RANDC-RAND_M_3A*RANDA-RANDEBD*RANDBD-RANDE*RANDEBD-RANDI*RANDIBD-RANDIBD*RANDBD-RANDF*RANDFNTH-RANDACAC*RANDACBD-RAND_VW_D*RANDD-RANDFSTH*RAND12F-RAND12F*RAND12RD-RANDIAC*RAND67AC-RAND67AC*RAND06RD-RANDFSTH*RAND02F-RAND02F*RAND02RD-RAND_VW_V*RANDV-RANDE*RANDEF-RAND_M_1E*RANDE-RAND_M_4E*RANDE-RANDEF*RANDFSTH-RAND_VG_V*RANDV-RANDV*RANDIAC-RANDFSTH*RAND67F-RAND67F*RAND07RD-RANDFNTH*RAND01RD-RANDIF*RANDFSTH-RANDB*RANDBD-RAND_M_2D*RANDD-RAND_M_3B*RANDB-RANDI*RANDIF-RANDIF*RANDFNTH-RANDFNTH*RAND05RD-RANDC*RANDACAC-RAND_VW_C*RANDC-RANDACAC*RAND67AC-RAND67AC*RAND07RD-RAND_VG_D*RANDD-RANDD*RANDBD-RAND_M_1F*RANDF-RAND_M_4F*RANDF-RANDFSTH*RAND03F-RAND03F*RAND03RD-RANDI*RANDIAC-RAND_I_LINE*RANDI-RANDIAC*RAND89AC-RAND89AC*RAND09RD-RANDF*RANDFSTH-RANDFSTH*RAND0410-RAND0410*RAND04RD-RAND0410*RAND10RD-RANDBD*RAND26BD-RANDFSTH*RANDFWST-RANDFWST*RANDFX-RAND20X*RAND20RD-RAND21X*RAND21RD-RANDFX*RAND21X-RANDFX*RAND20X-RANDEF*RANDFNTH-RANDACAC*RANDJET-RAND22Y*RAND22RD-RAND23Y*RAND23RD-RANDACY*RAND23Y-RANDJET*RANDACY-RANDACY*RAND22Y-RAND23Y*RAND23BD-RAND22Y*RAND22BD-RAND22Y*RAND23BD-RAND26BD*RAND22BD-RAND26BD*RAND23BD-RAND23BD*RAND26BD-RAND22BD*RAND26BD-RAND23BD*RAND23RD-RAND22BD*RAND22RD-RAND26BD*RAND26RD-RANDJET*RANDACX-RANDACX*RAND20X-RANDACX*RAND21X-RANDACX*RANDFX-RANDFX*RANDFWST-RANDFWST*RANDFSTH-RANDFSTH*RANDFNTH-
Hopefully, someone can help me with that.
CodePudding user response:
Copy the connections to a text file named Connector.txt and save in the same folder as the workbook. Connections are written to Sheet1 and routes to Sheet2. Routes are traced using the dictionary dict built from the connector file. The route array stores nodes as it recurses along the path. End points are highlighted in yellow.
Option Explicit
Dim dictEnd As Object
Dim dict As Object
Sub Str_Search()
Const CONFILE = "Connector.txt"
' dictionaries
Set dictEnd = CreateObject("Scripting.Dictionary")
Call EndNodes(dictEnd)
'MsgBox Join(dictEnd.keys, vbLf)
Set dict = CreateObject("Scripting.Dictionary")
Call ConnectedNodes(dict, ThisWorkbook.Path & "\" & CONFILE)
' dump source to check
Call DumpConnected(Sheet1, dict)
' trace routes to sheet2
Const STEPS = 20
Dim route(1 To STEPS) As String, arStart, k
Dim n As Long, r As Long
r = 2
arStart = StartNodes()
With Sheet2
.Cells.Clear
.Cells(1, 1) = "Start Node"
For n = 0 To UBound(arStart)
k = arStart(n)
If dict.exists(k) Then
route(1) = k
Call TraceRoute(route, 1, r, Sheet2)
r = r 1
ElseIf Len(k) > 0 Then
MsgBox k & " not found", vbCritical
End If
Next
.Columns.AutoFit
End With
MsgBox "Done", vbInformation
End Sub
Sub TraceRoute(ByRef route, ByRef i As Long, ByRef r As Long, ws As Worksheet)
'Debug.Print r, i, route(i)
Dim node As String, dest As String
Dim n As Long, j As Long, msg As String
' current node
node = route(i)
ws.Cells(r, i) = node
' is end node
If dictEnd.exists(node) Then
ws.Cells(r, i).Interior.Color = RGB(255, 255, 0)
End If
' check not infinite loop
For j = 1 To i - 1
If route(j) = node Then
msg = "Inf Loop "
ws.Cells(r, i 1) = msg
r = r 1
Exit Sub
End If
Next
' end of route ?
If Not dict.exists(node) Then
r = r 1
Exit Sub
End If
msg = ""
For n = 1 To dict(node).Count
dest = dict(node).Item(n)
' recurse
If dict.exists(dest) Then
i = i 1
route(i) = dest
Call TraceRoute(route, i, r, ws)
i = i - 1
Else
ws.Cells(r, i 1) = dest
If dictEnd.exists(dest) Then
ws.Cells(r, i 1).Interior.Color = RGB(255, 255, 0)
End If
r = r 1
End If
Next
End Sub
Function StartNodes() As Variant
StartNodes = Split("-RAND_VW_E-RAND_VG_E-RAND_VG_F-RAND_M_2C-RAND_M_3A-RAND_VW_D-RAND_VW_V" & _
"-RAND_M_1E-RAND_M_4E-RAND_VG_V-RAND_M_2D-RAND_M_3B-RAND_VW_C-RAND_VG_D" & _
"-RAND_M_1F-RAND_M_4F-RAND_I_LINE-RAND_M_1E-RAND_M_4E-RAND_M_1F-RAND_M_4F", "-")
End Function
Sub EndNodes(ByRef d)
Dim k
For Each k In Split("-RAND26RD-RAND06RD-RAND08RD-RAND12RD-RAND06RD-RAND02RD-RAND07RD-RAND01RD" & _
"-RAND05RD-RAND03RD-RAND09RD-RAND04RD-RAND10RD-RAND20RD-RAND21RD-RAND22RD-RAND23RD-", "-")
If Len(Trim(k)) > 0 Then d(Trim(k)) = 1
Next
MsgBox d.Count & " End Nodes"
End Sub
Sub ConnectedNodes(ByRef d, filename As String)
' read connection file
Dim FSO As Object, ts As Object, sTxt As String
Set FSO = CreateObject("Scripting.FilesystemObject")
Set ts = FSO.OpenTextFile(filename)
sTxt = ts.readAll
ts.Close
' regular expression
Dim regex As Object, m As Object, node As Object
Dim n As Long, k
Set regex = CreateObject("vbscript.regexp")
With regex
.Global = True
.MultiLine = True
.IgnoreCase = True
.Pattern = "(?:-([^*] )\*([^-] ))"
End With
' parse file
If regex.test(sTxt) Then
Set m = regex.Execute(sTxt) '
For n = 1 To m.Count
Set node = m.Item(n - 1).submatches
k = Trim(node(0))
If Not dict.exists(k) And Len(k) > 0 Then
dict.Add k, New Collection
End If
dict(k).Add Trim(node(1))
Next
End If
MsgBox d.Count & " Connectd Nodes"
End Sub
Sub DumpConnected(ws As Worksheet, dict)
Dim k, r As Long, n As Long
r = 1
With ws
.Cells.Clear
.Cells(r, 1) = "Start Node"
For Each k In dict
r = r 1
.Cells(r, 1) = k
For n = 1 To dict(k).Count
.Cells(r, n 1) = dict(k).Item(n)
Next
Next
.Columns.AutoFit
.Sort.SortFields.Clear
.Sort.SortFields.Add Key:=.Range("A1"), SortOn:=xlSortOnValues, _
Order:=xlAscending, DataOption:=xlSortNormal
With .Sort
.SetRange ws.UsedRange
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End With
End Sub

