17
\$\begingroup\$

In case there's any doubt: Nan = Non-numeric datatype for the purposes of this challenge.


Write a program or function that takes a matrix / array as input, as well as a list of column indices.

The challenge is to remove the rows where all elements in the specified columns are Nan. It doesn't matter if other elements in the row are numeric or not. The following examples will hopefully make this more clear (it's one-indexed):

Input array:
    16   NaN     3    13
     5    11   NaN     8
   NaN     7   NaN    12
     4    14   -15     1

Input column index: [1 3]

Output array:
16   NaN     3    13
 5    11   NaN     8
 4    14   -15     1

----

Input array:
    16   NaN     3    13
     5    11   NaN     8
   NaN     7   NaN    12
     4    14   -15     1

Input column index: 3

Output array =
    16   NaN     3    13
     4    14   -15     1

----

Input array:
   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

Input column index: 1 2 4

Output array:
 []

Rules and clarifications:

  • The matrix will always be non-empty
  • The numeric values will be finite, but not necessarily integers or positive values
  • The column index vector can be empty (in which case no rows will be removed)
  • The column index will never have values exceeding the matrix dimensions
  • You can assume there won't be duplicates in the column index list
  • You can choose if you want to use zero- or one-indexed values (please specify)
  • You can take the input on any convenient format
    • Array as list of lists is OK. The column indices can be separate arguments
  • ans = and similar is accepted in output
  • You are free to choose what type of non-numeric datatype you want to use
    • It should be impossible to perform arithmetic operations with this datatype, or convert it to a finite number using functions such as float(x).

This is code golf, so shortest code in bytes win.

\$\endgroup\$
0

12 Answers 12

6
\$\begingroup\$

Pyth, 16 19 10 9 7 10 Bytes

Column indices start at zero. Input is a list of lists. Uses an empty string as non-numeric value. Takes list of column indices on the first line and the Matrix with the values on the second line.

?Qf-QxkTEE

Try it online!

Explanation

?Qf-QxkTEE       # Implicit: Q=column indices, E=Matrix

?Q       E       # If column list is empty no rows get removed
  f     E        # filter the given matrix by each row T
     xkT         # Get the indices of all occurences of an emtpy string (k) 
   -Q            # If the indices match with the given column indices, remove the row
    
     

Update: My first solution handled an empty list of column indices wrong. Fixed it (pretty ugly) at the cost of 3 Bytes. Gonna try to do it better after work...

Update 2: Golfed it down to 10 9 7 bytes, with some help from @FryAmTheEggman an by improving the algorithm significantly.

Update3: Fixed a bug @ThomasKwa discovered. His proposed 7-byte solution did not handle empty column indices right, so I just catch that case with a ternary here. I don't see how I can shorten this atm.

\$\endgroup\$
12
  • 1
    \$\begingroup\$ You can replace J with vz and K with Q. z is initialized to input, Q to evaluated input. \$\endgroup\$ Feb 2, 2016 at 13:19
  • \$\begingroup\$ @Pietu1998 Thanks a lot! :) I knew I was missing something in that regard. Sadly I found a bug when I looked at it again to implement your suggestion which overall increases my byte count until I find a nicer solution. \$\endgroup\$
    – Denker
    Feb 2, 2016 at 13:44
  • 1
    \$\begingroup\$ ?KEfnmklKm@TdKQQ empty lists are falsy in Pyth, and assignment statements return the value that was assigned, which saves some bytes. I hope you enjoy golfing Pyth! :) \$\endgroup\$ Feb 2, 2016 at 15:48
  • \$\begingroup\$ @FryAmTheEggman Thanks for the suggestions. Is not really relevant anymore since I improved the algorithm a lot, but I really appreciate the help! :) \$\endgroup\$
    – Denker
    Feb 2, 2016 at 16:54
  • \$\begingroup\$ Very nice :) you can save another byte using L -> fnks@LTQE \$\endgroup\$ Feb 2, 2016 at 16:59
6
\$\begingroup\$

JavaScript (ES6), 48 46 bytes

(a,l)=>a.filter(r=>l.some(c=>r[a=0,c]<1/0)||a)

Explanation

Expects an array of rows as arrays, and an array of 0-indexed numbers for the columns to check. Returns an array of arrays.

Straight-forward filter and some. Checks for NaN by using n < Infinity (true for finite numbers, false for NaNs).

var solution =

(a,l)=>
  a.filter(r=>     // for each row r
    l.some(c=>     // for each column to check c
      r[a=0,       // set a to false so we know the some was executed
        c]<1/0     // if any are not NaN, do not remove the row
    )
    ||a            // default to a because if l is of length 0, some returns false but
  )                //     we must return true
<textarea id="matrix" rows="5" cols="40">16 NaN 3 13
5 11 NaN 8
NaN 7 NaN 12
4 14 -15 1</textarea><br />
<input type="text" id="columns" value="0 2" />
<button onclick="result.textContent=solution(matrix.value.split('\n').map(l=>l.split(' ').map(n=>+n)),(columns.value.match(/\d+/g)||[]).map(n=>+n)).join('\n')">Go</button>
<pre id="result"></pre>

\$\endgroup\$
1
  • \$\begingroup\$ Nice handling of that edge case! \$\endgroup\$
    – Neil
    Feb 2, 2016 at 19:25
3
\$\begingroup\$

CJam, 18 bytes

{{1$\f=_!\se|},\;}

An unnamed block (function) expecting the matrix and the zero-based column indices on the stack (the matrix on top), which leaves the filtered matrix on the stack. I'm using the empty array "" as the non-numeric value.

Test it here.

Explanation

{     e# Filter the matrix rows based on the result of this block...
  1$  e#   Copy the column indices.
  \f= e#   Map them to the corresponding cell in the current row.
  _!  e#   Duplicate, logical NOT. Gives 1 for empty column list, 0 otherwise.
  \s  e#   Convert other copy to string. If the array contained only empty arrays, this 
      e#   will be an empty string which is falsy. Otherwise it will contain the numbers 
      e#   that were left after filtering, so it's non-empty and truthy.
  e|  e#   Logical OR.
},
\;    e# Discard the column indices.
\$\endgroup\$
7
  • \$\begingroup\$ Am I testing it wrong or does this violate the rule about no given column indices? The column index vector can be empty (in which case no rows will be removed) \$\endgroup\$
    – Denker
    Feb 2, 2016 at 13:59
  • \$\begingroup\$ @DenkerAffe Damn, fixed at the cost of 5 bytes... \$\endgroup\$ Feb 2, 2016 at 14:05
  • \$\begingroup\$ I was there too...You still one byte ahead of me tho, so my plan did not work out yet :P \$\endgroup\$
    – Denker
    Feb 2, 2016 at 14:13
  • \$\begingroup\$ "the empty array """ Did you mean "the empty string"? \$\endgroup\$ Feb 2, 2016 at 15:48
  • \$\begingroup\$ @ETHproductions There is no difference in CJam. Strings are just arrays of characters, so [] and "" are identical and the canonical representation is "" (e.g. it's what you get when you stringify an empty array). \$\endgroup\$ Feb 2, 2016 at 15:51
3
\$\begingroup\$

APL, 19 bytes

{⍵⌿⍨∨/⍬∘≡¨0↑¨⍵[;⍺]}

The left argument should be a list of indices (and it must be a list, not a scalar), the right argument is the matrix. APL has two datatypes, numbers and characters, so this filters out the character types.

Tests:

      m1 m2
   16  NaN    3  13   NaN  NaN  NaN  NaN  
    5   11  NaN   8   NaN  NaN  NaN  NaN  
  NaN    7  NaN  12   NaN  NaN  NaN  NaN  
    4   14  ¯15   1   NaN  NaN  NaN  NaN  
      1 3 {⍵⌿⍨∨/⍬∘≡¨0↑¨⍵[;⍺]} m1
16  NaN    3  13
 5   11  NaN   8
 4   14  ¯15   1
      (,3) {⍵⌿⍨∨/⍬∘≡¨0↑¨⍵[;⍺]} m1
16  NaN    3 13
 4   14  ¯15  1
      1 2 4 {⍵⌿⍨∨/⍬∘≡¨0↑¨⍵[;⍺]} m2 ⍝ this shows nothing
      ⍴1 2 4 {⍵⌿⍨∨/⍬∘≡¨0↑¨⍵[;⍺]} m2 ⍝ the nothing is in fact a 0-by-4 matrix
0 4

Explanation:

  • ⍵[;⍺]: select the given columns from the matrix
  • 0↑¨: take the first 0 elements from the start of each item
  • ⍬∘≡¨: compare to the numerical empty list
  • ∨/: see in which of the rows at least one item matches
  • ⍵⌿⍨: select those rows from the matrix
\$\endgroup\$
2
\$\begingroup\$

MATLAB, 32 28 bytes

I'll answer my own question for once. The best I can do in MATLAB is 28 bytes. I was hoping to avoid using both all and isnan somehow, but haven't found a way yet.

@(A,c)A(any(A(:,c)<inf,2),:)

Test:

A =
    35     1   NaN   NaN   NaN    24
     3    32   NaN    21    23    25
    31   NaN   NaN   NaN    27    20
   NaN    28   NaN    17   NaN    15
    30     5   NaN    12    14   NaN
     4    36   NaN    13    18    11

f(A,[3,5])
ans =
     3    32   NaN    21    23    25
    31   NaN   NaN   NaN    27    20
    30     5   NaN    12    14   NaN
     4    36   NaN    13    18    11

This is an unnamed anonymous function that takes the input matrix as the first input variable, and a list of column indices as the second.

In MATLAB, NaN < Inf evaluates to false. It can be assumed that all values are finite, thus checking if values are less than inf is equivalent to checking if they are non-numeric. any(...,2) checks if there are any true values along the second dimension (rows). If that's the case, then those rows will be returned.

Old version:

@(A,c)A(~all(isnan(A(:,c)),2),:)

isnan(A(:,c)) returns an array with booleans for the specified columns. ~all(isnan(A(:,c)),2) checks if all values along the second dimension (rows) are non-numeric, and negates it. This results in a boolean vector with ones in the positions we want to keep. A(~all(isnan(A(:,c)),2),:) uses logical indexing to extract the entire rows for A.


The following 24 byte solution would work if the values were guaranteed to be non-zero:

@(A,c)A(any(A(:,c),2),:)
\$\endgroup\$
2
\$\begingroup\$

Ruby, 48 bytes

->a,c{a.select{|r|c.map{|i|Fixnum===r[i]}.any?}}

Input is 0-based indices1.

Fairly self-explanatory, actually. select elements from the array where any? of the indices mapped over the row are Fixnums.

Sample run:

irb(main):010:0> (->a,c{a.select{|r|c.map{|i|Fixnum===r[i]}.any?}})[[[16,'',3,13],[5,11,'',8],['',7,'',12],[4,14,-15,1]],[0,2]]
=> [[16, "", 3, 13], [5, 11, "", 8], [4, 14, -15, 1]]

1: I finally spelled this word correctly on the first try! \o/

\$\endgroup\$
2
\$\begingroup\$

K5, 15 bytes

This uses 0-indexed columns and K's natural list-of-lists matrix representation:

{x@&~&/'^x[;y]}

Index into the matrix (x@) the rows where (&) not all of each (~&/') is null (^).

In action:

  m: (16 0N 3 13;5 11 0N 8;0N 7 0N 12;4 14 -15 1);
  f: {x@&~&/'^x[;y]};

  f[m;0 2]
(16 0N 3 13
 5 11 0N 8
 4 14 -15 1)

  f[m;2]
(16 0N 3 13
 4 14 -15 1)
\$\endgroup\$
2
\$\begingroup\$

MATL, 15 16 bytes

tiZ)tn?ZN!XA~Y)

NaN is represented in the input as N. Indexing is 1-based. For example, in the first test case the input is

[16 N 3 13; 5 11 N 8; N 7 N 12; 4 14 -15 1]
[1 3]

Try it online!

Explanation

t       % implicitly input matrix, M. Duplicate
i       % input vector specifying columns
Z)      % matrix N containing those columns of M
tn?     % duplicate matrix N. If non-empty ...
  ZN    %   true for NaN values in matrix N
  !     %   transpose
  XA    %   "all" within each column: gives true for rows of N that contained all NaN's
  ~     %   logical negate
  Y)    %   apply this logical index as a row index into the copy of M that was left
        %   at the bottom of the stack
        % ... implicitly end if
        % implictly display stack contents. If the input vector was empty, the stack
        % contains the original matrix M and an empty matrix. The latter produces no
        % displayed output. If the input vector was non-empty, the stack contains the
        % resulting matrix N
\$\endgroup\$
2
\$\begingroup\$

R, 49 bytes

function(m,j)m[!!rowSums(!is.nan(m[,j,drop=F])),]

Input is 1-based. The function takes a matrix (m) and a vector of column indices (j) which may be missing.

Two test cases:

> f <- function(m,j)m[!!rowSums(!is.nan(m[,j,drop=F])),]
> f(m)   
      V1  V2  V3 V4
[1,]  16 NaN   3 13
[2,]   5  11 NaN  8
[3,] NaN   7 NaN 12
[4,]   4  14 -15  1

> f(m, c(1,3))
     V1  V2  V3 V4
[1,] 16 NaN   3 13
[2,]  5  11 NaN  8
[3,]  4  14 -15  1
\$\endgroup\$
0
\$\begingroup\$

Lua, 148 Bytes

A function that takes a matrix and an array as input, and output a matrix with the corresponding rows at nil. As arrays are quite the same as C's arrays, nihilating is like free()ing it as the garbage collector isn't far away.

Arrays are 1-indexed in Lua, and I use the string "NaN" as a non-nomber element.

function f(m,l)c=1 while(c<#m)do x=0 for j=1,#l do x=x+((type(m[c][l[j]])=="number")and 0 or 1)end m[c]=(x<#l and m[c] or nil)c=c+1 end return m end

You can try Lua online, and copy/paste the following code sample to try this submission:

-- The function that does the stuff
function f(m,l)
  c=1 
  while(c<#m)
  do 
    x=0 
    for j=1,#l 
    do 
      x=x+((type(m[c][l[j]])=="number")and 0 or 1)
    end
    m[c]=(x<#l and m[c] or nil)
    c=c+1 
   end 
   return m 
end
-- A function to format matrixes into "readable" strings
function printMatrix(matrix,len)
  s="{"
  for v=1,len
  do
    if matrix[v]~=nil
    then
      s=s.."{"..table.concat(matrix[v],",").."}"..(v<len and",\n "or"")
    end
  end
  s=s.."}"
  print(s)
end

nan="NaN"
-- Datas in, indexed as matrices[testCase][row][column]
matrices={{{7,nan,5,3},{5,4,nan,4},{nan,4,nan,9},{5,7,9,8}},
{{16,nan,3,13},{5,11,nan,8},{nan,7,nan,12},{4,14,-15,1}},
{{nan,nan,nan,nan},{nan,nan,nan,nan},{nan,nan,nan,nan},{nan,nan,nan,nan}}}
indexes={{1,3},{3},{1,2,4}}

-- looping so we can test lots of things at once :)
for i=1,#matrices
do
  print("\ninput: "..table.concat(indexes[i]," "))
  printMatrix(matrices[i],4)
  print("output:")
  printMatrix(f(matrices[i],indexes[i]),4)
end
\$\endgroup\$
0
\$\begingroup\$

Mathematica, 52 51 49 46 bytes

Delete[#,Extract[#,{;;,#2}]~Position~{NaN..}]&

Input is [matrix as list of lists,vector of columns]

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to Programming Puzzles & Code Golf! :) Please correct your formatting and specify your input format including the indexing of the columns as asked in the challenge. \$\endgroup\$
    – Denker
    Feb 2, 2016 at 17:36
0
\$\begingroup\$

Haskell, 39 bytes

m#[]=m
m#r=[l|l<-m,any(<1/0)$map(l!!)r]

This uses 0-based indices. Usage example (I'm using sqrt(-1) to create NaNs):

*Main> [[16,sqrt(-1),3,13], [5,11,sqrt(-1),8], [sqrt(-1),7,sqrt(-1),12], [4,14,-15,1]] # [0,2]
[[16.0,NaN,3.0,13.0],[5.0,11.0,NaN,8.0],[4.0,14.0,-15.0,1.0]]

It's just a simple filter as seen in other answers via list comprehension. The special case of an empty index list is caught separately.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.