1

Tutor gave me an assignment, to check in a 2D matrix if there are any rows which their sum equals to any sum of columns. Allowed to use only **1 loop** and only sum,any,size.

a = [2 3 4; 5 5 2; 1 3 3; 1 1 1]; --- % Just an example %

rows = size(a,1);
cols = size(a,2);
x = [rows, cols];
tA = a'; i = 1;
RowSum = zeros(rows,1)';
ColSum = zeros(1,cols);

while (i<=max(x))

    if (size(a,1)>=i)
        RowSum(i) = sum(a(i,:));
    end
    if (size(tA,1)>=i)
        ColSum(i) = sum(tA(i,:));
    end
  i=i+1;

end

I know it could be a bit messy, but it gave me the job. Now I don't know how to check if there are any matching values in RowSum and ColSum. (can't use intersect); Any idea?

Divakar
  • 218,885
  • 19
  • 262
  • 358
  • I don't think you should ask assignment questions on SO. – Lord Henry Wotton Dec 24 '14 at 00:12
  • @LordHenryWotton By saying "tutor" I mean by my friend (I'm not a student). I just got to a point where I have no idea how to keep progressing from here. – Daniel Watson Dec 24 '14 at 00:15
  • 1
    Two hints: you don't need a loop to sum the columns and rows (see [`sum`](http://www.mathworks.com/help/matlab/ref/sum.html)), and you should read the [`any`](http://www.mathworks.com/help/matlab/ref/any.html) documentation for the comparison portion. – TroyHaskin Dec 24 '14 at 00:17
  • @TroyHaskin I understand, I know how can use `sum(A,1)` for columns sum and `sum(A,2)` for rows sum. I can't figure how to use `any` if my matrix is not `NxN`.. – Daniel Watson Dec 24 '14 at 00:23
  • @DanielWatson `any` also accepts a logical vector and produces a logical scalar (`true` if any are `true`; `false` otherwise). Therefore, `any` can say whether a vector contains an element that matches a scalar: `tf = any(v==s)`. – TroyHaskin Dec 24 '14 at 00:28
  • @TroyHaskin thanks! managed to use the `any` with `for` loop. Is it possible to do it without a loop? – Daniel Watson Dec 24 '14 at 00:42
  • @DanielWatson: That's the one loop you are allowed to use, you have to get rid of all other loops. – Daniel Dec 24 '14 at 00:48
  • @DanielWatson Luis Mendo's answer is the no-loop solution. – TroyHaskin Dec 24 '14 at 00:52

3 Answers3

3

This is what I've done:

ColSum = sum(a,1);
RowSum = sum(a,2)';
r = 0;
for i=1:length(ColSum)
    if (any(RowSum==ColSum(i)))
        r = 1;
    end
end
disp(r);

Now trying to think how do to it without the loop..

  • Any way to do this entire thing without the loop and only with the functions above? – Daniel Watson Dec 24 '14 at 00:57
  • Only with the functions above and no loops? I lean toward no. – TroyHaskin Dec 24 '14 at 00:58
  • 2
    Also, you can exit the `for`-loop using the [`break`](http://www.mathworks.com/help/matlab/ref/break.html) command since you're only looking for the existence of a match and not the total number of matches. – TroyHaskin Dec 24 '14 at 00:59
  • 1
    @TroyHaskin My friend says that it is possible :/ I'll post here when I have the solution.. – Daniel Watson Dec 24 '14 at 01:01
  • @TroyHaskin Well I almost gave up, until I figured one way to do it without loop and with those three functions [here](http://stackoverflow.com/a/27636657/3293881). – Divakar Dec 24 '14 at 12:04
  • @DanielWatson I would be really interested in seeing what your "friend" had, to solve this without loop and with those three functions only, so please do post that as well. – Divakar Dec 24 '14 at 12:10
3

Discussion of the solution and code

You could employ this three-steps process and implement the solution with sum, size and any and without using any loop!!

The steps to be followed for such an implementation could be classified into three steps -

  • Get the sum of the input matrix along rows and columns.

  • Calculate the distance matrix between all elements of sum along rows against sum along columns. The is essentially the most important of these steps and you would have otherwise required at least one loop or bsxfun (for internal replication) to perform this. Now, the distance matrix calculation here is performed with matrix-multiplication and is a simplified case of this solution to Speed-efficient classification in Matlab.

  • For all distance matrix elements, see if there's any element that is zero.

The code to realize the above steps would look something like this -

%// Get the sum of rows and columns into column vectors - A and B respectively
A = sum(M,2)
B = sum(M,1)' %//'

%// Calculate the distance matrix between A and B
nA = size(A,1);
nB = size(B,1);

A_ext(nA,3) = 0;
A_ext(:,1) = 1;
A_ext(:,2) = -2*A;
A_ext(:,3) = A.^2;

B_ext(nB,3) = 0;
B_ext(:,3) = 1;
B_ext(:,1) = B.^2;
B_ext(:,2) = B;

distmat = A_ext * B_ext.'; %//'

%// For all distance matrix values check if any is zero for the final output
out = any(distmat(:)==0)

Sample run and verification

>> M (Sample input matrix)
M =
     2    14     3
     5     6     7
     1     5     5
     3     1     2

As can be seen that the sum along the third row is 11, which is the same as the sum along the first column. Thus, in the distance matrix, at least one element must be zero.

>> A (Sum along rows)
A =
    19
    18
    11
     6
>> B (Sum along columns)
B =
    11
    26
    17
>> distmat (distance matrix between A and B)
distmat =
    64    49     4
    49    64     1
     0   225    36
    25   400   121

As estimated earlier, there is one zero at (3,1) and thus, the final output of any(distmat(:)==0)would be 1, which is the expected final result.

Community
  • 1
  • 1
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • Super!! Great thinking :) – Daniel Watson Dec 24 '14 at 14:40
  • After trying to understand your solution, could you please explain how does the distance matrix works? (what do the values represent, except for the matrix multiplication). [Why did u multiply -2*A?] – Daniel Watson Dec 24 '14 at 15:30
  • 1
    @DanielWatson The link listed in the solution should clear out those questions. Here [it is linked again](http://stackoverflow.com/a/26994722/3293881). Under `Vectorized Variations`, look for Varation #1 and set `dim` to `1`. So, you need to look at this solution as a special case of that linked solution. – Divakar Dec 24 '14 at 15:31
2

After you solve it with one loop, sum, any, size, I suggest you read up on bsxfun and find a no-loop, one-line solution with bsxfun, sum, any (hover the mouse to check):

any(any(bsxfun(@eq, sum(a,1), sum(a,2))))

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • Cool, thanks. I guess that's not the function I'm allowed to use though, cuz I didn't learn about it yet. Good to know though! – Daniel Watson Dec 24 '14 at 00:56
  • I figured a way to do the `bsxfun(@eq` by calculating the distance matrix and checking if any of its element is zero. So, this was quite interesting for me. Then, I ran some benchmarks between these two, but didn't see any improvement for the distance matrix based solution over `bsxfun(@eq`, but I thought this was an interesting alternative, just for fun maybe :) – Divakar Dec 24 '14 at 12:08
  • @Divakar So you managed to do it without loops and with only those three functions! Well done! – Luis Mendo Dec 24 '14 at 12:52
  • @LuisMendo Yup! Basically that `bsxfun(@eq` translates to `pdist2()==0`, which you might have used before. Not efficient, but a fun alternative :) – Divakar Dec 24 '14 at 12:57
  • @Divakar Yes, I thought about `pdist2`, but it wasn't allowed. Now I remember you have used that matrix multiplication instead of `pdist2` before – Luis Mendo Dec 24 '14 at 12:58