Zigzagify a Matrix


43

Come parte del suo algoritmo di compressione, lo standard JPEG srotola una matrice in un vettore lungo antidiagonali di direzione alternata:

inserisci qui la descrizione dell'immagine

Il tuo compito è prendere una matrice (non necessariamente quadrata) e restituirla in forma non srotolata. Come esempio:

[1 2 3 4
 5 6 7 8
 9 1 2 3]

dovrebbe cedere

[1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]

Regole

Si può presumere che gli elementi della matrice siano numeri interi positivi inferiori a 10.

È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e producendo il risultato tramite STDOUT (o l'alternativa più vicina), il valore di ritorno della funzione o il parametro della funzione (out).

La matrice di input può essere fornita in qualsiasi elenco o formato stringa nidificato conveniente, inequivocabile, o come un elenco piatto con entrambe le dimensioni della matrice. (O, ovviamente, come tipo di matrice se la tua lingua ne ha.)

Il vettore di output può essere in qualsiasi elenco o formato stringa conveniente, non ambiguo.

Si applicano le regole standard del .

Casi test

[[1]]                                               => [1]
[[1 2] [3 1]]                                       => [1 2 3 1]
[[1 2 3 1]]                                         => [1 2 3 1]
[[1 2 3] [5 6 4] [9 7 8] [1 2 3]]                   => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1 2 3 4] [5 6 7 8] [9 1 2 3]]                     => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1 2 6 3 1 2] [5 9 4 7 8 3]]                       => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1 2 5 9 6 3 4 7 1 2 8 3]]                         => [1 2 5 9 6 3 4 7 1 2 8 3]
[[1] [2] [5] [9] [6] [3] [4] [7] [1] [2] [8] [3]]   => [1 2 5 9 6 3 4 7 1 2 8 3]

Sfide correlate


1
L'ingresso può essere una matrice effettiva in J? O dovrebbe essere trasformato da elenchi nidificati in una matrice come parte della funzione?
Gareth,

4
Se prendiamo la matrice come un array 2D, possiamo ancora prendere le dimensioni come input?
xnor

1
@Gareth sì, puoi prendere un tipo di matrice come input.
Martin Ender,

1
@xnor Hmmm, è un po 'più complicato. Sento che prendere una tale quantità di informazioni ridondanti va un po 'nel preelaborare l'input.
Martin Ender,

L'elenco piatto può essere in ordine di colonna maggiore se è l'ordine nativo della lingua?
Luis Mendo,

Risposte:


27

J, 31 30 14 12 11 byte

[:;<@|.`</.

Ych . Troppo grande.

Prende una matrice come input.

Spiegazione

J ha un vantaggio qui. C'è un comando chiamato oblique ( /.) che prende a turno le linee oblique e applica un verbo ad esse. In questo caso sto usando un gerundio per applicare alternativamente due verbi: <( box ) e <@|.( reverse e box). Quindi è solo una questione di unboxing tutto usando ;( raze ).


26
J è l'unica lingua che mi fa sentire come se avessi bisogno di una laurea in inglese per capirlo.
Alex A.

2
@AlexA. tra l'altro, la parola "comando" avrebbe dovuto essere "avverbio".
Adám,

11

Pyth, 24 23 21 20 19 18 17 byte

ssm_W=!Td.T+LaYkQ

Versione alternativa a 17 byte: ssuL_G=!T.T+LaYkQ

                Q  input
           +L      prepend to each subarray...
             aYk   (Y += ''). Y is initialized to [], so this prepends [''] to
                     the first subarray, ['', ''] to the second, etc.
                   ['' 1  2  3  4
                    '' '' 5  6  7  8
                    '' '' '' 9  1  2  3]
         .T        transpose, giving us
                   ['' '' ''
                    1  '' ''
                    2  5  ''
                    3  6  9
                    4  7  1
                    8  2
                    3]
  m_W=!Td          black magic
 s                 join subarrays together
s                  join *everything* on empty string (which means ''s used for
                     padding disappear)

Grazie a @FryAmTheEggman per un byte, @Jakube per 2 byte e @isaacg per un byte!

Spiegazione della "magia nera" accennata in precedenza: m_W=!Tdsostanzialmente inverte ogni altro sottoarray. Lo fa mappando _W=!Tsu ciascun subarray; Wè un'applicazione condizionale, quindi _s (inverte) tutti i sottocampi dove =!Tè vero. Tè una variabile preinizializzata su dieci (verità) e =!Tsignifica (T = !T). Quindi attiva o disattiva il valore di una variabile che inizia con la verità e restituisce il nuovo valore, il che significa che si alternerà tra il ritorno di falsità, verità, falsità, verità ... (merito a Jakube per questa idea)

Suite di test qui .


11

Gelatina, 24 19 15 13 11 byte

pS€żị"¥pỤị⁵

Accetta il numero di righe, il numero di colonne e un elenco semplice come argomenti della riga di comando separati.

Provalo online!

Come funziona

pS€żị"¥pỤị⁵  Main link. Argument: m (rows), n (columns), A (list, flat)

p            Compute the Cartesian product [1, ..., m] × [1, ..., n]. This yields
             the indices of the matrix M, i.e., [[1, 1], [1, 2], ..., [m, n]].
 S€          Compute the sums of all index pairs.
       p     Yield the Cartesian product.
      ¥      Dyadic chain. Arguments: Sums, Cartesian product.
    ị"       For each index pair in the Cartesian product, retrieve the coordinate
             at the index of its sum, i.e., map [i, j] to i if i + j is odd and to
             j if i + j is even.
   ż         Zip the sums with the retrieved indices.
       Ụ     Sort [1, ..., mn] by the corresponding item in the resulting list.
        ị⁵   Retrieve the corresponding items from A.

Tsk. Non sono sicuro di poter ridurre il mio ora. : -S
Gareth

Questo non vuol dire che non ci proverò però ...
Gareth

Perché Jelly non ha ancora ereditato Oblique? Posso suggerire i glifi APL e ? O forse scandinavo øe ǿ?
Adám,

7

MATL , 28 27 byte

tZyZ}:w:!+-1y^7MGn/*-X:K#S)

Adattato dalla mia risposta qui . L'idea generale è quella di creare un array 2D della stessa dimensione dell'input, pieno di valori che aumentano nello stesso ordine del percorso a zig-zag. Quindi viene ordinata la versione linearizzata (appiattita) di quell'array e vengono mantenuti gli indici di tale ordinamento. Questi sono gli indici che devono essere applicati all'input per produrre il percorso a zig-zag.

L'input è nella forma

[1 2 3; 5 6 4; 9 7 8; 1 2 3]

Spiegazione

Provalo online!

t       % input 2D array. Duplicate
ZyZ}    % get size as length-2 vector. Split into two numbers: r, c
:       % range [1,2,...,c] as a row vector
w:!     % swap, range [1;2;...;r] as a column vector
+       % add with broadcast. Gives a 2D array
-1      % push -1
y^      % duplicate previous 2D array. Compute -1 raised to that
7M      % push [1;2;...;r] again
Gn/     % divide by input matrix size, that is, r*c
*       % multiply
-       % subtract
X:      % linearize 2D array into column array
K#S     % sort and push the indices of the sorting. Gives a column vector
)       % index input matrix with that column vector

4

Matlab, 134 byte

Ho appena fatto del mio meglio per abbreviare il mio codice in Matlab, come telegrafarlo.

function V=z(M)
[m,n]=size(M);
a=(1:m)'*ones(1,n);
b=ones(m,1)*(1:n);
A=a+b-1;
B=a-b;
C=(A.^2+(-1).^A.*B+1);
[~,I]=sort(C(:));
V=M(:);
V=V(I)';

Gli appunti:

  1. Mè una m×nmatrice.
  2. ae bhanno entrambe le matrici della stessa dimensione di M, ciascuna riga di è acomposta da numeri uguali al suo numero di riga, mentre ogni colonna di bè uguale al suo numero di colonna. Pertanto, a+ bè una matrice il cui elemento equivale alla somma del numero di riga e colonna, ovvero matrix(p,q)=p+q.
  3. Quindi A(p,q)=p+q-1,; e B(p,q)=p-q.
  4. Cè matematicamente indicato come equazione di seguito. Matrice a zigzagificazione crescente con l'equazione, si può realizzare una matrice a zigzagificazione crescente come mostrato di seguito.
C =
     1     2     6     7
     3     5     8    14
     4     9    13    18
    10    12    19    25
  1. Cindica l'ordine degli elementi di M nei risultati a zigzag. Quindi, [~,I]=sort(C(:));restituisce l'ordine, ovvero I, quindi, V=V(I)'è il risultato.

Sì, l'ho appena trovato, ora lo aggiorno.
Guoyang Qin

@AlexA. Grazie Alex. Perché sono nuovo in questo e voglio accorciarlo il più breve possibile, ma renderlo un frammento. Ora ho ancora corretto il mio codice.
Guoyang Qin

Sembra buono. Bel primo post! :)
Alex A.

3

JavaScript (SpiderMonkey 30+), 99 byte

x=>[for(y of[...x,...x[0]].keys())for(z of Array(y+1).keys())if(a=x[y%2?z:y-z])if(b=a[y%2?y-z:z])b]

Testato in Firefox 44. Accetta input come un array 2D.


3

Python 2, 84 byte

lambda N,w,h:[N[i*w+s-i]for s in range(w+h+1)for i in range(h)[::s%2*2-1]if-1<s-i<w]

Porting della risposta di Nimi . Prende una matrice piatta con larghezza e altezza indicate. xsot ha salvato un byte.


88 byte:

lambda M,w,h:[M[i]for i in sorted(range(w*h),key=lambda i:(i/w+i%w,-i*(-1)**(i/w+i%w)))]

Prende una matrice piatta con larghezza e altezza indicate. Ordina le coordinate 2D corrispondenti (i/w,i%w)in ordine di zigzag di somma crescente per ottenere diagonali, con il punto di interruzione aumentando o diminuendo il valore della riga, a seconda che la colonna più la riga sia pari o dispari.


Che se la condizione può essere ulteriormente ridotta.
xsot

@xsot Nice catch.
xnor

3

Haskell, 79 78 73 byte

(m#h)w=[m!!(y*w+x-y)|x<-[0..h+w],y<-g!!x$[0..x],y<h,x-y<w]
g=reverse:id:g

L'input è un elenco semplice con il numero di righe e colonne, ad es. ( [1,2,6,3,1,2,5,9,4,7,8,3] # 2) 6-> [1,2,5,9,6,3,4,7,1,2,8,3].

Come funziona: cammina attraverso le coordinate xey della matrice ( hrighe, wcolonne) in due cicli nidificati:

  | 0 1 2 3 4 5 6 7 8    outer loop               Index is y*w+x-y, i.e.
--+------------------    x from 0 to h+w          the elements are accessed
0 | 1 2 6 3 1 2                                   in the following order:
1 | 5 9 4 7 8 3
2 |                                               1 2 4 6  8 10 
3 |                                               3 5 7 9 11 12
4 |
5 |
6 |
7 | inner loop:
8 | y from 0 to x

vale a dire dall'alto / destra verso il basso / sinistra, saltando fuori dagli indici associati ( ye xdeve soddisfare y<he x-y<w). Quando xè pari, l'ordine del circuito interno è invertito: ypassa da xa 0. Lo faccio selezionando una funzione di modifica per l'intervallo y [0..x]che è l' xelemento th di [reverse,id,reverse,id,...].

Modifica: @xnor ha riorganizzato i loop e salvato 5 byte. Grazie!


Penso che tu possa fare g=id:reverse:g.
xnor

Le parentesi sul multication (y-x)*wpossono essere tagliati trasponendo il problema: (m#h)w=[m!!(x*w+y-x)|y<-[0..h+w],x<-g!!y$[0..y],x<h,y-x<w] g=reverse:id:g. La traduzione in Python salva 3 caratteri rispetto a quello che avevo.
xnor

1

Python 2 + NumPy, 122 byte

Lo ammetto. Ho lavorato in anticipo. Sfortunatamente, questo stesso metodo non può essere facilmente modificato per risolvere le altre 2 sfide correlate ...

import numpy
def f(m):w=len(m);print sum([list(m[::-1,:].diagonal(i)[::(i+w+1)%2*-2+1])for i in range(-w,w+len(m[0]))],[])

Prende una matrice numpy come input. Emette un elenco.

Provalo online

Spiegazione:

def f(m):
    w=len(m)    # the height of the matrix, (at one point I thought it was the width)
    # get the anti-diagonals of the matrix. Reverse them if odd by mapping odd to -1
    d=[list(m[::-1,:].diagonal(i)[::(i+w+1)%2*-2+1])for i in range(-w,w+len(m[0]))]
            # w+len(m[0]) accounts for the width of the matrix. Works if it's too large.
    print sum(d,[]) # join the lists

Una lambda ha la stessa lunghezza:

import numpy
lambda m:sum([list(m[::-1,:].diagonal(i)[::(i+len(m)+1)%2*-2+1])for i in range(-len(m),len(m)+len(m[0]))],[])

1

Python 3, 131 118 115 107 byte

Basato sullo stesso principio della mia risposta alla sfida di Deusovi

Presumo che non possiamo avere zero nella matrice di input

e=enumerate
lambda s:[k for j,i in e(zip(*[([0]*n+i+[0]*len(s))for n,i in e(s)]))for k in i[::j%2*2-1]if k]

Spiegazione

come funziona :

            pad with 0      transpose    remove 0    reverse line           concatenate 
                                                     with even index
1 2 3       1 2 3 0 0        1 0 0        1            1                
4 5 6   --> 0 4 5 6 0    --> 2 4 0    --> 2 4     -->  2 4              -->  1 2 4 7 5 3 6 8 9
7 8 9       0 0 7 8 9        3 5 7        3 5 7        7 5 3             
                             0 6 8        6 8          6 8               
                             0 0 9        9            9

risultati

>>> [print([i,f(i)]) for i in [[[1]], [[1, 2], [3, 1]], [[1, 2, 3, 1]], [[1, 2, 3], [5, 6, 4], [9, 7, 8], [1, 2, 3]], [[1, 2, 3, 4], [5, 6, 7, 8], [9, 1, 2, 3]], [[1, 2, 6, 3, 1, 2], [5, 9, 4, 7, 8, 3]], [[1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]], [[1], [2], [5], [9], [6], [3], [4], [7], [1], [2], [8], [3]]]]
# [input,                                                          output]
[[[1]],                                                            [1]]
[[[1, 2], [3, 1]],                                                 [1, 2, 3, 1]]
[[[1, 2, 3, 1]],                                                   [1, 2, 3, 1]]
[[[1, 2, 3], [5, 6, 4], [9, 7, 8], [1, 2, 3]],                     [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1, 2, 3, 4], [5, 6, 7, 8], [9, 1, 2, 3]],                       [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1, 2, 6, 3, 1, 2], [5, 9, 4, 7, 8, 3]],                         [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]],                           [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]
[[[1], [2], [5], [9], [6], [3], [4], [7], [1], [2], [8], [3]],     [1, 2, 5, 9, 6, 3, 4, 7, 1, 2, 8, 3]]

Dovrebbe reverse even lineessere reverse odd linesinvece?
nwp,

L'indice @nwp inizia alle 0 ^^
Erwan

Ah, stai parlando dei numeri delle linee, non della lunghezza della linea. Ho confuso quelli, scusa.
nwp,

@nwp np, tra l'altro l'ho cambiato per evitare confusione
Erwan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.