Tri des blocs de lignes et de colonnes dans un tableau 2D

15

Étant donné un tableau 2D d'entiers, trions ses lignes et colonnes en blocs. Cela signifie que vous n'avez qu'à trier une ligne ou une colonne donnée, mais en appliquant les transformations nécessaires pour le trier à toutes les autres lignes ou colonnes du tableau 2D.

Règles

  • L'entrée sera un tableau 2D d'entiers et un entier indexé 1. Cet entier représentera la ligne à trier si le nombre est positif, ou la colonne à trier si le nombre est négatif (ou l'inverse vous voulez). Exemple: étant donné un 4x3tableau (lignes x colonnes), vous pouvez trier la deuxième colonne avec un -2argument ou la troisième ligne avec un 3argument. Ce deuxième argument ne sera jamais nul et sa valeur absolue ne sera jamais supérieure à la dimension correspondante du tableau.
  • La sortie sera également un tableau 2D d'entiers avec les transformations nécessaires appliquées pour trier la ligne ou la colonne donnée. Alternativement, vous pouvez simplement écrire le tableau dans STDOUT.
  • Le tableau de sortie aura la ligne ou la colonne spécifiée triée par ordre croissant. Notez simplement que lorsque vous devez échanger deux numéros d'affilée, toutes les colonnes où se trouvent les numéros seront échangées. Et lorsque vous devez échanger deux nombres dans une colonne, les lignes entières où se trouvent les nombres seront échangées.
  • Dans le cas où le même numéro apparaît plusieurs fois dans la ligne / colonne à trier, il y aura plusieurs solutions possibles selon la façon dont vous permutez les valeurs, faites juste en conséquence avec le reste des lignes / colonnes à permuter.

Exemples

Positive indices for rows and negative indices for columns

[5  8  7  6                                  [1  3  2  4
 1  3  2  4   order by -3 (3rd column)  -->   9  6  3  0
 9  6  3  0]                                  5  8  7  6]

[5  8  7  6                                  [9  6  3  0
 1  3  2  4   order by -4 (4th column)  -->   1  3  2  4
 9  6  3  0]                                  5  8  7  6]

[5  8  7  6                                  [5  7  8  6
 1  3  2  4     order by 2 (2nd row)  -->     1  2  3  4
 9  6  3  0]                                  9  3  6  0]

[5  8  7  6                                  [6  7  8  5
 1  3  2  4     order by 3 (3rd row)  -->     4  2  3  1
 9  6  3  0]                                  0  3  6  9]

[1  2                                    [1  2     [3  2
 3  2]   order by -2 (2nd column)  -->    3  2] or  1  2]  (both are valid)

[7  5  9  7                                  [5  7  7  9     [5  7  7  9
 1  3  2  4     order by 1 (1st row)  -->     3  1  4  2  or  3  4  1  2
 9  6  3  0]                                  6  9  0  3]     6  0  9  3]

C'est le , donc le code le plus court pour chaque langue peut gagner!

Charlie
la source
Cela vient du bac à sable .
Charlie
Pouvons-nous changer la représentation entière? négatif pour les lignes et positif pour les colonnes?
Luis felipe De jesus Munoz
1
@LuisfelipeDejesusMunoz oui, cela est indiqué dans la question.
Charlie
Une ligne / colonne peut-elle contenir des numéros en double?
Kevin Cruijssen du
@KevinCruijssen oui, voir les derniers exemples et le dernier point des règles.
Charlie

Réponses:

5

Matlab, 73 62 47 octets

@(m,i){sortrows(m,-i) sortrows(m',i)'}{(i>0)+1}

Essayez-le en ligne!

-11 octets grâce à @Giuseppe.

-15 octets grâce à @LuisMendo.

DimChtz
la source
4

Japt , 18 17 octets

négatif pour les lignes et positif pour les colonnes

>0?VñgUÉ:ßUa Vy)y

Essayez-le en ligne!

Luis felipe De jesus Munoz
la source
Cela échoue quand il Uest négatif - la version précédente de 17 octets fonctionne cependant.
Shaggy
@Shaggy Mon mauvais, je pensais que ça marcherait de toute façon, je n'ai pas vérifié du tout
Luis felipe De jesus Munoz
Ce n'est pas une mauvaise idée, cependant, passer une fonction comme premier argument est ßautomatiquement appliqué U. Cela pourrait créer des problèmes en essayant de passer des chaînes littérales, mais postez une suggestion au dépôt GitHub de toute façon pour une enquête plus approfondie.
Shaggy
4

05AB1E , 25 24 14 octets

diø}Σ¹Ä<è}¹diø

Un énorme -10 octets grâce à @Emigna .

Utilise une entrée entière positive pour trier les lignes, négative pour les colonnes.

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

di }      # If the (implicit) integer input is positive:
  ø       #  Swap the rows and columns of the (implicit) matrix input
          #   i.e. 3 and [[5,8,7,6],[1,3,2,4],[9,6,3,0]]
          #    → [[5,1,9],[8,3,6],[7,2,3],[6,4,0]]
Σ    }    # Sort the rows of this matrix by:
 ¹Ä       #  Take the absolute value of the input
          #   i.e. -3 → 3
   <      #  Decreased by 1 to make it 0-indexed
          #   i.e. 3 → 2
    è     #  And index it into the current row
          #   i.e. [5,8,7,6] and 2 → 7
          #   i.e. [5,1,9] and 2 → 9
          #  i.e. [[5,1,9],[8,3,6],[7,2,3],[6,4,0]] sorted by [9,6,3,0]
          #   → [[6,4,0],[7,2,3],[8,3,6],[5,1,9]]
          #  i.e. [[5,8,7,6],[1,3,2,4],[9,6,3,0]] sorted by [7,2,3]
          #   → [[1,3,2,4],[9,6,3,0],[5,8,7,6]]
¹di       # And if the integer input was positive:
   ø      #  Swap the rows and columns back again now that we've sorted them
          #   i.e. 3 and [[6,4,0],[7,2,3],[8,3,6],[5,1,9]]
          #    → [[6,7,8,5],[4,2,3,1],[0,3,6,9]]
          # (And implicitly output the now sorted matrix)
Kevin Cruijssen
la source
1
J'ai obtenu diø}Σ¹Ä<è]¹diøce qui est un sous-ensemble du vôtre, donc je ne poste pas de réponse séparée.
Emigna
@Emigna Dang, vous rendez ça si facile .. Maintenant que je le vois, je ne peux pas croire que je n'y avais pas pensé moi-même, mais c'est ingénieux en même temps .. Merci! Un énorme 10 octets enregistrés grâce à vous.
Kevin Cruijssen du
4

JavaScript (ES6), 90 octets

t=m=>m[0].map((_,x)=>m.map(r=>r[x]))
f=(m,k)=>k<0?m.sort((a,b)=>a[~k]-b[~k]):t(f(t(m),-k))

Essayez-le en ligne!

Comment?

JS n'a pas de méthode de transposition native, nous devons donc en définir une:

t = m =>              // given a matrix m[]
  m[0].map((_, x) =>  // for each column at position x in m[]:
    m.map(r =>        //   for each row r in m[]:
      r[x]            //     map this cell to r[x]
    )                 //   end of map() over rows
  )                   // end of map() over columns

Fonction principale:

f = (m, k) =>         // given a matrix m[] and an integer k
  k < 0 ?             // if k is negative:
    m.sort((a, b) =>  //   given a pair (a, b) of matrix rows, sort them:
      a[~k] - b[~k]   //     by comparing a[-k - 1] with b[-k - 1]
    )                 //   end of sort
  :                   // else:
    t(f(t(m), -k))    //   transpose m, call f() with -k and transpose the result

k=2

M=(58sept613249630)t(M)=(519836sept23640)F(t(M),-2)=(519sept23836640)F(M,2)=t(F(t(M),-2))=(5sept8612349360)
Arnauld
la source
3

MATL , 17 octets

y0>XH?!]w|2$XSH?!

Essayez-le en ligne!

Ou vérifiez tous les cas de test

Explication

y       % Implicit inputs: number n, matrix M. Duplicate from below: pushes n, M, n
0>      % Greater than 0?
XH      % Copy into clipboard H
?       % If true
  !     %   Transpose matrix. This way, when we sort the rows it will correspond
        %   to sorting the columns of the original M
]       % End
w       % Swap: moves n to top
|       % Absolute value
2$XS    % Two-input sortrows function: sorts rows by specified column
H       % Push contents from clipboard H
?       % If true
  !     %   Transpose again, to convert rows back to columns
        % Implicit end
        % Implicit display
Luis Mendo
la source
2

Python 2 , 71 70 octets

f=lambda m,n:n<0and sorted(m,key=lambda l:l[~n])or zip(*f(zip(*m),-n))

Essayez-le en ligne!


Si nest négatif, les lignes sont triées en fonction de la colonne n.

Sinon, la matrice est transposée, triée de la même manière et à nouveau transposée.

TFeld
la source
1

C # (.NET Core) , 186 octets

(x,y)=>{Func<int[][],int[][]>shift=a=> a[0].Select((r,i)=>a.Select(c=>c[i]).ToArray()).ToArray();return y>0?shift(shift(x).OrderBy(e=>e[y-1]).ToArray()):x.OrderBy(e=>e[-y-1]).ToArray();}

Essayez-le en ligne!

Non golfé:

    private static int[][] Blocksort0a(int[][] array, int sortingInstruction)
    {
        Func<int[][], int[][]> shift = a => a[0].Select((r, i) => a.Select(c => c[i]).ToArray()).ToArray();

        sortingInstruction++;

        array = sortingInstruction < 0 ? 
        shift(shift(array).OrderBy(e => e[-sortingInstruction]).ToArray()) 
             : 
        array.OrderBy(e => e[sortingInstruction]).ToArray();

        return null;
    }

La fonction shift que nous utiliserons deux fois, donc une variable de fonction économisera de l'espace. La fonction parcourt la dimension horizontale du tableau sur l'index et ajoute chaque élément de cet index dans chaque tableau horizontal à un nouveau tableau de sortie (horizontalement) - un peu comme dans la solution JS d'Arnoud.

Maintenant, l'ordre est simple, ordonnez le tableau horizontal par numéro à l'index (argument -1), en décalant éventuellement le tableau avant et après le tri.

Vu comment la question parle spécifiquement des tableaux, nous convertissons plusieurs fois en tableau (très, très inutile). Se sentir un peu idiot d'utiliser un langage aussi verbeux dans le code golf hehe.

Barodus
la source
1

C # (.NET Core) , 142/139 138/135 octets (et encore un autre -1 par Kevin)

(a,s)=>s<0?a.OrderBy(e=>e[~s]).ToArray():a.Select(f=>a[s-1].Select((v,j)=>new{v,j}).OrderBy(e=>e.v).Select(e=>f[e.j]).ToArray()).ToArray()

Essayez-le en ligne!

Non golfé:

    private static int[][] Blocksort0b(int[][] array, int sortingInstruction)
    {
        if (sortingInstruction < 0) { return array.OrderBy(e => e[-sortingInstruction - 1]).ToArray(); }
        var rowIndices = array[sortingInstruction - 1].Select((value, index) => (value, index)).OrderBy(e => e.value);
        var newRow = new int[array[0].Length];
        for (var i = 0; i < array.Length; i++)
        {
            int horizontalIndexer = 0;
            foreach (var e in rowIndices)
            {
                newRow[horizontalIndexer++] = array[i][e.index];
            }
            array[i] = newRow.ToArray();
        }
        return array;
    }

Nouvelle approche tout en ligne; la réponse négative ordonne toujours les tableaux par élément à l'indice. Sinon, une collection de paires index-valeur est créée à partir du tableau à index et triée par valeur. Cela crée effectivement une collection d'indices dans l'ordre à ajouter. Ensuite, pour chaque réseau, les éléments dans les positions prédéterminées sont sélectionnés. Un peu de rognage de code et laid, laid, laid ** sanglote silencieusement ** la réutilisation des paramètres d'entrée est impliquée, et c'est parti ... 142 octets.

Encore une fois, l'argument tableaux est strictement appliqué, ajoutant une certaine surcharge pour les appels .ToArray ().

135 octets de réclamation, hein?! Les tuples de valeur inférés en C # 7.2 couperaient trois octets supplémentaires, mais tio.run ne le permet pas. Par conséquent, c'est la réponse que j'ai décidé de publier pour une vérification facile.

Barodus
la source
1
Bonne réponse. Il y a quelques petites choses au golf. (a,s)=>peut être un curry a=>s=>. (s<0)?n'a pas besoin de parenthèses et -s-1peut l'être ~s. Essayez-le en ligne: 137 octets
Kevin Cruijssen
Sucré! Je n'aurais jamais pu laisser la fonction retourner encore une autre fonction pour sauver un personnage, je suis agréablement surpris. Merci! Également un cas fort de négligence flagrante de l'opérateur non et des parenthèses. J'ai mis à jour le not et les parenthèses, mais je vous laisse tout l'honneur pour la fonction de retour de fonction.
Barodus du
1

Java (OpenJDK 8) , 326 octets

(a,b)->{int l=a.length,w=a[0].length,k,m,t,i;if(b>0){for(i=0;i<w;i++){for(k=1;k<(w-i);k++){if(a[b-1][k-1]>a[b-1][k]){for(m=0;m<l;m++){t=a[m][k];a[m][k]=a[m][k-1];a[m][k-1]=t;}}}}}else{b*=-1;for(i=0;i<l;i++){for(k=1;k<(l-i);k++){if(a[k-1][b-1]>a[k][b-1]){for(m=0;m<w;m++){t=a[k][m];a[k][m]=a[k-1][m];a[k-1][m]=t;}}}}}return a;}

Essayez-le en ligne!

Eh bien les gars, cette question était très frustrante pour moi, et j'ai posté ma réponse en sachant que j'oubliais quelque chose, heureusement, nous avons des légendes comme Kevin Cruijssen ici pour nous aider :)

Java (OpenJDK 8) , 281 octets

a->b->{int l=a.length,w=a[0].length,k,m,t,i;if(b>0)for(i=0;i<w;i++)for(k=0;++k<w-i;)for(m=0;a[b-1][k-1]>a[b-1][k]&m<l;a[m][k]=a[m][k-1],a[m++][k-1]=t)t=a[m][k];else for(b*=-1,i=0;i<l;i++)for(k=0;++k<l-i;)for(m=0;a[k-1][b-1]>a[k][b-1]&m<w;a[k][m]=a[k-1][m],a[k-1][m++]=t)t=a[k][m];}

Essayez-le en ligne!

X1M4L
la source
Je n'ai pas encore regardé l'algorithme réel, mais vous pouvez économiser 35 octets en supprimant tous les crochets et en mettant tout à l'intérieur des boucles (y compris l'instruction if interne). Essayez-le en ligne: 291 octets EDIT: ici avec des empreintes afin que vous puissiez voir plus clairement les changements que j'ai faits.
Kevin Cruijssen du
@KevinCruijssen Je savais que je
manquais
De plus, vous pouvez en faire une entrée curry a->b->au lieu de (a,b)->et supprimer la returndéclaration, car vous modifiez le tableau d'entrée. 281 octets Encore une belle réponse, cependant. +1 de moi. J'ai fait le défi en 05AB1E, mais je ne l'aurais même pas essayé en Java cette fois. ;)
Kevin Cruijssen
270 octets
plafondcat
1

Nettoyer , 95 octets

import StdEnv,Data.List,Data.Func
$n#f=if(n>0)transpose id
=f o sortBy(on(<)\u=u!!(abs n-1))o f

Essayez-le en ligne!

Οurous
la source
1

Kotlin , 192 octets

{m:Array<Array<Int>>,s:Int->if(s<0){m.sortBy{it[-s-1]}}else{val a=Array(m[0].size){c->Array(m.size){m[it][c]}}
a.sortBy{it[s-1]}
(0..m.size-1).map{r->(0..m[0].size-1).map{m[r][it]=a[it][r]}}}}

Essayez-le en ligne!

JohnWells
la source
1

Rubis , 69 octets

->a,n{f=->x{[0,x.transpose,x][n<=>0]};f[f[a].sort_by{|x|x[n.abs-1]}]}

Essayez-le en ligne!

GB
la source
1

Rouge , 190 185 octets

func[b n][t: func[a][c: length? a/1 a: to[]form a
d: copy[]loop c[append/only d extract a c take a]d]d: does[if n > 0[b: t b]]d
m: absolute n sort/compare b func[x y][x/(m) < y/(m)]d b]

Essayez-le en ligne!

Explication:

f: func [ b n ] [
    t: func [ a ] [                            ; helper transpose function 
        c: length? a/1                         ; c is the length of the rows
        a: to-block form a                     ; flatten the list
        d: copy []                             ; an empty block (list)
        loop c [                               ; do as many times as the number of columns  
            append/only d extract a c          ; extract each c-th element (an entire column)
                                               ; and append it as a sublist to d
            take a                             ; drop the first element
        ] 
        d                                      ; return the transposed block (list of lists)
    ]
   d: does [ if n > 0 [ b: t b ] ]             ; a helper function (parameterless) to transpose 
                                               ; the array if positive n
   d                                           ; call the function  
   m: absolute n                               ; absolute n
   sort/compare b func[ x y ] [ x/(m) < y/(m) ]; sort the array according to the chosen column 
   d                                           ; transpose if positive n
   b                                           ; return the array  
]

Ma solution actuelle fait 175 octets, mais elle ne fonctionne pas dans TIO. La voici, fonctionnant normalement dans la console rouge:

Rouge , 175 octets

func[b n][d: does[if n > 0[c: length? b/1 a: to-block form b
t: copy[]loop c[append/only t extract a c take a]b: t]]d
m: absolute n sort/compare b func[x y][x/(m) < y/(m)]d b]
Galen Ivanov
la source
0

VBA (Excel), 205 octets

Yay! 2e décompte d'octets le plus long! Je n'ai pas complètement perdu: D

Golfé:

Sub d(a)
With ActiveSheet.Sort
  .SortFields.Clear
  .SortFields.Add Key:=IIf(a<0,ActiveSheet.Columns(Abs(a)),ActiveSheet.Rows(Abs(a)))
  .SetRange ActiveSheet.UsedRange
  .Orientation=IIf(a<0,1,2)
  .Apply
End With
End Sub

Cela trie toutes les données de la feuille de calcul ouverte (active) en utilisant UsedRange ... qui peut être bogué, mais ne doit contenir que des cellules qui ont été modifiées.

Non golfé:

Sub d(a)
  'Clear any Sort preferences that already exists
  ActiveSheet.Sort.SortFields.Clear
  'Use the column if A is negative, the row if A is positive
  ActiveSheet.Sort.SortFields.Add Key:=IIf(a < 0, ActiveSheet.Columns(Abs(a)), ActiveSheet.Rows(Abs(a)))
  'Set the area to sort
  ActiveSheet.Sort.SetRange ActiveSheet.UsedRange
  'Orient sideways if sorting by row, vertical if by column
  ActiveSheet.Sort.Orientation = IIf(a < 0, xlTopToBottom, xlLeftToRight)
  'Actually sort it now
  ActiveSheet.Sort.Apply
End Sub
seadoggie01
la source
Si vous supposez que la feuille active est la feuille1, vous pouvez la réduire à 169 octetsSub d(a) With Sheet1.Sort .SortFields.Clear .SortFields.Add IIf(a<0,Columns(Abs(a)),Rows(Abs(a))) .SetRange Sheet1.UsedRange .Orientation=(a<0)+2 .Apply End With End Sub
Taylor Scott
En outre, je pense que vous pouvez supposer en toute sécurité qu'il n'y a pas de .SortFieldsdéfinition afin que vous puissiez également supprimer la .Sortfields.Clearligne.
Taylor Scott
0

Perl 6 , 43 octets

{($!=$_>0??&[Z]!!*[])o*.sort(*[.abs-1])o$!}

Essayez-le en ligne!

Fonction curry.

Explication

{                                         } # Block returning function composed of
                                       o$!  # 1. Apply $! (transpose or not)
                     o*.sort(*[.abs-1])     # 2. Sort rows by column abs(i)-1
     $_>0??&[Z]                             # 3. If i > 0 transpose matrix
               !!*[]                        #    Else identity function
 ($!=               )                       #    Store in $!
nwellnhof
la source
0

Physica , 45 octets

Très similaire à la réponse JS d' Arnauld .

F=>n;m:n<0&&Sort[->u:u{~n};m]||Zip@F#Zip@m#-n

Essayez-le en ligne!

Comment ça fonctionne?

Une explication plus élaborée et visuelle peut être trouvée dans la réponse liée.

F=>n;m:           // Create a function F that takes two arguments, n and m.
       n<0&&      // If n < 0 (i.e. is negative)
Sort[->u{~n};m]   // Sort the rows u of m by the result of the function u[~n].
                  // In short, sort by indexing from the end with n.
||    F#Zip@m#-n  // Else, apply F to Zip[m] and -n. Uses a new feature, binding.
  Zip@            // And transpose the result.
M. Xcoder
la source
0

Clojure, 91 octets

(fn f[A i](if(< i 0)(sort-by #(nth %(- -1 i))A)(apply map list(f(apply map list A)(- i)))))

Argh, apply map list* 2.

NikoNyrh
la source