Invierta las columnas mientras conserva la forma

20

Introducción

Suponga que tiene una lista de listas de enteros (o cualquier objeto realmente, pero sigamos con los enteros por simplicidad). Las listas pueden tener diferentes longitudes y algunas de ellas pueden estar vacías. Escribamos las listas en formato tabular:

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

Esta tabla tiene 5 columnas verticales, que contiene los números 1, 6, 8, 12, 15, 2, 7, 9, 13, 16, 3, 10, 14, 17, 4, 11, 18, y 5. Si invertimos cada columna, se obtienen las listas 15, 12, 8, 6, 1, 16, 13, 9, 7, 2, 17, 14, 10, 3, 18, 11, 4, y 5. Vuelva a conectar esos números en las columnas de la tabla manteniendo las longitudes de las filas igual que antes:

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

Su tarea es implementar esta operación.

Entrada y salida

Su entrada es una lista de listas de enteros no negativos, que representan las filas. Las filas pueden tener diferentes longitudes, y algunas de ellas pueden estar vacías. Siempre habrá al menos una fila. Su salida es el resultado de invertir cada columna, como se detalla anteriormente. La entrada y salida pueden estar en cualquier formato razonable.

El conteo de bytes más bajo en cada idioma gana. Se aplican reglas estándar de .

Casos de prueba

[[]] -> [[]]
[[],[]] -> [[],[]]
[[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]]
Zgarb
fuente
1
¿Podemos rellenar las filas de la salida con nulos? (p [[1,9],[3],[2,4,5]] -> [[2,4],[3,null],[1,9,5]]. ej. )
ETHproductions
@ETHproductions No, la salida debe contener solo números.
Zgarb
-1 porque no es general (no permite números negativos, letras, cadenas y todo tipo posible como elemento de fila) + No me gusta (parece innecesariamente difícil)
RosLuP

Respuestas:

5

Jalea , 16 bytes

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

Pruébalo en línea! o verificar todos los casos de prueba .

Cómo funciona

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.
Dennis
fuente
¡Agradable, la línea superior es muy inteligente! ( ḟṚṁṣj¿ ⁸ḟ⁹Ṛṁ⁸ṣ⁹¤j⁹verdad?) De lo contrario, tuve esto por un byte más
Erik the Outgolfer
Sí, eso es exactamente lo que hace.
Dennis
4

Japt , 15 13 bytes

ahorró 2 bytes gracias a @Shaggy

y@=XfÊX£o
®fÄ

¡Pruébelo en línea!

La segunda línea se puede eliminar si se nos permite rellenar las filas con valores nulos, ahorrando 4 bytes.

Explicación

 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
ETHproducciones
fuente
¡Buena esa! Puede reducirlo a 13 bytes reemplazando l;con Êy mf_Äcon ®fÄ.
Shaggy
En realidad, mfparece funcionar para la segunda línea.
Shaggy
@ Shaggy Gracias, ¡no había pensado en eso! mfsin embargo, desafortunadamente ...
ETHproductions
Ah, sí, no estaba pensando en eso.
Shaggy
4

APL (Dyalog Unicode) , 20 19 16 bytes SBCS

-4 gracias a ngn.

Programa completo Solicita la entrada de STDIN.

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

Pruébalo en línea!

Explicación con ejemplo de recorrido

 solicitud de entrada evaluada
[[1,8,5],[7,5,4],[],[1]]

* elevar e al poder de eso ( e n que asegura que no habrá ceros)
[[2.7,2981,148.4],[1096.6,148.4,54.6],[],[2.7]]

 Mezcle las listas en una única matriz, rellenando con ceros:
┌ ┐
│2.7E0 3.0E3 1.5E2│
│1.1E3 1.5E2 5.5E1│
│0.0E0 0.0E0 0.0E0│
│2.7E0 0.0E0 0.0E0│
└ ┘

 transponer
┌ ┐
│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 invertir los elementos positivos de cada fila
┌ ┐
│2.7E0 1.1E3 0.0E0 2.7E0│
│1.5E2 3.0E3 0.0E0 0.0E0│
│5.5E1 1.5E2 0.0E0 0.0E0│
└ ┘

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

 dividir la matriz en una lista de listas
[[2.7,148.4,54.6],[1096.6,2981,148.4],[0,0,0],[2.7,0,0]]

0~¨⍨ eliminar ceros de cada lista
[[2.7,148.4,54.6],[1096.6,2981,148.4],[],[2.7]]

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

Adán
fuente
¿Qué pasa si la entrada contiene -1?
ngn
@ngn La entrada nunca contendrá números negativos; ver sección "Entrada y salida".
Zgarb
@ Zgarb Eso es perfecto, gracias.
ngn
@ Adám edité para usar el rango 1 en lugar de mezclar cada división.
ngn
@ Adám también: exp / log en lugar de + 1 / -1 cubre las pruebas con ⎕fr ← 1287
ngn
3

K4 , 36 bytes

Solución:

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

Ejemplos:

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

Explicación:

Este ha sido un dolor, y todavía estoy trabajando para simplificar la indexación elidida.

En lugar de indexar en, por ejemplo, x[0]lo que devolvería la primera fila , queremos tomar la primera columna , que se puede hacer usando x[;0].

Sin embargo, pasar la variable ya x[;]trata lo trata como si x[y]no x[;y]estuviera empujando ::allí:x[::;] .

Esto es equivalente a voltear la lista de listas, ¡pero voltear requiere que todas las listas tengan la misma longitud!

+{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
callejero
fuente
3

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

Pruébalo en línea!

Ungolfed / Explicación

La idea es envolver todos los elementos en [] y rellenar las filas con [](resultó ser más corto que el relleno con un entero negativo, esto también permite entradas negativas, lo cual es bueno), luego transponer, invertir todas las filas y transponer nuevamente y aplanar cada fila :

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

* Esta función de transposición (h ) simplemente devuelve la lista si no hay elementos en absoluto.

La función inversa tiene que ignorar los []elementos (por ejemplo, [[],[1],[],[3],[4]]-> [[],[4],[],[3],[1]]), lo hace al recibir dos argumentos: el primero son los elementos en orden inverso (por ejemplo [4,3,1]) y el segundo la fila original.

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
ბიმო
fuente
2

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]

Pruébalo en línea!

ovs
fuente
Puede usar en printlugar de returnguardar un byte.
Jonathan Frech
2

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`

Editar: Guardado 3 bytes gracias a @ETHproductions.

Neil
fuente
@ETHproductions Right; No tengo idea de por qué pensé que no lo haría, de lo contrario ya lo habría hecho.
Neil
0

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)%)

Yo estaba esperando (+ nil) lanzar una excepción, pero se evalúa como nil: o

Esto funciona sin relleno, en cambio, cuenta cuántas de las filas anteriores son al menos tan largas como la fila actual R .

NikoNyrh
fuente