20
\$\begingroup\$

Introduction

Suppose you have a list of lists of integers (or any objects really, but let's stick to integers for simplicity). The lists may be of different lengths, and some of them may be empty. Let's write the lists in a tabular format:

[[ 1,   2,   3,   4,   5],
 [ 6,   7],
 [ 8,   9,  10,  11],
 [],
 [12,  13,  14],
 [15,  16,  17,  18]]

This table has 5 vertical columns, containing the numbers 1, 6, 8, 12, 15, 2, 7, 9, 13, 16, 3, 10, 14, 17, 4, 11, 18, and 5. If we reverse each column, we obtain the lists 15, 12, 8, 6, 1, 16, 13, 9, 7, 2, 17, 14, 10, 3, 18, 11, 4, and 5. Let's plug those numbers back into the columns of the table while keeping the lengths of the rows the same as before:

[[15,  16,  17,  18,   5],
 [12,  13],
 [ 8,   9,  14,  11],
 [],
 [ 6,   7,  10],
 [ 1,   2,   3,   4]]

Your task is to implement this operation.

Input and output

Your input is a list of lists of nonnegative integers, representing the rows. The rows may have different lengths, and some of them may be empty. There will always be at least one row. Your output is the result of reversing each column, as detailed above. Input and output may be in any reasonable format.

The lowest byte count in each language wins. Standard rules apply.

Test cases

[[]] -> [[]]
[[],[]] -> [[],[]]
[[8,5,1]] -> [[8,5,1]]
[[1,200],[0,3]] -> [[0,3],[1,200]]
[[],[3,9],[1],[]] -> [[],[1,9],[3],[]]
[[],[5,8,7],[0,6,5,7,1]] -> [[],[0,6,5],[5,8,7,7,1]]
[[1,8,5],[7,5,4],[],[1]] -> [[1,5,4],[7,8,5],[],[1]]
[[],[],[2],[],[31],[],[5],[],[],[],[7]] -> [[],[],[7],[],[5],[],[31],[],[],[],[2]]
[[1,10,100,1000],[2,20,200],[3,30],[4],[5,50,500],[6,60],[7]] -> [[7,60,500,1000],[6,50,200],[5,30],[4],[3,20,100],[2,10],[1]]
[[8,4],[3,0,4,8,1],[8],[0,8],[9,7,1,6],[3,8,1,9,5]] -> [[3,8],[9,7,1,9,5],[0],[8,8],[3,0,1,6],[8,4,4,8,1]]
[[3,9,3],[5],[1],[3,5],[9,0,6,2],[1,3],[4,9,2],[6,6,7,8,7]] -> [[6,6,7],[4],[1],[9,9],[3,3,2,8],[1,0],[5,5,6],[3,9,3,2,7]]
[[8,5,6],[3,5,2,4,9],[4,3,8,3,7],[6,1,1],[1,8,9,9],[9,1,2],[8,7]] -> [[8,7,2],[9,1,9,9,7],[1,8,1,3,9],[6,1,8],[4,3,2,4],[3,5,6],[8,5]]
[[2,4],[1,4],[0,8,7,3],[4,9,2,5],[2,8,0],[0,8,3],[7,3,1],[],[3,3,7,8]] -> [[3,3],[7,3],[0,8,7,8],[2,8,1,5],[4,9,3],[0,8,0],[1,4,2],[],[2,4,7,3]]
\$\endgroup\$
3
  • 1
    \$\begingroup\$ May we pad the rows of the output with nulls? (e.g. [[1,9],[3],[2,4,5]] -> [[2,4],[3,null],[1,9,5]]) \$\endgroup\$ Jan 28, 2018 at 4:07
  • \$\begingroup\$ @ETHproductions No, the output should contain only numbers. \$\endgroup\$
    – Zgarb
    Jan 28, 2018 at 8:24
  • \$\begingroup\$ -1 because it is not general (not allow negative numbers , letters, string and all possible type as row element) + I don't like it (it seems unnecessary difficult) \$\endgroup\$
    – user58988
    Jan 30, 2018 at 11:09

9 Answers 9

5
\$\begingroup\$

Jelly, 16 bytes

ḟṚṁṣj
z-ç€-ZFḟ-ṁ

Try it online! or verify all test cases.

How it works

z-ç€-ZFḟ-ṁ  Main link. Argument: M (matrix / 2D array)

z-          Zip the rows of M, using -1 as filler.
  ç€-       Map the helper link over the result, with right argument -1.
     Z      Zip the rows of the result.
      F     Flatten the resulting matrix.
       ḟ-   Filterfalse -1; remove all occurrences of -1.
         ṁ  Mold; shape the result like M.


ḟṚṁṣj       Helper link.
            Left argument: A (row / 1D array). Right argument: -1

ḟ           Filterfalse; remove all occurrences of -1.
 Ṛ          Reverse the resulting vector.
   ṣ        Split A at occurrences of -1.
  ṁ         Mold; shape the vector to the left like the 2D array to the right.
    j       Join the resulting 2D array, separating by -1.
\$\endgroup\$
2
  • \$\begingroup\$ Nice, the on the top line is very clever! (ḟṚṁṣj does ⁸ḟ⁹Ṛṁ⁸ṣ⁹¤j⁹ right?) otherwise I had this for one more byte \$\endgroup\$ Jan 27, 2018 at 16:11
  • \$\begingroup\$ Yes, that's exactly what it does. \$\endgroup\$
    – Dennis
    Jan 27, 2018 at 16:25
5
\$\begingroup\$

APL (Dyalog Unicode), 20 19 16 bytesSBCS

-4 thanks to ngn.

Full program. Prompts for input from STDIN.

⍟0~¨⍨↓⍉⌽@×⍤1⍉↑*⎕

Try it online!

Explanation with example walk-through

 prompt for evaluated input
[[1,8,5],[7,5,4],[],[1]]

* raise e to the power of that (en which ensures that there will be no zeros)
[[2.7,2981,148.4],[1096.6,148.4,54.6],[],[2.7]]

 mix the lists into a single matrix, padding with zeros:
┌ ┐
│2.7E0 3.0E3 1.5E2│
│1.1E3 1.5E2 5.5E1│
│0.0E0 0.0E0 0.0E0│
│2.7E0 0.0E0 0.0E0│
└ ┘

 transpose
┌ ┐
│2.7E0 1.1E3 0.0E0 2.7E0│
│3.0E3 1.5E2 0.0E0 0.0E0│
│1.5E2 5.5E1 0.0E0 0.0E0│
└ ┘

⌽@×⍤1 reverse the positive elements of each row
┌ ┐
│2.7E0 1.1E3 0.0E0 2.7E0│
│1.5E2 3.0E3 0.0E0 0.0E0│
│5.5E1 1.5E2 0.0E0 0.0E0│
└ ┘

 transpose
┌ ┐
│2.7E0 1.5E2 5.5E1│
│1.1E3 3.0E3 1.5E2│
│0.0E0 0.0E0 0.0E0│
│2.7E0 0.0E0 0.0E0│
└ ┘

 split the matrix into a list of lists
[[2.7,148.4,54.6],[1096.6,2981,148.4],[0,0,0],[2.7,0,0]]

0~¨⍨ remove zeros from each list
[[2.7,148.4,54.6],[1096.6,2981,148.4],[],[2.7]]

 natural logarithm
[[1,5,4],[7,8,5],[],[1]]

\$\endgroup\$
11
  • \$\begingroup\$ What if the input contains -1? \$\endgroup\$
    – ngn
    Jan 28, 2018 at 9:44
  • \$\begingroup\$ @ngn Input will never contain negative numbers; see section "Input and output". \$\endgroup\$
    – Zgarb
    Jan 28, 2018 at 11:28
  • \$\begingroup\$ @Zgarb That's perfect, thanks. \$\endgroup\$
    – ngn
    Jan 28, 2018 at 13:42
  • \$\begingroup\$ @Adám I edited to use rank 1 instead of mix-each-split. \$\endgroup\$
    – ngn
    Jan 28, 2018 at 13:43
  • \$\begingroup\$ @Adám also: exp/log instead of +1/-1 covers the tests with ⎕fr←1287 \$\endgroup\$
    – ngn
    Jan 28, 2018 at 14:00
4
\$\begingroup\$

Japt, 15 13 bytes

saved 2 bytes thanks to @Shaggy

y@=XfÊX£o
®fÄ

Test it online!

The second line can be removed if we are allowed to pad the rows with null values, saving 4 bytes.

Explanation

 y@  =XfÊ X£  o      Implicit: U = input array
UyX{U=Xfl Xm{Uo}}    (Ungolfed)
UyX{            }    Map each column X in the input by this function:
    U=Xfl              Set U to X filtered to only items whose factorial is truthy;
                       this just gets rid of the empty slots in the column.
          Xm{  }       Map each item in X to
             Uo          the last item in U, popping this item from the list.
                       Due to the way .map works in JS, this is only called on real items
                       and not empty slots, so this preserves empty slots.
                     Newline: set U to the resulting column-reversed array
 ®   fÄ              Due to the way y works, there will now be `undefined` in some rows.
UmZ{Zf+1}            (Ungolfed)
 mZ{    }            Map each row Z in U to
    Zf+1               Z filtered to only items where the item + 1 is truthy.
                     undefined + 1 is NaN, which is falsy, and thus eliminated.
                     Implicit: output result of last expression
\$\endgroup\$
4
  • \$\begingroup\$ Nice one! You can get it down to 13 bytes by replacing l; with Ê and mf_Ä with ®fÄ. \$\endgroup\$
    – Shaggy
    Jan 28, 2018 at 9:45
  • \$\begingroup\$ Actually, just mf seems to work for the second line. \$\endgroup\$
    – Shaggy
    Jan 28, 2018 at 10:32
  • \$\begingroup\$ @Shaggy Thanks, hadn't thought of those! mf would get rid of any zeroes in the result though, unfortunately... \$\endgroup\$ Jan 28, 2018 at 13:01
  • \$\begingroup\$ Ah, yes, wasn't thinking of that. \$\endgroup\$
    – Shaggy
    Jan 28, 2018 at 13:02
3
\$\begingroup\$

K4, 36 bytes

Solution:

+{x[w]:|x w:&~^x;x}'x'[::;]@!|/#:'x:

Examples:

q)k)+{x[w]:|x w:&~^x;x}'x'[::;]@!|/#:'x:(1 2 3 4 5;6 7;8 9 10 11;0#0N;12 13 14;15 16 17 18)
15 16 17 18 5
12 13        
8  9  14 11  

6  7  10     
1  2  3  4

q)k)+{x[w]:|x w:&~^x;x}'x'[::;]@!|/#:'x:(0#0N;5 8 7; 0 6 5 7 1)

0 6 5    
5 8 7 7 1

Explanation:

This one has been a pain, and I'm still working to simplify the elided indexing.

Instead of indexing in at, for example, x[0] which would return the first row, we want to take the first column, which can be done using x[;0].

However passing variable y into x[;] treats it as doing x[y] not x[;y] hence shoving the :: in there: x[::;].

This is equivalent to flipping the list of lists, but flip requires all lists to be equal length!

+{x[w]:|x w:&~^x;x}'x'[::;]@!|/#:'x: / the solution
                                  x: / save input as variable x
                               #:'   / count (#:) each (') 
                             |/      / take the max of these lengths
                            !        / til, range 0..max-1
                           @         / apply (index into)
                      [::;]          / :: is a kind of null, 
                    x'               / index into x at each of these    
 {              ; }'                 / two statement lambda on each (')
              ^x                     / null x (returns true if entry is null)
             ~                       / not, so flip true/false
            &                        / where, indexes where true
          w:                         / save as variable w  
        x                            / index into w at these indexes
       |                             / reverse
  x[w]:                              / store this back in variable x at indexes w
                 x                   / return x from function
+                                    / flip the result
\$\endgroup\$
3
\$\begingroup\$

Haskell, 174 bytes

f x=map g.h.map(g.reverse>>=(!)).h$take(maximum$length<$>x).(++z).map pure<$>x
g=concat
h x|g x==[]=x|4>2=foldr(zipWith(:))z x
x!(c:d)|c==[]=c:x!d|a:b<-x=[a]:b!d
_!y=y
z=[]:z

Try it online!

Ungolfed/Explanation

The idea is to wrap all elements in [] and pad the rows with [] (turned out to be shorter than padding with a negative integer, this allows negative inputs as well which is nice), then transpose, reverse all rows and transpose again and flatten each row:

map concat                                   -- flatten each row
  . transpose'                               -- transpose (*)
  . map (\row-> reverse (concat row) ! row)  -- reverse each row (see below)
  . transpose'                               -- tranpose (*)
  $ take (maximum $ length <$> x)            -- only keep up as many as longest row
      . (++ z)                               -- pad row with [],[],..
      . map (\e-> [e])                       -- wrap elements in []
 <$> x

* This transpose function (h) simply returns the list if there are no elements at all.

The reverse function has to ignore [] elements (eg. [[],[1],[],[3],[4]] -> [[],[4],[],[3],[1]]), it does so by receiving two arguments: The first one are the elements in reverse order (eg. [4,3,1]) and the second one the original row.

x@(a:b) ! (c:d)
 | c == []   = c:x ! d    -- if current element is []: skip it
 | otherwise = [a]:b ! d  -- else: replace with new one (a) and continue
_ ! y = y                 -- base case (if no new elements are left): done
\$\endgroup\$
2
\$\begingroup\$

Python 2, 111 105 92 bytes

def f(l):x=map(lambda*n:[v for v in n if-1<v],*l);return[map(list.pop,x[:len(k)])for k in l]

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ You could use print instead of return to save a byte. \$\endgroup\$ Jan 28, 2018 at 17:27
2
\$\begingroup\$

JavaScript (ES6), 79 76 bytes

(a,d=[],g=s=>a.map(b=>b.map((c,i)=>(d[i]=d[i]||[])[s](c))))=>g`push`&&g`pop`

Edit: Saved 3 bytes thanks to @ETHproductions.

\$\endgroup\$
1
  • \$\begingroup\$ @ETHproductions Right; I've no idea why I thought it wouldn't, otherwise I would have done that already. \$\endgroup\$
    – Neil
    Jan 28, 2018 at 10:44
1
\$\begingroup\$

APL (Dyalog Unicode), 27 bytesSBCS

≢¨⍴¨∘↓∘⍉⍉∘↑{⍵\⌽⍵/⍺}⍤1∘⍉∘↑=⍨

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ I think you overthought this one. \$\endgroup\$
    – Adám
    Jan 28, 2018 at 9:23
  • \$\begingroup\$ I knew I could use @ but I don't have it. \$\endgroup\$
    – ngn
    Jan 28, 2018 at 9:38
0
\$\begingroup\$

Clojure, 123 bytes

#(map(fn[i R](map(fn[j _](let[V(for[Q %](get Q j))F filter](nth(reverse(F + V))(count(F +(take i V))))))(range)R))(range)%)

I was expecting (+ nil) to throw an exception, but it evaluates to nil :o

This operates without padding, instead it counts how many of the previous rows are at least as long as the current row R.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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