'Diagonal difference of a nested List C#

I'm trying to get from a function the absolute difference of a nested list. I have a fixed matrix, and I would like to get the result when is not fixed. At the moment I have a 3 x 3 matrix and this is what I've tried:

List<List<int>> matrix = new List<List<int>> { 
    new List<int>() { 6, 2, 3 },
    new List<int>() { 1, 8, 2 },
    new List<int>() { 3, 4, 7 }
};

public static int diagonalDifference(List<List<int>> arr)
{
   int right = 0;
   int left = 0;
   int result = 0;

   for (int i = 0; i < arr.Count; i++)
   {
       for (int j = 0; j < arr.Count; j++)
       {
           right = arr[0][0] + arr[1][1] + arr[2][2];
           left = arr[2][0] + arr[1][1] + arr[0][2];
       }

       result = Math.Abs(right - left);  
   }

   return result;
}

//Output : 7

So, how can I adjust the function to get the absolute difference from a dynamic matrix? Thanks for the guidance and help!!



Solution 1:[1]

Often, when we facing such problems we can query with a help of Linq:

using System.Linq;

...

private static diagonalDifference(List<List<int>> arr) => Math.Abs(arr
  .Select((line, index) => line[index] - line[line.Count - 1 - index])
  .Sum());

If you prefer good old for loop (please, note, that we want just one loop):

private static diagonalDifference(List<List<int>> arr) {
  int result = 0;

  for (int i = 0; i < arr.Count; ++i) 
    result += arr[i][i] - arr[i][arr.Count - 1 - i];
 
  return Math.Abs(result); 
}

What's going on? We scan matrix (arr) line by line an sum the difference between left and right diagonal items:

6, 2, 3  -> 6 - 3 == 3 
1, 8, 2     8 - 8 == 0
3, 4, 7     7 - 3 == 4
            ----------
                     7 in total 

Solution 2:[2]

You can do something similar to the following:

    static void Main(string[] args)
    {
        List<List<int>> matrix = new List<List<int>> {
                                        new List<int>(){ 6, 2, 3,4 },
                                        new List<int>(){ 1, 8, 2,7 },
                                        new List<int>(){ 3, 4, 7 ,10},
                                        new List<int>(){ 13, 24, 4 ,8}, //added one more to demo the code
                                 };

        var diagnoalValues = Enumerable.Range(0, matrix.Count).Select(x => new
        {
            Left = matrix[x][x], 
            Right = matrix[matrix.Count - x - 1][x]
        }).ToList();

        var leftSum = diagnoalValues.Sum(x => x.Left);
        var rightRum = diagnoalValues.Sum(x => x.Right);

        var difference = Math.Abs(leftSum - rightRum);

        Console.WriteLine($"Difference:{difference}");
    }

If you want to reduce iteration, you can change it to the following also if you want:

    static void Main(string[] args)
    {
        List<List<int>> matrix = new List<List<int>> {
            new List<int>(){ 6, 2, 3,4 },
            new List<int>(){ 1, 8, 2,7 },
            new List<int>(){ 3, 4, 7 ,10},
            new List<int>(){ 13, 24, 4 ,8},
        };

        var sum = Enumerable.Range(0, matrix.Count)
            .Aggregate(new { Left = 0, Right = 0 }, (previous, index) => new
            {
                Left = previous.Left + matrix[index][index],
                Right = previous.Right + matrix[matrix.Count - index - 1][index]
            });


        var difference = Math.Abs(sum.Left-sum.Right);

        Console.WriteLine($"Difference:{difference}");
    }

Solution 3:[3]

Without changing your code much I came up with this. You don't need embedded for loops to make this happen. This algorithm counts the left and right diagonals starting at the left going to the right, where the right diagonal starts at the top descending to the right, and the left diagonal starts at the bottom ascending to the right.

    public static int diagonalDifference(List<List<int>> arr)
    {
        var right = 0;
        var left = 0;
        var result = 0;
        var rowCount = arr.Count - 1;
        var listCount = arr[0].Count;

        for (var j = 0; j < listCount; j++)
        {
            right += arr[j][j];
            left += arr[rowCount - j][j];
        }
        result = Math.Abs(right - left);

       return result;
    }

This ASSUMES that the matrix is even in columns and rows. That every row has the same number of elements and the number of elements in a row is equal to the number of rows the matrix has. With varying columns and rows, this would have to be modified to suit your needs.

Solution 4:[4]

The main challenge with a dynamic matrix will be if the length does not match the width. In that case you will have to decide how you want it handled (average of the missing, skip missing, etc.).

To handle an equal matrix, all you need is the length of the matrix.

Below I show how to get the diagonal length and how to create your left and right diagonals using a for loop. This does not account for the case where the length and width are not equal, instead it will break short since the diagonal length is the smaller of the 2 dimensions.

var right = 0;
var left = 0;

var length = matrix.Count;
var width = matrix[0].Count;

var diagLength = length == width ? length : Math.Min(length, width);

for (int i = 0; i < diagLength; i++)
{
    right += matrix[i][i];
    left += matrix[diagLength - 1 - i][i];
}

var diff = Math.Abs(right - left);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3
Solution 4 hijinxbassist