Inverter colunas, preservando a forma


20

Introdução

Suponha que você tenha uma lista de listas de números inteiros (ou qualquer objeto realmente, mas vamos nos ater aos números inteiros por simplicidade). As listas podem ter diferentes comprimentos e algumas podem estar vazias. Vamos escrever as listas em um formato tabular:

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

Este quadro tem 5 colunas verticais, que contém os números de 1, 6, 8, 12, 15, 2, 7, 9, 13, 16, 3, 10, 14, 17, 4, 11, 18, e 5. Se invertermos cada coluna, obtemos as listas 15, 12, 8, 6, 1, 16, 13, 9, 7, 2, 17, 14, 10, 3, 18, 11, 4, e 5. Vamos conectar esses números de volta às colunas da tabela, mantendo os comprimentos das linhas iguais aos de antes:

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

Sua tarefa é implementar esta operação.

Entrada e saída

Sua entrada é uma lista de listas de números inteiros não negativos, representando as linhas. As linhas podem ter comprimentos diferentes e algumas podem estar vazias. Sempre haverá pelo menos uma linha. Sua saída é o resultado da reversão de cada coluna, conforme detalhado acima. A entrada e a saída podem estar em qualquer formato razoável.

A contagem de bytes mais baixa em cada idioma vence. Aplicam-se as regras padrão de .

Casos de teste

[[]] -> [[]]
[[],[]] -> [[],[]]
[[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]]

1
Podemos preencher as linhas da saída com valores nulos? (eg [[1,9],[3],[2,4,5]] -> [[2,4],[3,null],[1,9,5]])
ETHproductions

@ETHproductions Não, a saída deve conter apenas números.
Zgarb 28/01

-1, porque não é geral (não permitem números negativos, cartas, cordas e todos os possíveis tipo como elemento de linha) + Eu não gosto dele (parece desnecessário difícil)
RosLuP

Respostas:


5

Gelatina , 16 bytes

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

Experimente online! ou verifique todos os casos de teste .

Como 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.

Bom, a linha superior é muito inteligente! ( ḟṚṁṣjFaz ⁸ḟ⁹Ṛṁ⁸ṣ⁹¤j⁹certo?), Caso contrário eu tive este para mais um byte
Erik o Outgolfer

Sim, é exatamente isso que faz.
Dennis

4

Japonês , 15 13 bytes

economizou 2 bytes graças a @Shaggy

y@=XfÊX£o
®fÄ

Teste online!

A segunda linha pode ser removida se for permitido preencher as linhas com valores nulos, economizando 4 bytes.

Explicação

 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

Agradável! Você pode reduzi-lo a 13 bytes substituindo l;por Êe mf_Äpor ®fÄ.
Salsicha

Na verdade, apenas mfparece funcionar para a segunda linha.
Salsicha

@ Shaggy Obrigado, não tinha pensado nisso! mfiria se livrar de quaisquer zeros no resultado, infelizmente ...
ETHproductions

Ah, sim, não estava pensando nisso.
Salsicha

4

APL (Dyalog Unicode) , 20 19 16 bytes SBCS

-4 graças a ngn.

Programa completo. Solicita a entrada de STDIN.

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

Experimente online!

Explicação com o exemplo passo a passo

 prompt para entrada avaliada
[[1,8,5],[7,5,4],[],[1]]

* elevar e ao poder disso ( e n que garante que não haverá zeros)
[[2.7,2981,148.4],[1096.6,148.4,54.6],[],[2.7]]

 misture as listas em uma única matriz, preenchendo com 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│
└ ┘

 transpor
┌ ┐
│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 inverta os elementos positivos de cada linha
┌ ┐
│2.7E0 1.1E3 0.0E0 2.7E0│
│1.5E2 3.0E3 0.0E0 0.0E0│
│5.5E1 1.5E2 0.0E0 0.0E0│
└ ┘

 transpor
┌ ┐
│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 a matriz em uma lista de listas
[[2.7,148.4,54.6],[1096.6,2981,148.4],[0,0,0],[2.7,0,0]]

0~¨⍨ remova zeros 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]]


E se a entrada contiver -1?
NGN

@ngn A entrada nunca conterá números negativos; consulte a seção "Entrada e saída".
Zgarb 28/01

@ Zgarb Isso é perfeito, obrigado.
NGN

@ Adám editei para usar o rank 1 em vez de mix-each-split.
NGN

@ Adám também: exp / log em vez de + 1 / -1 cobre os testes com ⎕fr ← 1287
ngn

3

K4 , 36 bytes

Solução:

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

Exemplos:

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

Explicação:

Essa foi uma dor e ainda estou trabalhando para simplificar a indexação elidida.

Em vez de indexar em, por exemplo, x[0]que retornaria a primeira linha , queremos pegar a primeira coluna , que pode ser feita usandox[;0] .

No entanto, passar a variável ypara a x[;]trata como x[y]não fazendo com que ela não x[;y]seja empurrada ::lá:x[::;] .

Isso é equivalente a inverter a lista de listas, mas o flip exige que todas as listas tenham o mesmo comprimento!

+{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

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

Experimente online!

Ungolfed / Explicação

A idéia é envolver todos os elementos []e preencher as linhas com [](acabou por ser mais curto do que o preenchimento com um número inteiro negativo, isso também permite entradas negativas, o que é bom), em seguida, transponha, inverta todas as linhas e transponha novamente e aplique cada linha :

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 função de transposição (h ) simplesmente retorna a lista se não houver elementos.

A função reversa deve ignorar []elementos (por exemplo, [[],[1],[],[3],[4]]-> [[],[4],[],[3],[1]]), recebendo dois argumentos: o primeiro é os elementos em ordem inversa (por exemplo [4,3,1]) e o segundo a linha 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


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: salvou 3 bytes graças a @ETHproductions.


@ETHproductions Right; Eu não tenho idéia do por que pensei que não, caso contrário eu já teria feito isso.
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)%)

eu estava esperando (+ nil) lançar uma exceção, mas ela avalia nil:

Isso opera sem preenchimento, mas conta quantas linhas anteriores têm pelo menos o comprimento da linha atual R.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.