Reputation: 5953
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:
This problem can be found on CodeFights
Upvotes: 2
Views: 7209
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 -1
st row of the matrix.
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
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
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 ==
Enumerable.Range(0, lists.First().Length)
: enumerate all the column indexes.Sum(column => ...
: Aggregate the results of inner(second) layer through summationEssentially, 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.
Enumerable.Range(0, lists.Length)
: same as step#1, but with row indexes.Select(row => lists[row][column])
: project the row indexes into values on the respective indexes..TakeWhile(value => value != 0)
: allow us to skip 0
itself and every number after(below) it.Sum()
: add up everythingUpvotes: 3
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
Reputation: 4641
How about this approach?
(in pseudo-code)
sum
to 0mask
of length equal to matrix width (number of columns), fill it with 1i
j
in the row i
matrix[i,j]
is zero, set mask[j]
to 0.sum += matrix[i,j]*mask[j]
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
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