Grizzly
Grizzly

Reputation: 5953

Matrix Elements Sum C#

I am working on a problem (for fun) that is honestly making me confuse myself.

If I have a matrix like so:

matrix = [[0, 1, 1, 2], 
          [0, 5, 0, 0],
          [2, 0, 3, 3]]

I want to find the sum of all numbers that are not 0 and where a 0 is not above it. Here is the same matrix broken down into the numbers that I want to add up:

matrix = [[x, 1, 1, 2], 
          [x, 5, x, x],
          [x, x, x, x]]

matrixSum = 9  // (1 + 1 + 2 + 5)

I am traversing the array based on column first then retrieving the value I am looking for, but I don't know how to ignore the values where a 0 lies above it.

public class Program
{
    public static void Main()
    {
        int[] list1 = new int[4] { 0, 1, 1, 2};
        int[] list2 = new int[4] { 0, 5, 0, 0};
        int[] list3 = new int[4] { 2, 0, 3, 3 };
        int[][] lists = new int[][]{list1, list2, list3};

        var result = TestMethod(lists);
    }

    public static int TestMethod(int[][] matrix)
    {
        var lstOfIntsToAdd = new List<int>();
        for(int i = 0; i < 4; i++){
            for(int j = 0; j < 3; j++){
                Console.Write("matrix[[{1}][{0}]] = {2} /", j, i, matrix[j][i]);
            }
            Console.WriteLine();
        }

        return return lstOfIntsToAdd.Sum();

    }
}

Here is the .NET Fiddle.

Any help is appreciated.

Picture from codefights:

enter image description here

This problem can be found on CodeFights

Upvotes: 2

Views: 7209

Answers (6)

Martin Zikmund
Martin Zikmund

Reputation: 39092

You can just check the row above if it exists:

public static int TestMethod(int[][] matrix)
{
    int sum = 0;
    for (int column = 0; column < 4; column++)
        for (int row = 0; row < 3; row++)
            if (row == 0 || matrix[row - 1][column] != 0 )
                sum += matrix[row][column];
    return sum;         
}

Because C# uses short-circuit evaulation of logical expressions, we can check if we are on the first row first and if we are, the body of the if statement will be evaulated without trying to access the non-existent -1st row of the matrix.

Update

If the you should discard all values above which there is any zero, you can go through each column and add numbers as long as you don't encounter a zero.

public static int TestMethod(int[][] matrix)
{
    int sum = 0;
    for (int column = 0; column < 4; column++)
        for (int row = 0; row < 3; row++)
        {
            if (matrix[row][column] != 0)
                sum += matrix[row][column];   
            else
                break;
        }
    return sum;             
}

Upvotes: 2

schar
schar

Reputation: 2658

To help you with your fiddle(add these after Console.Write("matrix[[{1}][{0}]] = {2} /", j, i, matrix[j][i]);):

int ttl =0;                 
if (j == 0)
    ttl += matrix[j][i];
if (j > 0)
    if (matrix[j-1][i] != 0)
        ttl += matrix[j][i];

Upvotes: 0

Xiaoy312
Xiaoy312

Reputation: 14477

Using LINQ:

var result = Enumerable.Range(0, lists.First().Length)
    .Sum(column =>  Enumerable.Range(0, lists.Length)
        .Select(row => lists[row][column])
        .TakeWhile(value => value != 0)
        .Sum())

Here is some explanation for the uninitiated:

== First layer ==

  1. Enumerable.Range(0, lists.First().Length): enumerate all the column indexes
  2. .Sum(column => ...: Aggregate the results of inner(second) layer through summation

Essentially, we take the column index, project the index into the desired value, and sum them up.

== Second layer ==

While we are in the inner layer, throw away the notion of outer layer for now. As we will be focusing on each individual column.

  1. Enumerable.Range(0, lists.Length): same as step#1, but with row indexes
  2. .Select(row => lists[row][column]): project the row indexes into values on the respective indexes.
  3. .TakeWhile(value => value != 0): allow us to skip 0 itself and every number after(below) it
  4. .Sum(): add up everything

Upvotes: 3

Zohar Peled
Zohar Peled

Reputation: 82504

Here is how I would do it:
For the first row, you sum all values. For any other row, you check if the array in the row before is too short (meaning there can't be a 0 above current number) or if the current index on the row before does not contain 0.
Please note that the order of the conditions is critical - if you change it you will cause an IndexOutOfRange exception.

You could add a check if the current value is different than zero, but adding zero to the sum is a no-op anyway so why bother?

public static int TestMethod(int[][] Jagged)
{
    var sum = 0;
    for(int i = 0; i < Jagged.Length; i++){
        for(int j = 0; j < Jagged[i].Length; j++){
            if(i == 0 || Jagged[i-1].Length > j || Jagged[i-1][j] != 0) 
            {
                // you could add if Jagged[i][j] != 0 but it's a sum so who cares? 
                sum += Jagged[i][j];
            }
        }
    }
    return sum;
}

Upvotes: 1

Devstr
Devstr

Reputation: 4641

How about this approach?

(in pseudo-code)

  • set sum to 0
  • make an array mask of length equal to matrix width (number of columns), fill it with 1
  • for each row i
    • for every column j in the row i
      • if matrix[i,j] is zero, set mask[j] to 0.
      • sum += matrix[i,j]*mask[j]
  • return sum

Here's the code:

public class Program
{
    public static void Main()
    {
        int[] list1 = new int[4] { 0, 1, 1, 2};
        int[] list2 = new int[4] { 0, 5, 0, 0};
        int[] list3 = new int[4] { 2, 0, 3, 3 };
        int[][] lists = new int[][]{list1, list2, list3};

        var result = TestMethod(lists);
        Console.WriteLine(result);
    }

    public static int TestMethod(int[][] matrix)
    {
        int sum = 0;
        // fill the mask with ones
        int[] mask = Enumerable.Repeat(1, 4).ToArray();
        for(int i = 0; i < 3; i++){
            for(int j = 0; j < 4; j++){
                if (matrix[i][j] == 0) {
                    mask[j] = 0;
                }
                sum += matrix[i][j] * mask[j];
            }
        }
        return sum;

    }
}

Output:

9

You probably want to make number of columns and rows configurable.

Upvotes: 0

Dai
Dai

Reputation: 155438

I recommend using a 2D array instead of jagged arrays to avoid uncertainties about indexing higher dimensions:

int[,] matrix = new int[,]
{
    { 0, 1, 1, 2 }, 
    { 0, 5, 0, 0 },
    { 2, 0, 3, 3 },
};

Int32 sum = 0;

// Using row-major-order, so the indexer is [y,x] instead of the traditional [x,y]
for( int y = 0; y <= matrix.GetUpperBound(0); y++ )
for( int x = 0; x <= matrix.GetUpperBound(1); x++ )
{
    int cell = matrix[y,x];
    bool hasZeroAboveCurrentCell = y > 0 && matrix[y-1,x] != 0;

    if( cell != 0 && !hasZeroAboveCurrentCell )
    {
        sum += cell;
    }
}

Console.WriteLine( "Total: {0}", sum );

Upvotes: 0

Related Questions