Zigzagifier une matrice


43

Dans le cadre de son algorithme de compression, le standard JPEG déroule une matrice en un vecteur le long d'antidiagonales de sens alternant:

entrez la description de l'image ici

Votre tâche consiste à prendre une matrice (pas nécessairement carrée) et à la renvoyer sous forme déroulée. Par exemple:

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

devrait céder

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

Règles

Vous pouvez supposer que les éléments de la matrice sont des entiers positifs inférieurs à 10.

Vous pouvez écrire un programme ou une fonction en prenant l’entrée via STDIN (ou l’alternative la plus proche), un argument de ligne de commande ou une argumentation de fonction et en générant le résultat via STDOUT (ou l’alternative la plus proche), une valeur de retour de fonction ou un paramètre de fonction (out).

La matrice d'entrée peut être donnée dans une liste ou un format de chaîne approprié, non ambigu, sans équivoque, ou sous forme de liste simple avec les deux dimensions de la matrice. (Ou bien sûr, en tant que type de matrice si votre langue en possède.)

Le vecteur de sortie peut être dans n'importe quel format commode, non ambigu, de liste à plat ou de chaîne.

Les règles standard de s'appliquent.

Cas de 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]

Défis associés


1
L'entrée peut-elle être une matrice réelle en J? Ou faudrait-il transformer les listes imbriquées en une matrice faisant partie de la fonction?
Gareth

4
Si nous prenons la matrice comme un tableau 2D, pouvons-nous quand même prendre les dimensions comme entrées?
xnor

1
@Gareth oui, vous pouvez utiliser un type de matrice.
Martin Ender

1
@xnor Hmmm, c'est un peu plus compliqué. J'ai l'impression que prendre cette quantité d'informations redondantes va un peu dans le prétraitement de l'entrée.
Martin Ender

La liste plate peut -elle être en ordre de colonne majeur si c'est l'ordre natif de la langue?
Luis Mendo

Réponses:


27

J, 31 30 14 12 11 octets

[:;<@|.`</.

Ych . Trop grand.

Prend une matrice en entrée.

Explication

J a un avantage ici. Il existe une commande appelée oblique ( /.) qui prend les lignes obliques à leur tour et leur applique un verbe. Dans ce cas, j'utilise un gérondif pour appliquer deux verbes en alternance: <( boîte ) et <@|.( inverse et boîte). Ensuite, il suffit de déballer tout avec ;( raze ).


26
J est la seule langue qui me donne l'impression d'avoir besoin d'un diplôme d'études supérieures en anglais pour le comprendre.
Alex A.

2
@Alexa. Au fait, le mot "commande" aurait dû être "adverbe".
Adám

11

Pyth, 24 23 21 20 19 18 17 octets

ssm_W=!Td.T+LaYkQ

Version alternative de 17 octets: 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)

Merci à @FryAmTheEggman pour un octet, @Jakube pour 2 octets et @isaacg pour un octet!

Explication de la "magie noire" mentionnée ci-dessus: m_W=!Tdrenverse essentiellement tous les autres sous-réseaux. Pour ce faire, il mappe _W=!Tchaque sous-tableau. West une application conditionnelle, donc c’est _(inverse) tous les sous-tableaux où =!Test vrai. Test une variable pré-initialisée à dix (vérité) et un =!Tmoyen (T = !T). Donc, elle bascule la valeur d'une variable qui commence la vérité et retourne la nouvelle valeur, ce qui signifie qu'elle alternera entre la fausseté, la vérité, la fausseté, la vérité ... (à Jakube pour cette idée)

Suite de test ici .


11

Jelly, 24 19 15 13 11 octets

pS€żị"¥pỤị⁵

Prend le nombre de lignes, le nombre de colonnes et une liste simple en tant qu'arguments de ligne de commande distincts.

Essayez-le en ligne!

Comment ça marche

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. Je ne suis pas sûr de pouvoir raccourcir le mien maintenant. : -S
Gareth

Cela ne veut pas dire que je n'essaierai pas cependant ...
Gareth

Pourquoi Jelly n'a-t-elle pas encore hérité d'Oblique? Puis-je suggérer les glyphes APL et ? Ou peut-être scandinave øet ǿ?
Adám

7

MATL , 28 27 octets

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

Adapté de ma réponse ici . L'idée générale est de créer un tableau 2D de la même taille que l'entrée, rempli de valeurs qui augmentent dans le même ordre que le chemin en zig-zag. Ensuite, la version linéarisée (aplatie) de ce tableau est triée et les indices de ce tri sont conservés. Ce sont les indices qui doivent être appliqués à l'entrée pour produire le chemin en zig-zag.

L'entrée est sous la forme

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

Explication

Essayez-le en ligne!

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 octets

J'ai juste essayé de mon mieux pour raccourcir mon code dans Matlab, comme pour le télégraphier.

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

Remarques:

  1. Mest une m×nmatrice.
  2. aet bles deux matrices ont la même taille M, chaque ligne de se acompose de nombres égaux à son numéro de ligne, tandis que chaque colonne de best égale à son numéro de colonne. Ainsi, a+ best une matrice dont l'élément est égal à la somme de ses numéros de ligne et de colonne, c'est-à-dire matrix(p,q)=p+q.
  3. Ainsi, A(p,q)=p+q-1; et B(p,q)=p-q.
  4. Cest mathématiquement exprimé comme l'équation ci-dessous. Matrice croissante de façon zigzagique avec l'équation, une matrice croissant de manière zigzagique peut être réalisée comme indiqué ci-dessous.
C =
     1     2     6     7
     3     5     8    14
     4     9    13    18
    10    12    19    25
  1. Cindique l'ordre des éléments de M dans les résultats zigzagifiés. Ensuite, [~,I]=sort(C(:));retourne la commande, c’est-à-dire que I, ainsi, V=V(I)'est le résultat.

Oui, je viens de le trouver, maintenant je le mets à jour.
Guoyang Qin

@Alexa. Merci Alex. Car je suis nouveau dans ce domaine et je veux le raccourcir le plus court possible, mais en faire un extrait. Maintenant, j'ai encore corrigé mon code.
Guoyang Qin

Cela semble bon. Nice premier post! :)
Alex A.

3

JavaScript (SpiderMonkey 30+), 99 octets

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]

Testé dans Firefox 44. Prend l'entrée sous forme de tableau 2D.


3

Python 2, 84 octets

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]

Portage La réponse de Nimi . Prend un tableau plat avec une largeur et une hauteur données. xsot a sauvegardé un octet.


88 octets:

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

Prend un tableau plat avec une largeur et une hauteur données. Trie les coordonnées 2D correspondantes (i/w,i%w)par ordre croissant en zigzag de la somme pour obtenir des diagonales, liées par une valeur de ligne croissante ou décroissante, en fonction du caractère pair ou impair de la ligne plus colonne.


Que si la condition peut être encore raccourcie.
Xsot

@xsot Belle prise.
Xnor

3

Haskell, 79 78 73 octets

(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'entrée est une liste simple avec le nombre de lignes et de colonnes, par exemple ( [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].

Comment ça marche: parcourez les coordonnées x et y de la matrice ( hlignes, wcolonnes) dans deux boucles imbriquées:

  | 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

c'est-à-dire de haut / droite à bas / gauche, sautant des index hors limites ( yet xdoivent satisfaire y<het x-y<w). Quand xest pair, l'ordre de la boucle interne est inversé: yva de xà 0. Je le fais en choisissant une fonction de modification pour la plage y, [0..x]qui est le xthème de [reverse,id,reverse,id,...].

Edit: @xnor a réorganisé les boucles et enregistré 5 octets. Merci!


Je pense que tu peux faire g=id:reverse:g.
xnor

Les parens du multication (y-x)*wpeuvent être coupées en transposant le problème: (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. Traduire en Python enregistre 3 caractères par rapport à ce que j'avais.
Xnor

1

Python 2 + NumPy, 122 octets

Je l'admets. J'ai travaillé devant. Malheureusement, cette même méthode ne peut pas être facilement modifiée pour résoudre les 2 autres problèmes liés ...

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

Prend un tableau numpy en entrée. Affiche une liste.

Essayez-le en ligne

Explication:

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

Un lambda a la même longueur:

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 octets

Basé sur le même principe que ma réponse au défi de Deusovi

Je suppose que nous ne pouvons pas avoir zéro dans la matrice d'entrée

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]

Explication

comment ça marche :

            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

Résultats

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

Devrait reverse even lineêtre à la reverse odd linesplace?
nwp

@nwp index commence à 0 ^^
Erwan

Ah, vous parlez des numéros de ligne, pas de la longueur de la ligne. Je les ai confus, désolé.
nwp

@nwp np, btw je l'ai changé pour éviter toute confusion
Erwan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.