Index of the row with most non-zero elements

26

2

This is a simple one: Take a matrix of integers as input, and output the index of the row with the most non-zero elements. You may assume that there will only be one row with the most non-zero elements.

Test cases:

These are 1-indexed, you may choose if you want 0 or 1-indexed.

1
0
row = 1
---
0  -1
0   0
row = 1
---
1   1   0   0   0
0   0   5   0   0
2   3   0   0   0
0   5   6   2   2
row = 4
---
0   4   1   0
0   0  -6   0
0   1   4  -3
2   0   0   8
0   0   0   0
row = 3

Stewie Griffin

Posted 2017-06-26T15:25:39.330

Reputation: 43 471

Answers

8

MATL, 6 bytes

!gs&X>

Input is a matrix, with ; as row separator.

Try it online! Or verify all test cases.

Explanation

!     % Transpose
g     % Logical: convert non-zeros to 1
s     % Sum of each column, or sum of row if there's a single row
&X>   % Arg max. Implicitly display

Luis Mendo

Posted 2017-06-26T15:25:39.330

Reputation: 87 464

6

Mathematica, 23 bytes

Ordering[Count@0/@#,1]&

alephalpha

Posted 2017-06-26T15:25:39.330

Reputation: 23 988

6

R, 31 bytes

pryr::f(which.min(rowSums(!m)))

returns an anonymous function which takes a matrix:

function(m)which.min(rowSums(!m))

rowSums sums the rows, with !m transforming 0 to 1 and everything else to 0. which.min returns the 1-based index of the first row which contains the min sum (i.e., which row has the fewest zeros).

Try it online!

Giuseppe

Posted 2017-06-26T15:25:39.330

Reputation: 21 077

You need which.min() since non-zero elements will become FALSE with !m. – user2390246 – 2017-06-26T16:09:11.563

@user2390246 oh, wow, I completely misread the question. Fixed, thank you. – Giuseppe – 2017-06-26T16:33:05.023

6

05AB1E, 8 6 bytes

ΣĀO}θk

Try it online!

-2 Bytes thanks to Erik the Outgolfer

Explanation

ΣĀO}θk
Σ  }   # Sort input by following code
 Ā      # Is element not 0? (vectorized)
  O     # Sum
    θk # Get index of "largest" element
       # Implicit print

Datboi

Posted 2017-06-26T15:25:39.330

Reputation: 1 213

Use Ā instead of Ä0› for -2. – Erik the Outgolfer – 2017-06-26T16:31:08.700

Yee just realized there is probably a better way to do that part than what I had. Damn I feel like I'm learning a new 05AB1E command every day ^^ – Datboi – 2017-06-26T16:32:40.640

5

Haskell, 46 42 41 bytes

snd.minimum.(`zip`[1..]).map(filter(==0))

Try it online!

How it works

    map                    -- for each row
        (filter(==0))      -- collect the 0s
    (`zip`[1..])           -- pair with row index  (<#0s>, <index>)
  minimum                  -- find the minimum
snd                        -- extract index from pair

nimi

Posted 2017-06-26T15:25:39.330

Reputation: 34 639

Nice! Better than mine, good to learn something. – Henry – 2017-06-27T03:42:41.650

4

C#, 69 bytes

using System.Linq;m=>m.IndexOf(m.OrderBy(r=>r.Count(n=>n!=0)).Last())

Takes a List<int[]> as input and returns the 0-indexed result.

TheLethalCoder

Posted 2017-06-26T15:25:39.330

Reputation: 6 930

3

Python 3, 54 48 bytes

lambda a:a.index(min(a,key=lambda r:r.count(0)))

Shaved off 6 bytes. Old solution:

lambda a:min(range(len(a)),key=lambda i:a[i].count(0))

CensoredUsername

Posted 2017-06-26T15:25:39.330

Reputation: 951

1Just noticed it matches directly with the changes to the python 2 answer now. – CensoredUsername – 2017-06-26T16:49:29.767

3

Actually, 9 bytes

0@♀cñ♂RmN

Try it online!

Explanation:

0@♀cñ♂RmN
0@♀c       count zeroes in each row
    ñ♂R    enumerate and reverse each row (each row becomes [count, index] pair)
       m   minimum
        N  last element (the index)

Mego

Posted 2017-06-26T15:25:39.330

Reputation: 32 998

3

APL (Dyalog), 11 bytes

(⊢⍳⌈/)+/0≠⎕

Try it online!

0≠⎕ Boolean matrix where non-zero

+/ sum rows

( apply the following tacit function to the list of sums

⌈/ the maximum's

 index

 in the argument list

)

Adám

Posted 2017-06-26T15:25:39.330

Reputation: 37 779

3

Brachylog, 17 bytes

{{∋0}ᶜ}ᵐA;.∋₎~⌋A∧

Try it online!

Leaky Nun

Posted 2017-06-26T15:25:39.330

Reputation: 45 011

2

Jelly, 5 bytes

TL$€M

Try it online!

1-indexed.

So many 5-byte versions...

TL$€M, T€L€M, TJ$€M, T€J€M, ¬¬Ṣ€M, ṠAṢ€M, ṠAS€M, AṠṢ€M, AṠS€M, ¬ċ€0M, ...

Erik the Outgolfer

Posted 2017-06-26T15:25:39.330

Reputation: 38 134

Why do they all look like words? – caird coinheringaahing – 2017-06-26T22:33:56.603

2

Clojure, 64 bytes

This one works also with negative numbers in the input, luckily the same length as the original:

#(nth(sort-by(fn[i](count(filter #{0}(% i))))(range(count %)))0)

Original:

#(last(sort-by(fn[i](count(filter pos?(% i))))(range(count %))))

NikoNyrh

Posted 2017-06-26T15:25:39.330

Reputation: 2 361

numbers in matrix are integers. so pos? isn't correct – cliffroot – 2017-06-27T09:29:34.747

True, I forgot to account for negative integers. Fixed now. – NikoNyrh – 2017-06-27T10:22:30.693

2

05AB1E, 5 bytes

€ĀOZk

Try it online!

0-indexed.

Erik the Outgolfer

Posted 2017-06-26T15:25:39.330

Reputation: 38 134

2

Haskell - 69 68 Bytes

Saved one byte thanks to Siracusa!

Rows are zero indexed

g=filter
m y=head$g((==maximum y).(y!!))[0..]
f=m.map(length.g(0/=))

Usage

f [[1,1,0,0,0],[2,3,0,0,0],[0,5,6,2,2],[1,1,1,1,1]]

Try it online!

Henry

Posted 2017-06-26T15:25:39.330

Reputation: 461

Defining g=filter saves you one byte – siracusa – 2017-06-26T17:54:02.153

You can even remove a few bytes more with m y=length$takeWhile(<maximum y)y and shortening length instead of filter – siracusa – 2017-06-26T19:13:18.957

2

CJam, 11 bytes

{0fe=_:e<#}

Try it online!

-2 thanks to Challenger5.

Erik the Outgolfer

Posted 2017-06-26T15:25:39.330

Reputation: 38 134

11: {0fe=_:e>#} – Esolanging Fruit – 2017-06-30T04:46:41.807

@Challenger5 > should be < instead...thanks anyways. :) – Erik the Outgolfer – 2017-06-30T07:27:12.873

2

q/kdb+, 25 17 16 bytes

Solution:

(*)(<)sum(+)0=/:

Example:

q)(*)(<)sum(+)0=/:enlist(1;0)
0
q)(*)(<)sum(+)0=/:(0 -1;0 0)
0
q)(*)(<)sum(+)0=/:(1 1 0 0 0;0 0 5 0 0;2 3 0 0 0;0 5 6 2 2)
3
q)(*)(<)sum(+)0=/:(0 4 1 0;0 0 -6 0;0 1 4 -3;2 0 0 8;0 0 0 0)
2

Explanation:

first iasc sum flip 0=/:  / ungolfed
                      /:  / each right, apply a function to each item to the right
                    0=    / returns boolean 1b or 0b if item in each list is equal to zero
               flip       / flip (rotate) the output
           sum            / sum these up
      iasc                / return indices if we were to sort ascending
first                     / take the first one

Notes:

The problem is fairly straightforward, this solution feels overly complicated. As soon as I hit submit I realised the error of my ways.

Bonus:

Here's a k solution that weights in at 16 10 9 bytes - almost exactly the same but 7 bytes shorter due to the fact we don't need brackets when using the k built-ins, and as a result some become shorter than the q keywords (e.g. +/ for sum (would be (+/) in q)).

*<+/+0=/:

streetster

Posted 2017-06-26T15:25:39.330

Reputation: 3 635

1

Jelly, 7 bytes

ċ0$ÞḢi@

Try it online!

ċ0$ÞḢi@  Main link
   Þ     Sort by
ċ0$              the number of occurences of 0
    Ḣ    Take the first element
     i@  Index in the original array

HyperNeutrino

Posted 2017-06-26T15:25:39.330

Reputation: 26 575

1

Python 2, 64 55 52 48 bytes

  • Thanks to @Rod for shaving 9 bytes!!: count 0s and use min() instead of max()
  • @Rod saved yet another 3 bytes: use input() instead of def
  • @ovs saved 4 bytes: use of lambda and hash-map
lambda x:x.index(min(x,key=lambda n:n.count(0)))

Try it online!

officialaimm

Posted 2017-06-26T15:25:39.330

Reputation: 2 739

248 bytes – ovs – 2017-06-26T16:28:01.223

Thanks @ovs. I didn't exactly understand how it works though. – officialaimm – 2017-06-26T16:36:52.763

1

It's more or less the same logic that you had on your answer, but using min with the key parameter

– Rod – 2017-06-26T18:54:48.023

1

JavaScript (ES6), 62 bytes

0-indexed. Takes a 2D array as input.

a=>(a=a.map(x=>x.filter(y=>y).length)).indexOf(Math.max(...a))

Shaggy

Posted 2017-06-26T15:25:39.330

Reputation: 24 623

Can you add an explanation for this one? Does filter implicitly "filter" zeroes? – TheLethalCoder – 2017-06-26T16:10:19.507

You're supposed to return the index of the row... – Neil – 2017-06-26T16:10:59.947

Still trying to golf some more off it, @TheLethalCoder, will be adding a demo and an explanation when I'm done. In the meantime, see here for more info on filter, keeping in mind that 0 is falsey.

– Shaggy – 2017-06-26T16:28:57.743

@Neil: Fixed now. – Shaggy – 2017-06-26T16:29:11.403

@Shaggy I assumed that was the case with filter was just making sure. – TheLethalCoder – 2017-06-26T16:30:41.337

You may already be below that score by now, but here's a 61: a=>a.map((r,i)=>m=r.map(v=>n+=!!v,n=0)&&n>m?(o=i,n):m,m=0)&&o (not really tested). – Arnauld – 2017-06-26T17:18:43.723

1

PHP, 58 bytes

0-Indexed

<?=array_search(max($a=array_map(array_filter,$_GET)),$a);

Try it online!

Jörg Hülsermann

Posted 2017-06-26T15:25:39.330

Reputation: 13 026

1

V, 18 bytes

òø0
jòÚDuu/"
dGؾ

Try it online!

Unlike most V answers, this is 0-indexed.

00000000: f2f8 300a 6af2 da44 7575 2f12 220a 6447  ..0.j..Duu/.".dG
00000010: d8be                                     ..

Not bad for a language with no numeric support! ;P

I also have discovered that the uppercase variant of the count command, that is Ø, is horribly broken.

James

Posted 2017-06-26T15:25:39.330

Reputation: 54 537

1

Python 3, 92 bytes

def f(x):
    for e in x:
        e.sort()
    y=x[:]
    y.sort()
    return x.index(y[-1])

First sort each row such that the entrys are [0,0,..,0,x,x,x] then sort the whole matrix, so that the last entry in y is the row we are looking for. The copy y=x[:] is necessary, since .sort() works inplace, hence we don't know the original index after sorting.

I appreciate any help how to golf this solution further. Most bytes are lost because of the whitespaces in each line. The code itself is only 68 bytes long.

Try it online!

P. Siehr

Posted 2017-06-26T15:25:39.330

Reputation: 227

1I don't know Python but can't you remove most of the whitespace from this? – TheLethalCoder – 2017-06-26T16:09:01.213

@TheLethalCoder Python uses indentation instead of brackets for codeblocks, instead of brackets or keywords (e.g. for .. end). – P. Siehr – 2017-06-26T16:12:18.623

1Even then python can be golfed a fair amount. The following is equivalent to your original code: def f(a):b=list(map(sorted,a));return b.index(sorted(b)[-1]) – CensoredUsername – 2017-06-26T16:13:56.093

This answer uses a for loop and a function but with no newlines so I assume you can remove a lot of them although it is Python 2 the whitespace restrictions should be similar. – TheLethalCoder – 2017-06-26T16:14:12.070

3Don't works for lists with negative numbers – Rod – 2017-06-26T16:18:28.377

Even 56 bytes: def f(x):k=[i.count(0)for i in x];print(k.index(min(k))) – Mr. Xcoder – 2017-06-26T19:44:24.533

1

Pyth, 6 bytes

xQh/D0

Demonstration

Instead of finding the row with the most non-zero elements, I find the row with the least zero elements.

/D0: Order (D) by count (/) of zeros (0). Implicitly applied to Q, the input.

h: Take the first, and minimum, element.

xQ: Find the index (x) in the input (Q) of that element.

isaacg

Posted 2017-06-26T15:25:39.330

Reputation: 39 268

This was exactly what I had a well. It felt clunky and like I was missing something, but it seems like there's just not a clean way to do it :( – FryAmTheEggman – 2017-06-27T01:29:57.673

1

Retina, 46 bytes

%M`\b0
m`(?<=(¶.+)*)$
;$#1
O#`.+
!`(?<=^.+;).+

Try it online!

0-indexed. Works with positive and negative integers (and 0). Assumes no leading zeros.

Leaky Nun

Posted 2017-06-26T15:25:39.330

Reputation: 45 011

1

Java (OpenJDK 8), 119 101 bytes

m->{int i=m.length,M=0,I=0,c;for(;i-->0;){c=0;for(int x:m[i])if(x!=0)c++;if(c>M){M=c;I=i;}}return I;}

Try it online!

Java, that sweet verbose language :)

Thanks for saving 18 bytes, @KevinCruijssen ;)

Olivier Grégoire

Posted 2017-06-26T15:25:39.330

Reputation: 10 647

+1 nice answer. Was about to post an even more verbose answer myself.. Was doubting whether to post it, and it's a good thing I hadn't since it's 145 bytes and ugly.. ;) Here it is... EDIT: Hmm, btw, your last two test cases fail..

– Kevin Cruijssen – 2017-06-27T08:46:14.537

Checking your code just made me realize there's a bug in my answer! o_O I don't even know how my test cases pass... – Olivier Grégoire – 2017-06-27T08:49:21.530

Good to go, I fixed it! – Olivier Grégoire – 2017-06-27T08:51:40.150

1

Nice! Btw, you can golf it by using a for-each inner loop to get rid of j and other longer parts like j=m[i].length, and m[i][j] like this: m->{int i=m.length,M=0,I=0,c;for(;i-->0;){c=0;for(int x:m[i])if(x!=0)c++;if(c>M){M=c;I=i;}}return I;} (101 bytes)

– Kevin Cruijssen – 2017-06-27T09:01:19.800

1

Java 8, 145 bytes

import java.util.*;m->{int t=0,s=0,i=0,r=0;for(;i<m.size();i++){List l=(List)m.get(i);for(;l.remove(0L););s=l.size();if(s>t){t=s;r=i;}}return r;}

Ugly, but it works..

Explanation:

Try it here.

import java.util.*;         // Required import for List

m->{                        // Method with List parameter and integer return-type
  int t=0,s=0,i=0,          //  Temp integers
      r=0;                  //  Result integer
  for(;i<m.size();i++){     //  Loop over the List of Lists
    List l=(List)m.get(i);  //   Get the inner List
    for(;l.remove(0L););    //   Remove all zeros
    s=l.size();             //   Get the size of the List
    if(s>t){                //   If this size is larger than the previous
      t=s;                  //    Set `t` to this size
      r=i;                  //    And set the result to the index of this row
    }
  }                         //  End of loop
  return r;                 //  Return result-integer
}                           // End of method

Kevin Cruijssen

Posted 2017-06-26T15:25:39.330

Reputation: 67 575

1

JavaScript (ES6), 51 Bytes

m=>m.reduce((a,e,i)=>e.filter(x=>x).length>a?i:a,0)

where m is a 2D array and the index returned is 0-indexed

Test cases:

f=
m=>m.reduce((a,e,i)=>e.filter(x=>x).length>a?i:a,0)

console.log(f([[1], [0]]))
console.log(f([[0,-1], [0,0]]))
console.log(f([[1,1,0,0,0], [0,0,5,0,0], [2,3,0,0,0], [0,5,6,2,2]]))
console.log(f([[0,4,1,0], [0,0,-6,0], [0,1,4,-3], [2,0,0,8], [0,0,0,0]]))

Craig Ayre

Posted 2017-06-26T15:25:39.330

Reputation: 217

1

Python 2, 51 bytes

def f(x,i=0):print i;x[i].remove(0);f(x,-~i%len(x))

Try it online!

This version removes 0s progressively through the arrays, printing the current index, and crashes when there are no more zeros to remove. Last printed index is the answer.

Python 2, 57 bytes

lambda x,i=0:0in x[i]>x[i].remove(0)and f(x,-~i%len(x))|i

Try it online!

Wanted to try a different approach from what's already here. So here I recursively iterate over the array removing one 0 at a time until the current array no longer has any zeroes - and then output the index of that array.

Coty Johnathan Saxman

Posted 2017-06-26T15:25:39.330

Reputation: 280

1

Java 8, 100 bytes

m->m.indexOf(m.stream().map(z->{z.removeIf(x->x==0);return z;}).max((q,r)->q.size()-r.size()).get())

Explanation

The power of Lists and Streams! (and without the imports, to boot!)

Let's break this little lambda down into chunks:

m.stream().map(z->{z.removeIf(x->x==0);return z;}

We turn our List of Lists (the matrix in the question) into a Stream and go through each element, removing all of those pesky zeroes from each sub-List. We need to explicitly return the sublist each time here, because Stream.map() converts each object in the Stream to whatever the mapping returns, and we don't want to change them.

.max((q,r)->q.size()-r.size()).get()

We go through our newly de-zeroed sublists, and simply check how big they are next to each other, getting us the biggest sublist. The .get() is because the Stream.max() returns an Optional, requiring that extra function call.

m.indexOf()

We take that biggest sublist, and find where it is in the main List, giving us our result!

Notes

This breaks if the outer list is empty, but I'm taking

You may assume that there will only be one row with the most non-zero elements.

to imply that there will always be at least one row. Correct me if I'm wrong.

Xanderhall

Posted 2017-06-26T15:25:39.330

Reputation: 1 236

1

Japt, 7 bytes

0-indexed. Takes input as an array of arrays.

mè
bUrw

Test it


Explanation

Implicit input of array U.
[[0,4,1,0],[0,0,-6,0],[0,1,4,-3],[2,0,0,8],[0,0,0,0]]

Map (m) over U returning the count of truthy (non-zero) elements in each sub-array. Implicitly assign this new array to U.
[2,1,3,2,0]

Urw

Reduce (r) array U by getting the greater of the current value and the current element.
3

b

Get the first index in U where the element equals that value and implicitly output the result.
2

Shaggy

Posted 2017-06-26T15:25:39.330

Reputation: 24 623

0

Python 2, 62 bytes

lambda m:max(range(len(m)),key=lambda n:len(filter(abs,m[n])))

Try it online!

ovs

Posted 2017-06-26T15:25:39.330

Reputation: 21 408

0

J, 16 bytes

0{[:/:@:+/@|:0=]

Try it online!

Leaky Nun

Posted 2017-06-26T15:25:39.330

Reputation: 45 011