Make()
takes projects with a list of tuples representing project references in the form of (Dependency, Dependent)
and returns projects in the order to be build:
static void Main(string[] args)
{
var projects = new[] { "a", "b", "c", "d", "e", "f" };
var dependencies = new[] { ("a", "b"), ("a", "c"), ("e", "f"), ("c", "f"), ("f", "d") };
Console.WriteLine(
string.Join(", ", Make(projects, dependencies))); // a, e, b, c, f, d
}
Where:
static IEnumerable<string> Make(
IEnumerable<string> projects,
IEnumerable<(string Dependency, string Dependent)> references)
{
var dependents = new HashSet<string>(references.Select(d => d.Dependent));
var build = new HashSet<string>(projects.Except(dependents));
return
!projects.Any() ? Enumerable.Empty<string>() :
!build.Any() ? throw new Exception("Circled references detected.") :
build.Concat(Make(
projects.Except(build).ToArray(),
references.Where(r => !build.Contains(r.Dependency)).ToArray()));
}
What about run-time complexity of this one? Could it be optimized?