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 code-golf 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]]
9 Answers 9
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.
-
\$\begingroup\$ Nice, the
ṣ
on the top line is very clever! (ḟṚṁṣj
does8ḟ9Ṛṁ8ṣ9¤j9
right?) otherwise I had this for one more byte \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2018年01月27日 16:11:18 +00:00Commented Jan 27, 2018 at 16:11 -
\$\begingroup\$ Yes, that's exactly what it does. \$\endgroup\$Dennis– Dennis2018年01月27日 16:25:24 +00:00Commented Jan 27, 2018 at 16:25
APL (Dyalog Unicode), (削除) 20 (削除ここまで) (削除) 19 (削除ここまで) 16 bytes SBCS
Full program. Prompts for input from STDIN.
⍟0~ ×ばつ⍤1⍉↑*⎕
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]]
-
\$\begingroup\$ What if the input contains -1? \$\endgroup\$ngn– ngn2018年01月28日 09:44:18 +00:00Commented Jan 28, 2018 at 9:44
-
\$\begingroup\$ @ngn Input will never contain negative numbers; see section "Input and output". \$\endgroup\$Zgarb– Zgarb2018年01月28日 11:28:15 +00:00Commented Jan 28, 2018 at 11:28
-
\$\begingroup\$ @Zgarb That's perfect, thanks. \$\endgroup\$ngn– ngn2018年01月28日 13:42:40 +00:00Commented Jan 28, 2018 at 13:42
-
\$\begingroup\$ @Adám I edited to use rank 1 instead of mix-each-split. \$\endgroup\$ngn– ngn2018年01月28日 13:43:35 +00:00Commented Jan 28, 2018 at 13:43
-
\$\begingroup\$ @Adám also: exp/log instead of +1/-1 covers the tests with ⎕fr←1287 \$\endgroup\$ngn– ngn2018年01月28日 14:00:15 +00:00Commented Jan 28, 2018 at 14:00
Japt, (削除) 15 (削除ここまで) 13 bytes
saved 2 bytes thanks to @Shaggy
y@=XfÊX£o
®fÄ
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
-
-
\$\begingroup\$ Actually, just
mf
seems to work for the second line. \$\endgroup\$Shaggy– Shaggy2018年01月28日 10:32:40 +00:00Commented 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\$ETHproductions– ETHproductions2018年01月28日 13:01:25 +00:00Commented Jan 28, 2018 at 13:01 -
\$\begingroup\$ Ah, yes, wasn't thinking of that. \$\endgroup\$Shaggy– Shaggy2018年01月28日 13:02:14 +00:00Commented Jan 28, 2018 at 13:02
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
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
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
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]
-
\$\begingroup\$ You could use
print
instead ofreturn
to save a byte. \$\endgroup\$Jonathan Frech– Jonathan Frech2018年01月28日 17:27:25 +00:00Commented Jan 28, 2018 at 17:27
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.
-
\$\begingroup\$ @ETHproductions Right; I've no idea why I thought it wouldn't, otherwise I would have done that already. \$\endgroup\$Neil– Neil2018年01月28日 10:44:31 +00:00Commented Jan 28, 2018 at 10:44
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
.
[[1,9],[3],[2,4,5]] -> [[2,4],[3,null],[1,9,5]]
) \$\endgroup\$