Zickzack-Matrix

43

Als Teil seines Komprimierungsalgorithmus entrollt der JPEG-Standard eine Matrix in einen Vektor entlang von Antidiagonalen mit wechselnder Richtung:

Bildbeschreibung hier eingeben

Ihre Aufgabe ist es, eine Matrix (nicht unbedingt ein Quadrat) zu nehmen und sie in abgewickelter Form zurückzugeben. Als Beispiel:

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

sollte nachgeben

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

Regeln

Sie können davon ausgehen, dass die Matrixelemente positive ganze Zahlen kleiner als sind 10.

Sie können ein Programm oder eine Funktion schreiben, indem Sie eine Eingabe über STDIN (oder die nächstgelegene Alternative), ein Befehlszeilenargument oder ein Funktionsargument vornehmen und das Ergebnis über STDOUT (oder die nächstgelegene Alternative), einen Funktionsrückgabewert oder einen Funktionsparameter (out) ausgeben.

Die Eingabematrix kann in jedem geeigneten, eindeutigen, verschachtelten Listen- oder Zeichenfolgenformat oder als flache Liste zusammen mit beiden Matrixdimensionen angegeben werden. (Oder natürlich als Matrixtyp, wenn Ihre Sprache diese hat.)

Der Ausgabevektor kann in jedem geeigneten, eindeutigen, flachen Listen- oder Zeichenkettenformat vorliegen.

Es gelten die Standardregeln für .

Testfälle

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

Verwandte Herausforderungen

Martin Ender
quelle
1
Kann die Eingabe eine tatsächliche Matrix in J sein? Oder müsste es als Teil der Funktion von verschachtelten Listen in eine Matrix umgewandelt werden?
Gareth
4
Wenn wir die Matrix als 2D-Array verwenden, können wir die Dimensionen trotzdem als Eingaben verwenden?
Xnor
1
@Gareth Ja, Sie können einen Matrixtyp als Eingabe verwenden.
Martin Ender
1
@xnor Hmmm, das ist etwas kniffliger. Ich habe das Gefühl, dass diese Menge an redundanten Informationen ein wenig in die Vorverarbeitung der Eingabe fließt.
Martin Ender
Kann die flache Liste in der Hauptreihenfolge der Spalten sein, wenn dies die native Reihenfolge der Sprache ist?
Luis Mendo

Antworten:

27

J, 31 30 14 12 11 Bytes

[:;<@|.`</.

Ych . Zu groß.

Nimmt eine Matrix als Eingabe.

Erläuterung

J hat hier einen Vorteil. Es gibt einen Befehl namens oblique ( /.), der die schrägen Linien der Reihe nach verwendet und ein Verb auf sie anwendet. In diesem Fall verwende ich ein Gerundium, um zwei Verben abwechselnd anzuwenden: <( box ) und <@|.( reverse und box). Dann geht es nur noch darum, alles mit ;( raze ) auszupacken .

Gareth
quelle
26
J ist die einzige Sprache, in der ich das Gefühl habe, dass ich einen fortgeschrittenen Abschluss in Englisch brauche, um sie zu verstehen.
Alex A.
2
@AlexA. Übrigens sollte das Wort "Befehl" "Adverb" gewesen sein.
Adám
11

Pyth, 24 23 21 20 19 18 17 Bytes

ssm_W=!Td.T+LaYkQ

Alternative 17-Byte-Version: 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)

Vielen Dank an @FryAmTheEggman für ein Byte, @Jakube für 2 Byte und @isaacg für ein Byte!

Erklärung der "schwarzen Magie", auf die oben m_W=!Tdangespielt wurde : Kehrt im Wesentlichen jedes andere Subarray um. Dies geschieht durch _W=!TZuordnen über jedes Subarray. Wist eine bedingte Anwendung, _dh es werden alle Subarrays umgekehrt, bei denen dies =!Tzutrifft. Tist eine Variable vorinitialisiert auf zehn (wahr) und =!Tbedeutet (T = !T). Damit wird der Wert einer Variablen umgeschaltet, die mit der Wahrheit beginnt und den neuen Wert zurückgibt. Dies bedeutet, dass zwischen der Rückkehr von Falschem, Wahrem, Falschem, Wahrem ... gewechselt wird (Dank an Jakube für diese Idee).

Testsuite hier .

Türknauf
quelle
11

Jelly, 24 19 15 13 11 Bytes

pS€żị"¥pỤị⁵

Nimmt die Anzahl der Zeilen, die Anzahl der Spalten und eine flache Liste als separate Befehlszeilenargumente.

Probieren Sie es online!

Wie es funktioniert

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.
Dennis
quelle
Tsk. Ich bin mir nicht sicher, ob ich meine jetzt kürzer machen kann. : -S
Gareth
Das heißt aber nicht, dass ich es nicht versuchen werde ...
Gareth
Warum hat Jelly Oblique noch nicht geerbt? Darf ich die APL-Glyphen und vorschlagen ? Oder vielleicht skandinavisch øund ǿ?
Adám
7

MATL , 28 27 Bytes

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

Angepasst von meiner Antwort hier . Die allgemeine Idee ist, ein 2D-Array mit der gleichen Größe wie die Eingabe zu erstellen, das mit Werten gefüllt ist, die in der gleichen Reihenfolge wie der Zick-Zack-Pfad zunehmen. Dann wird die linearisierte (abgeflachte) Version dieses Arrays sortiert, und die Indizes dieser Sortierung werden beibehalten. Dies sind die Indizes, die auf den Eingang angewendet werden müssen, um den Zick-Zack-Pfad zu erzeugen.

Die Eingabe erfolgt im Formular

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

Erläuterung

Probieren Sie es 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
Luis Mendo
quelle
4

Matlab, 134 Bytes

Ich habe gerade mein Bestes versucht, um meinen Code in Matlab zu verkürzen, als würde ich ihn telegraphieren.

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)';

Anmerkungen:

  1. Mist eine m×nMatrix.
  2. aund bsind beide Matrizen gleich groß M, so besteht jede Zeile aaus Zahlen, die ihrer Zeilennummer entsprechen, während jede Spalte von bihrer Spaltennummer entspricht. Somit ist a+ beine Matrix, deren Element gleich der Summe ihrer Zeilen- und Spaltennummer ist, dh matrix(p,q)=p+q.
  3. Also A(p,q)=p+q-1; und B(p,q)=p-q.
  4. Cwird mathematisch als folgende Gleichung angegeben. Zickzackförmig ansteigende Matrix Mit der Gleichung kann eine zickzackförmig ansteigende Matrix wie nachstehend gezeigt hergestellt werden.
C =
     1     2     6     7
     3     5     8    14
     4     9    13    18
    10    12    19    25
  1. Cgibt die Reihenfolge der Elemente von M in zickzackförmigen Ergebnissen an. Dann wird [~,I]=sort(C(:));die Bestellung zurückgegeben, das heißt I, also V=V(I)'das Ergebnis.
Guoyang Qin
quelle
Ja, ich habe es gerade gefunden, jetzt aktualisiere ich es.
Guoyang Qin
@AlexA. Vielen Dank, Alex. Denn ich bin neu darin und ich möchte es so kurz wie möglich machen, aber es zu einem Schnipsel machen. Jetzt habe ich meinen Code noch repariert.
Guoyang Qin
Sieht gut aus. Schöner erster Beitrag! :)
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]

Getestet in Firefox 44. Nimmt Eingaben als 2D-Array auf.

ETHproductions
quelle
3

Python 2, 84 Bytes

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]

Portierung der Antwort von Nimi . Nimmt ein flaches Array mit gegebener Breite und Höhe auf. xsot hat ein Byte gespeichert.


88 Bytes:

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

Nimmt ein flaches Array mit gegebener Breite und Höhe auf. Sortiert die entsprechenden 2D-Koordinaten (i/w,i%w)in Zick-Zack-Reihenfolge nach zunehmender Summe, um Diagonalen zu erhalten, die entweder durch Erhöhen oder Verringern des Zeilenwerts unterbrochen werden, je nachdem, ob die Zeile plus Spalte ungerade oder gerade ist.

xnor
quelle
Die if-Bedingung kann weiter verkürzt werden.
Xsot
@xsot Schöner Fang.
16.
3

Haskell, 79 78 73 Bytes

(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

Die Eingabe ist eine flache Liste mit der Anzahl der Zeilen und Spalten, zB ( [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].

So funktioniert es: Gehen Sie in zwei verschachtelten Schleifen durch die x- und y-Koordinaten der Matrix ( hZeilen, wSpalten):

  | 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

dh von oben / rechts nach unten / links, Überspringen von gebundenen Indizes ( yund xmuss erfüllen y<hund x-y<w). Wenn gerade xist, wird die Reihenfolge der inneren Schleife umgekehrt: ygeht von xnach 0. Dazu wähle ich eine Änderungsfunktion für den y-Bereich, [0..x]der das xdritte Element von ist [reverse,id,reverse,id,...].

Edit: @xnor hat die Schleifen neu angeordnet und 5 Bytes gespeichert. Vielen Dank!

nimi
quelle
Ich denke, du kannst es tun g=id:reverse:g.
16.
Die Pars auf der multication (y-x)*wkann durch Umsetzung des Problems geschnitten werden: (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. Das Übersetzen in Python spart 3 Zeichen mehr als das, was ich hatte.
16.
1

Python 2 + NumPy, 122 Bytes

Ich gebe es zu. Ich habe weitergearbeitet. Leider kann dieselbe Methode nicht einfach geändert werden, um die anderen 2 damit verbundenen Herausforderungen zu lösen ...

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

Nimmt ein Numpy-Array als Eingabe. Gibt eine Liste aus.

Probieren Sie es online aus

Erläuterung:

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

Ein Lambda hat die gleiche Länge:

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]))],[])
mbomb007
quelle
1

Python 3, 131 118 115 107 Bytes

Basierend auf dem gleichen Prinzip wie meine Antwort auf Deusovis Herausforderung

Ich gehe davon aus, dass wir in der Eingabematrix keine Null haben können

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]

Erläuterung

wie es funktioniert :

            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

Ergebnisse

>>> [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]]
Erwan
quelle
Sollte reverse even linees reverse odd linesstattdessen sein?
NWP
@nwp Index beginnt um 0 ^^
Erwan
Ah, Sie sprechen von den Zeilennummern, nicht von der Länge der Zeile. Ich habe die verwechselt, sorry.
nwp
@nwp np, übrigens habe ich es geändert, um Verwirrung zu vermeiden
Erwan