├── GraphResolver.PNG ├── README.md ├── GraphResolver.csproj ├── Model ├── Vertex.cs ├── Edge.cs └── Graph.cs ├── GraphResolver.cs ├── GraphResolver.sln └── Program.cs /GraphResolver.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/access/GraphResolver/main/GraphResolver.PNG -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Graph Resolver Test Data: 2 | ![Graph Resolver](/GraphResolver.PNG "Graph Resolver") 3 | -------------------------------------------------------------------------------- /GraphResolver.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Model/Vertex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace GraphResolver.Model 8 | { 9 | public class Vertex 10 | { 11 | public int Number { get; set; } 12 | public Vertex(int number) => Number = number; 13 | public bool Visited { get; set; } 14 | public override string ToString() => Number.ToString(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Model/Edge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace GraphResolver.Model 8 | { 9 | public class Edge 10 | { 11 | public Vertex From { get; set; } 12 | public Vertex To { get; set; } 13 | public override string ToString() => $"({From}; {To})"; 14 | 15 | public Edge(Vertex from, Vertex to) 16 | { 17 | From = from; 18 | To = to; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /GraphResolver.cs: -------------------------------------------------------------------------------- 1 | using GraphResolver.Model; 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace GraphResolver 10 | { 11 | class GraphResolver 12 | { 13 | public static List> ConnectingPaths(List> graph, int node1, int node2) 14 | { 15 | var newGraph = new Graph(); 16 | 17 | // init graph vertexes and edges 18 | foreach (var edge in graph) 19 | { 20 | var vertexFrom = newGraph.AddVertex(edge.Item1); 21 | var vertexTo = newGraph.AddVertex(edge.Item2); 22 | newGraph.AddEdge(vertexFrom, vertexTo); 23 | } 24 | 25 | return newGraph.GetRoutes(node1, node2); 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /GraphResolver.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31410.357 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphResolver", "GraphResolver.csproj", "{3BD96597-5365-4DBF-A341-6E6CBD9CEC82}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3BD96597-5365-4DBF-A341-6E6CBD9CEC82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {3BD96597-5365-4DBF-A341-6E6CBD9CEC82}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {3BD96597-5365-4DBF-A341-6E6CBD9CEC82}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {3BD96597-5365-4DBF-A341-6E6CBD9CEC82}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {59ABFC51-FAB2-446A-B415-D7B8F7643977} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace GraphResolver 5 | { 6 | class Program 7 | { 8 | // fill edges data for testing... 9 | private static List> _edges = new List>() { 10 | new Tuple(1, 2), 11 | new Tuple(1, 3), 12 | new Tuple(2, 4), 13 | new Tuple(3, 4), 14 | new Tuple(4, 5), 15 | new Tuple(4, 6), 16 | //------------------------ 17 | new Tuple(5, 15), 18 | 19 | new Tuple(5, 7), 20 | new Tuple(6, 7), 21 | new Tuple(7, 8), 22 | new Tuple(7, 9), 23 | new Tuple(8, 10), 24 | new Tuple(9, 10), 25 | new Tuple(10, 11), 26 | new Tuple(10, 12), 27 | 28 | new Tuple(12, 120), 29 | new Tuple(120, 88), 30 | 31 | 32 | new Tuple(88, 33), 33 | new Tuple(88, 55), 34 | }; 35 | 36 | static void Main(string[] args) 37 | { 38 | Console.WriteLine("GraphResolver started."); 39 | 40 | var result = GraphResolver.ConnectingPaths(_edges, 1, 4); 41 | 42 | foreach (var route in result) 43 | { 44 | Console.Write(string.Join(",", route.ToArray())); 45 | Console.WriteLine(); 46 | } 47 | 48 | Console.WriteLine("GraphResolver finished."); 49 | Console.ReadLine(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Model/Graph.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace GraphResolver.Model 8 | { 9 | public class Graph 10 | { 11 | private HashSet _UniqueVertexes = new HashSet(); 12 | private List _Vertexes = new List(); 13 | private List _Edges = new List(); 14 | private List> _AvailableRoutes = new List>(); 15 | 16 | public int VertexCount => _Vertexes.Count; 17 | public int EdgesCount => _Edges.Count; 18 | 19 | public Vertex AddVertex(int vertex) 20 | { 21 | var newVertex = new Vertex(vertex); 22 | if (_UniqueVertexes.Add(vertex)) 23 | _Vertexes.Add(newVertex); 24 | else 25 | foreach (var v in _Vertexes) 26 | if (v.Number == vertex) 27 | return v; 28 | return newVertex; 29 | } 30 | 31 | public void AddEdge(Vertex from, Vertex to) 32 | { 33 | var edge = new Edge(from, to); 34 | _Edges.Add(edge); 35 | } 36 | 37 | public List GetToVertexesList(Vertex vertex) 38 | { 39 | var result = new List(); 40 | 41 | foreach (var edge in _Edges) 42 | if (edge.From == vertex) 43 | result.Add(edge.To); 44 | return result; 45 | } 46 | 47 | public Vertex GetVertexByValue(int val) 48 | { 49 | foreach (var v in _Vertexes) 50 | if (v.Number == val) 51 | return v; 52 | return null; 53 | } 54 | 55 | public List> GetRoutes(int start, int finish) 56 | { 57 | // get start and finish Vertexes 58 | var startVertex = GetVertexByValue(start); 59 | var finishVertex = GetVertexByValue(finish); 60 | 61 | GenerateAvailableRoutes(startVertex, finishVertex); 62 | 63 | var neededList = new List>(); 64 | foreach (var route in _AvailableRoutes) 65 | { 66 | if (route.Contains(start) && route.Contains(finish)) 67 | { 68 | int startIdx = route.IndexOf(start); 69 | int finishIdx = route.IndexOf(finish); 70 | var routeVertexes = route.GetRange(startIdx, finishIdx - startIdx + 1); 71 | neededList.Add(routeVertexes); 72 | } 73 | } 74 | 75 | // remove duplicates 76 | var distinct = neededList.Select(x => new HashSet(x)).Distinct(HashSet.CreateSetComparer()); 77 | var outList = new List>(); 78 | foreach (var list in distinct) 79 | outList.Add(list.ToList()); 80 | return outList; 81 | } 82 | 83 | private void GenerateAvailableRoutes(Vertex start, Vertex finish) 84 | { 85 | bool endOfBranch = false; 86 | var tmpRoute = new LinkedList(); 87 | var currentVertex = start; 88 | 89 | tmpRoute.AddFirst(start); 90 | while (tmpRoute.Count > 0) 91 | { 92 | if (endOfBranch) 93 | { 94 | tmpRoute.RemoveLast(); 95 | if (tmpRoute.Last != null) 96 | currentVertex = tmpRoute.Last.Value; 97 | } 98 | 99 | var neighborList = GetToVertexesList(currentVertex); 100 | if (neighborList.Count > 0) 101 | { 102 | bool hasNotVisited = false; 103 | foreach (var vertex in neighborList) 104 | { 105 | if (!vertex.Visited) 106 | { 107 | hasNotVisited = true; 108 | tmpRoute.AddLast(vertex); 109 | vertex.Visited = true; 110 | currentVertex = vertex; 111 | endOfBranch = false; 112 | break; 113 | } 114 | } 115 | if (!hasNotVisited) 116 | { 117 | if (!endOfBranch) 118 | CleanVisits(currentVertex); 119 | else 120 | { 121 | if (!endOfBranch) 122 | tmpRoute.RemoveLast(); 123 | if (tmpRoute.Last != null) 124 | currentVertex = tmpRoute.Last.Value; 125 | } 126 | } 127 | } 128 | else 129 | { 130 | endOfBranch = true; 131 | _AvailableRoutes.Add(tmpRoute.Select((item) => (item.Number)).ToList()); 132 | } 133 | } 134 | } 135 | 136 | private void CleanVisits(Vertex currentVertex) 137 | { 138 | foreach (var vertex in GetToVertexesList(currentVertex)) 139 | { 140 | vertex.Visited = false; 141 | CleanVisits(vertex); 142 | } 143 | } 144 | } 145 | } 146 | --------------------------------------------------------------------------------