mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-13 03:35:04 +00:00
Whitespace, tidying
This commit is contained in:
@@ -7,199 +7,212 @@ using ICD.Common.Utils.Extensions;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
public static class RecursionUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all of the nodes in the tree via breadth-first search.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="root"></param>
|
||||
/// <param name="getChildren"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> BreadthFirstSearch<T>(T root, Func<T, IEnumerable<T>> getChildren)
|
||||
{
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
public static class RecursionUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all of the nodes in the tree via breadth-first search.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="root"></param>
|
||||
/// <param name="getChildren"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> BreadthFirstSearch<T>(T root, Func<T, IEnumerable<T>> getChildren)
|
||||
{
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
|
||||
Queue<T> process = new Queue<T>();
|
||||
process.Enqueue(root);
|
||||
Queue<T> process = new Queue<T>();
|
||||
process.Enqueue(root);
|
||||
|
||||
while (process.Count > 0)
|
||||
{
|
||||
T current = process.Dequeue();
|
||||
yield return current;
|
||||
while (process.Count > 0)
|
||||
{
|
||||
T current = process.Dequeue();
|
||||
yield return current;
|
||||
|
||||
foreach (T child in getChildren(current))
|
||||
process.Enqueue(child);
|
||||
}
|
||||
}
|
||||
foreach (T child in getChildren(current))
|
||||
process.Enqueue(child);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the shortest path from root to destination via breadth-first search.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="root"></param>
|
||||
/// <param name="destination"></param>
|
||||
/// <param name="getChildren"></param>
|
||||
/// <returns></returns>
|
||||
[CanBeNull]
|
||||
public static IEnumerable<T> BreadthFirstSearchPath<T>(T root, T destination, Func<T, IEnumerable<T>> getChildren)
|
||||
{
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
/// <summary>
|
||||
/// Returns the shortest path from root to destination via breadth-first search.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="root"></param>
|
||||
/// <param name="destination"></param>
|
||||
/// <param name="getChildren"></param>
|
||||
/// <returns></returns>
|
||||
[CanBeNull]
|
||||
public static IEnumerable<T> BreadthFirstSearchPath<T>(T root, T destination, Func<T, IEnumerable<T>> getChildren)
|
||||
{
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
|
||||
return BreadthFirstSearchPath(root, destination, getChildren, EqualityComparer<T>.Default);
|
||||
}
|
||||
return BreadthFirstSearchPath(root, destination, getChildren, EqualityComparer<T>.Default);
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public static Dictionary<T2, IEnumerable<T>> BreadthFirstSearchManyDestinations<T, T2>(T root, Dictionary<T2, T> destinations, Func<T, IEnumerable<T>> getChildren)
|
||||
{
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
/// <summary>
|
||||
/// Returns the shortest path from root to destination via breadth-first search.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="root"></param>
|
||||
/// <param name="destination"></param>
|
||||
/// <param name="getChildren"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
[CanBeNull]
|
||||
public static IEnumerable<T> BreadthFirstSearchPath<T>(T root, T destination, Func<T, IEnumerable<T>> getChildren,
|
||||
IEqualityComparer<T> comparer)
|
||||
{
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
|
||||
return BreadthFirstSearchPathManyDestinations(root, destinations, getChildren, EqualityComparer<T>.Default);
|
||||
}
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
|
||||
/// <summary>
|
||||
/// Returns the shortest path from root to destination via breadth-first search.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="root"></param>
|
||||
/// <param name="destination"></param>
|
||||
/// <param name="getChildren"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
[CanBeNull]
|
||||
public static IEnumerable<T> BreadthFirstSearchPath<T>(T root, T destination, Func<T, IEnumerable<T>> getChildren,
|
||||
IEqualityComparer<T> comparer)
|
||||
{
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
// Edge case - root and destination are the same
|
||||
if (comparer.Equals(root, destination))
|
||||
return new[] {root};
|
||||
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
Queue<T> queue = new Queue<T>();
|
||||
queue.Enqueue(root);
|
||||
|
||||
// Edge case - root and destination are the same
|
||||
if (comparer.Equals(root, destination))
|
||||
return new[] { root };
|
||||
Dictionary<T, T> nodeParents = new Dictionary<T, T>();
|
||||
|
||||
Queue<T> queue = new Queue<T>();
|
||||
queue.Enqueue(root);
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
T current = queue.Dequeue();
|
||||
|
||||
Dictionary<T, T> nodeParents = new Dictionary<T, T>();
|
||||
foreach (T node in getChildren(current))
|
||||
{
|
||||
if (nodeParents.ContainsKey(node))
|
||||
continue;
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
T current = queue.Dequeue();
|
||||
queue.Enqueue(node);
|
||||
nodeParents.Add(node, current);
|
||||
|
||||
foreach (T node in getChildren(current))
|
||||
{
|
||||
if (nodeParents.ContainsKey(node))
|
||||
continue;
|
||||
// Found a path to the destination
|
||||
if (comparer.Equals(node, destination))
|
||||
return GetPath(destination, nodeParents).Reverse();
|
||||
}
|
||||
}
|
||||
|
||||
queue.Enqueue(node);
|
||||
nodeParents.Add(node, current);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Found a path to the destination
|
||||
if (comparer.Equals(node, destination))
|
||||
return GetPath(destination, nodeParents).Reverse();
|
||||
}
|
||||
}
|
||||
[NotNull]
|
||||
public static Dictionary<T2, IEnumerable<T>> BreadthFirstSearchManyDestinations<T, T2>(T root,
|
||||
Dictionary<T2, T> destinations,
|
||||
Func<T, IEnumerable<T>>
|
||||
getChildren)
|
||||
{
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
|
||||
return null;
|
||||
}
|
||||
return BreadthFirstSearchPathManyDestinations(root, destinations, getChildren, EqualityComparer<T>.Default);
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
public static Dictionary<T2, IEnumerable<T>> BreadthFirstSearchPathManyDestinations<T, T2>(T root, Dictionary<T2, T> destinations,
|
||||
Func<T, IEnumerable<T>> getChildren,
|
||||
IEqualityComparer<T> comparer)
|
||||
{
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
[NotNull]
|
||||
public static Dictionary<T2, IEnumerable<T>> BreadthFirstSearchPathManyDestinations<T, T2>(T root,
|
||||
Dictionary<T2, T>
|
||||
destinations,
|
||||
Func<T, IEnumerable<T>>
|
||||
getChildren,
|
||||
IEqualityComparer<T>
|
||||
comparer)
|
||||
{
|
||||
if (destinations == null)
|
||||
throw new ArgumentNullException("destinations");
|
||||
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
if (getChildren == null)
|
||||
throw new ArgumentNullException("getChildren");
|
||||
|
||||
Dictionary<T2, T> destinationsToBeProcessed = new Dictionary<T2, T>(destinations);
|
||||
List<T> destinationsProcessed = new List<T>();
|
||||
Dictionary<T2, IEnumerable<T>> pathsToReturn = new Dictionary<T2, IEnumerable<T>>();
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
|
||||
//Edge case, root is the destination
|
||||
foreach (var destination in destinationsToBeProcessed.Where(destination => comparer.Equals(root, destination.Value)))
|
||||
{
|
||||
destinationsProcessed.Add(destination.Value);
|
||||
pathsToReturn.Add(destination.Key, new[] { root });
|
||||
}
|
||||
Dictionary<T2, T> destinationsToBeProcessed = new Dictionary<T2, T>(destinations);
|
||||
List<T> destinationsProcessed = new List<T>();
|
||||
Dictionary<T2, IEnumerable<T>> pathsToReturn = new Dictionary<T2, IEnumerable<T>>();
|
||||
|
||||
foreach (var destination in destinationsProcessed)
|
||||
{
|
||||
destinationsToBeProcessed.RemoveValue(destination);
|
||||
}
|
||||
destinationsProcessed.Clear();
|
||||
if (destinationsToBeProcessed.Count == 0)
|
||||
{
|
||||
return pathsToReturn;
|
||||
}
|
||||
// Edge case, root is the destination
|
||||
foreach (
|
||||
KeyValuePair<T2, T> destination in
|
||||
destinationsToBeProcessed.Where(destination => comparer.Equals(root, destination.Value)))
|
||||
{
|
||||
destinationsProcessed.Add(destination.Value);
|
||||
pathsToReturn.Add(destination.Key, new[] {root});
|
||||
}
|
||||
|
||||
Queue<T> queue = new Queue<T>();
|
||||
queue.Enqueue(root);
|
||||
foreach (T destination in destinationsProcessed)
|
||||
{
|
||||
destinationsToBeProcessed.RemoveValue(destination);
|
||||
}
|
||||
destinationsProcessed.Clear();
|
||||
if (destinationsToBeProcessed.Count == 0)
|
||||
{
|
||||
return pathsToReturn;
|
||||
}
|
||||
|
||||
Dictionary<T, T> nodeParents = new Dictionary<T, T>();
|
||||
Queue<T> queue = new Queue<T>();
|
||||
queue.Enqueue(root);
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
T current = queue.Dequeue();
|
||||
Dictionary<T, T> nodeParents = new Dictionary<T, T>();
|
||||
|
||||
foreach (T node in getChildren(current).Where(node => !nodeParents.ContainsKey(node)))
|
||||
{
|
||||
queue.Enqueue(node);
|
||||
nodeParents.Add(node, current);
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
T current = queue.Dequeue();
|
||||
|
||||
foreach (var destination in destinationsToBeProcessed.Where(destination => comparer.Equals(node, destination.Value)))
|
||||
{
|
||||
destinationsProcessed.Add(destination.Value);
|
||||
pathsToReturn.Add(destination.Key, GetPath(destination.Value, nodeParents).Reverse());
|
||||
}
|
||||
foreach (var destination in destinationsProcessed)
|
||||
{
|
||||
destinationsToBeProcessed.RemoveValue(destination);
|
||||
}
|
||||
destinationsProcessed.Clear();
|
||||
if (destinationsToBeProcessed.Count == 0)
|
||||
{
|
||||
return pathsToReturn;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (T node in getChildren(current).Where(node => !nodeParents.ContainsKey(node)))
|
||||
{
|
||||
queue.Enqueue(node);
|
||||
nodeParents.Add(node, current);
|
||||
|
||||
return pathsToReturn;
|
||||
}
|
||||
foreach (
|
||||
KeyValuePair<T2, T> destination in
|
||||
destinationsToBeProcessed.Where(destination => comparer.Equals(node, destination.Value)))
|
||||
{
|
||||
destinationsProcessed.Add(destination.Value);
|
||||
pathsToReturn.Add(destination.Key, GetPath(destination.Value, nodeParents).Reverse());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Walks through a map of nodes from the starting point.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="nodeParents"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> GetPath<T>(T start, IDictionary<T, T> nodeParents)
|
||||
{
|
||||
IcdHashSet<T> visited = new IcdHashSet<T>();
|
||||
foreach (T destination in destinationsProcessed)
|
||||
destinationsToBeProcessed.RemoveValue(destination);
|
||||
|
||||
while (true)
|
||||
{
|
||||
yield return start;
|
||||
visited.Add(start);
|
||||
destinationsProcessed.Clear();
|
||||
|
||||
T next;
|
||||
if (!nodeParents.TryGetValue(start, out next))
|
||||
break;
|
||||
if (destinationsToBeProcessed.Count == 0)
|
||||
return pathsToReturn;
|
||||
}
|
||||
}
|
||||
|
||||
if (visited.Contains(next))
|
||||
break;
|
||||
return pathsToReturn;
|
||||
}
|
||||
|
||||
start = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Walks through a map of nodes from the starting point.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="nodeParents"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> GetPath<T>(T start, IDictionary<T, T> nodeParents)
|
||||
{
|
||||
IcdHashSet<T> visited = new IcdHashSet<T>();
|
||||
|
||||
while (true)
|
||||
{
|
||||
yield return start;
|
||||
visited.Add(start);
|
||||
|
||||
T next;
|
||||
if (!nodeParents.TryGetValue(start, out next))
|
||||
break;
|
||||
|
||||
if (visited.Contains(next))
|
||||
break;
|
||||
|
||||
start = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user