Aggregate cidrs up to a limit I have this algorithm which aggregates a list of cidrs up to a provided limit based on the distance between them. It finds the closest ones and calculates the subnet to join them. The loop repeats until the limit is reached. I think there's room to improve it but I'm stuck at the moment. Any advice?

Input


limit: 9
cidrs (10):

52.1.0.0/16
52.2.0.0/16
52.3.0.0/16
52.4.0.0/16
52.5.0.0/16
52.6.0.0/16
52.7.0.0/16
52.8.0.0/16
52.9.0.0/16
52.10.0.0/16



Output


cidrs (9):

52.1.0.0/16
5̶2̶.̶2̶.̶0̶.̶0̶/̶1̶6̶
5̶2̶.̶3̶.̶0̶.̶0̶/̶1̶6̶
52.4.0.0/16
52.5.0.0/16
52.6.0.0/16
52.7.0.0/16
52.8.0.0/16
52.9.0.0/16
52.10.0.0/16
**52.2.0.0/15**



Code

public static IEnumerable&lt;string&gt; Aggregate(List&lt;string&gt; cidrs, int limit)
{
    var parsedCidrs = cidrs.Select(IPNetwork.Parse).ToArray();

    var cidr1 = parsedCidrs[0];
    var cidr2 = parsedCidrs[1];
    var minWideSubnet = IPNetwork.WideSubnet(new[] { cidr1, cidr2 });

    while (parsedCidrs.Count &gt; limit)
    {
        foreach (var cidrA in parsedCidrs)
        {
            foreach (var cidrB in parsedCidrs)
            {
                if (cidrA != cidrB)
                {
                    var wideSubnet = IPNetwork.WideSubnet(new[] {cidrA, cidrB});

                    if (wideSubnet.Usable &lt; minWideSubnet.Usable)
                    {
                        minWideSubnet = wideSubnet;
                        cidr1 = cidrA;
                        cidr2 = cidrB;
                    }
                }
            }
        }
        // update array
        cidrs.Remove(cidr1.ToString());
        cidrs.Remove(cidr2.ToString());
        var end = minWideSubnet.ToString();
        cidrs.Add(end);
    }

    return cidrs;
}
First just a small cosmetic improvement: I'd call the method MergeSimilarIps or something like this (you know better what name would make more sense). Aggregate suggests you would get a sigle result.




    foreach (var cidrA in parsedCidrs)
    {
        foreach (var cidrB in parsedCidrs)
        {
            if (cidrA != cidrB)
            {



I thnink you can speed the merge a little bit by using for loops and starting the second one at i + 1 of the first loop. This way you check x == y only once because y == x is the same an you already checked it so there is no need that you do it again plus the + 1 will skip x == x.

Compare these two loops. The first one works like in your solution:

var nums = new [] { 1, 2, 3 };

foreach (var x in nums)
{
    foreach (var y in nums)
    {
        Console.WriteLine($"({x}, {y})");
    }
}


its result is:



(1, 1)
(1, 2)
(1, 3)
(2, 1)
(2, 2)
(2, 3)
(3, 1)
(3, 2)
(3, 3)


The second one works without repetitions.

for (var x = 0; x &lt; nums.Length; x++)
{
    for (var y = x + 1; y &lt; nums.Length; y++)
    {
        Console.WriteLine($"({nums[x]}, {nums[y]})");
    }
}


It produces only 1/3 of this list above:



(1, 2)
(1, 3)
(2, 3)


This means you get only unique combinations without repetitions.