Sortieren Sie eine Liste minimal in eine Matrix


18

Wenn Sie eine unsortierte Liste eindeutiger, streng positiver Ganzzahlen haben, sortieren Sie sie minimal in eine 2D-Matrix. Es wird garantiert, dass die Eingabeliste eine zusammengesetzte Länge hat, was bedeutet, dass die Ausgabematrix nicht unbedingt quadratisch ist, sondern eine Größe n x mmit hat n,m > 1.

"Minimal sortieren" bedeutet hier:

  • Sortieren Sie die Liste in aufsteigender Reihenfolge.
  • Komprimieren Sie die Ausgabematrix so weit wie möglich - minimieren Sie die Summe der Abmessungen der Matrix (z. B. ist für 20Eingabeelemente als Eingabe eine 5x4oder 4x5Ausgabematrix erforderlich und nicht eine 2x10).
  • Komprimieren Sie die sortierten Zahlen so weit wie möglich links oben in der Matrix, beginnend mit dem ersten Element in der sortierten Liste.
  • Man kann sich das so vorstellen, als würde man die Liste sortieren und dann entlang der Antidiagonalen der Matrix aufteilen, beginnend mit der oberen linken Ecke.

Beispiele:

Für die Eingabe 1..20wird entweder eine 5x4- oder eine 4x5-Matrix wie folgt ausgegeben:

 1  2  4  7 11
 3  5  8 12 15
 6  9 13 16 18
10 14 17 19 20

 1  2  4  7
 3  5  8 11
 6  9 12 15
10 13 16 18
14 17 19 20

Für den Eingangsausgang [3, 5, 12, 9, 6, 11]ist ein 2x3 oder 3x2 wie folgt

3  5  9
6 11 12

 3  5
 6  9
11 12

Für die Eingabe [14, 20, 200, 33, 12, 1, 7, 99, 58]ist die Ausgabe 3x3 wie folgt

 1   7  14
12  20  58
33  99 200

Für die Eingabe sollte 1..10der Ausgang 2x5 oder 5x2 sein, wie folgt

1 2 4 6  8
3 5 7 9 10

1  2
3  4
5  6
7  8
9 10

Für die Eingabe ist die [5, 9, 33, 65, 12, 7, 80, 42, 48, 30, 11, 57, 69, 92, 91]Ausgabe 5x3 oder 3x5 wie folgt

 5  7 11 33 57
 9 12 42 65 80
30 48 69 91 92

 5  7 11
 9 12 33
30 42 57
48 65 80
69 91 92

Regeln

  • Es kann davon ausgegangen werden, dass die Eingabe in den systemeigenen Ganzzahltyp Ihrer Sprache passt.
  • Die Eingabe und Ausgabe kann durch jede bequeme Methode erfolgen .
  • Es ist entweder ein vollständiges Programm oder eine Funktion zulässig. Bei einer Funktion können Sie die Ausgabe zurückgeben, anstatt sie zu drucken.
  • Standardlücken sind verboten.
  • Dies ist daher gelten alle üblichen Golfregeln, und der kürzeste Code (in Byte) gewinnt.

1
Oh, wow, ein Wort, das ich seit der linearen Algebra nicht mehr gesehen habe. leicht übersehen. Entschuldigen Sie.
Magic Octopus Urn

@LuisMendo Es wurde ein Elementtestfall hinzugefügt 15.
AdmBorkBork

Antworten:


10

Jelly , 24 22 20 Bytes

pS€ỤỤs
LÆDżṚ$SÞḢç/ịṢ

Probieren Sie es online!

2 Bytes dank @ Jonathan Allan gespeichert .

Erläuterung

pS€ỤỤs  Helper link. Input: integer a (LHS), integer b (RHS)
p       Cartesian product between [1, 2, ..., a] and [1, 2, ..., b]
 S€     Sum each pair
   Ụ    Grade up
    Ụ   Grade up again (Obtains the rank)
     s  Split into slices of length b

LÆDżṚ$SÞḢç/ịṢ  Main link. Input: list A
L              Length
 ÆD            Divisors
     $         Monadic pair
    Ṛ            Reverse
   ż             Interleave
                 Now contains all pairs [a, b] where a*b = len(A)
      SÞ       Sort by sum
        Ḣ      Head (Select the pair with smallest sum)
         ç/    Call helper link
            Ṣ  Sort A
           ị   Index into sorted(A)

L%J¬TżṚ$-> LÆDżṚ$sollte zwei retten, denke ich
Jonathan Allan

Der erste Link kann werden pSÞỤs.
Dennis


4

R 110 95 Bytes

function(x){n=sum(x|1)
X=matrix(x,max(which(!n%%1:n^.5)))
X[order(col(X)+row(X))]=sort(x)
t(X)}

Probieren Sie es online!

Wie es funktioniert

f <- function(x) {
  n <- sum(x|1)                           # length
  p <- max(which(!n%%1:n^.5))             # height of matrix
  X <- matrix(x, p)                       # initialize matrix
  X[order(col(X) + row(X))] <- sort(x)    # filling the matrix using position distance to the top left corner
  t(X)                                    # probably required by OP
}

Giuseppe hat mit den folgenden Tricks unglaubliche 15 (!) Bytes gespart

  • Ersetzen length(x)durch sum(x|1)(-1 Byte)
  • floor()wird :ohnehin nicht als Abrundung benötigt (-7)
  • ^.5ist kürzer als sqrt()(-3)
  • verwenden col(X) + row(X)statt outer(schön!)
  • konnte das zwar nicht loswerden t(X)- enttäuschend;)

Originelle Lösung

function(x){
n=length(x)
p=max(which(!n%%1:floor(sqrt(n))))
X=outer(1:p,1:(n/p),`+`)
X[order(X)]=sort(x)
t(X)}

Es würde ausgefallener aussehen , wenn outeres durch ersetzt row(X)+col(X)würde, aber dazu müsste Xzuerst die Ausgabematrix initialisiert werden .

Probieren Sie es online!


2
Sehr schön! Sie können bis zu 95 Bytes bekommen
Giuseppe

1
Könnte in der Lage sein, auch hier etwas aus meiner Lösung für eine verwandte Herausforderung zu verwenden.
Giuseppe

Es ist in der Tat eng miteinander verbunden. Sehr schöner Ansatz!
Michael M

3

JavaScript (ES6), 172 Byte

l=>(n=l.sort((a,b)=>b-a).length,w=l.findIndex((_,i)=>!(i*i<n|n%i)),a=l=>[...Array(l)],r=a(n/w).map(_=>a(w)),a(w+n/w).map((_,x)=>r.map((s,y)=>x-y in s&&(s[x-y]=l.pop()))),r)

Erläuterung

l=>(                                // Take a list l as input
 l.sort((a,b)=>b-a),                // Sort it
 n=l.length,                        // Get the length n
 w=l.findIndex((_,i)=>!(i*i<n|n%i)),// Find the first integer w where w >= √n and n % w = 0
 a=l=>[...Array(l)],                // Helper function a
 r=a(n/w).map(_=>a(w)),             // Create the grid r of size w, n/w
 a(w+n/w).map((_,x)=>               // For every x from 0 to w + n/w:
  r.map((s,y)=>                     //  For every row s in r:
   x-y in s&&(                      //   If the index x-y is in s:
    s[x-y]=l.pop()))),              //    Set s[x-y] to the next element of l
 r)                                 // Return r

Testfälle


3

Perl 5 , 132 Bytes

sub d{$,=0|sqrt(@_=sort{$a-$b}@_);--$,while@_%$,;map{$r++,$c--for@_/$,..$c;$a[$r++][$c--]=$_;$c=++$i,$r=0if$r<0||$c<0||$r>=$,}@_;@a}

Probieren Sie es online!

Das Unterprogramm gibt ein 2D-Array zurück. Der TIO-Link enthält einen Fußzeilencode für die Anzeige der Testergebnisse.


3

Oktave , 151 Bytes

function f(v)n=floor(sqrt(l=nnz(v)));while i=mod(l,n);++n;end;A=nan(m=l/n,n);for k=[1:m 2*m:m:l];do A(k)=sort(v)(++i);until~mod(k+=m-1,m)|k>l;end;A'end

Verwenden von drei verschiedenen Arten von Schleifenkonstrukten.

Probieren Sie es online!

Abgerollt:

function f(v)
    n = floor(sqrt(l=nnz(v)));

    while i = mod(l,n);
        ++n;
    end;

    A = nan(m=l/n, n);

    for k = [1:m 2*m:m:l];
        do
            A(k) = sort(v)(++i);
        until ~mod(k+=m-1, m) | k>l;
    end;

    A'
end

Gute Antwort! Warum ist das 'in nnz(v') erforderlich?
Luis Mendo

1
@ LuisMendo Danke! Es stellt sich heraus, dass dies 'nicht erforderlich ist, wenn ich den Bereichsausdruck z. B. an der Aufrufstelle 1:20um eckige Klammern ( [1:20]) setze (um daraus einen tatsächlichen Vektor zu machen). Offensichtlich erzeugt der Doppelpunktoperator in Octave keinen Vektor , sondern eine Bereichskonstante, die viel weniger Speicherplatz in Anspruch nimmt. Funktioniert aus irgendeinem Grund nnz()nicht mit diesem Typ, aber wenn Sie die Bereichskonstante transponieren, erhalten Sie einen Vektor. Daher funktioniert dies auch mit dem Apostroph. Durch Aufrufen der Funktion mit einem tatsächlichen Vektor entfällt die Notwendigkeit für '.
Steadybox

1
Danke für die Erklärung. Ich wusste nicht, dass ein Range-Ausdruck diese besondere Behandlung in Octave hatte. Auf jeden Fall sollte die Tatsache, dass kein Vektor für die Speichereffizienz erstellt wird, für den Programmierer transparent sein. Das heißt, die Tatsache , dass nnz(1:20)keine Arbeit tut , ist wahrscheinlich ein Fehler ( max(1:20), sum(1:20)etc sind gültig).
Luis Mendo

1
Wir sollten es melden . Es könnte andere Funktionen als beeinflussen nnz. Willst du es selbst machen, oder soll ich?
Luis Mendo

1
Gemeldet . Es wirkte sich auch auf MATL aus. jetzt gelöst . Vielen Dank, dass Sie das bemerkt haben!
Luis Mendo

0

Schale , 15 Bytes

ḟȯΛ≤Σ∂MCP¹→←½ḊL

Dies funktioniert mit brachialer Gewalt, daher kann es bei längeren Testfällen zu einer Zeitüberschreitung kommen. Probieren Sie es online!

Erläuterung

ḟȯΛ≤Σ∂MCP¹→←½ḊL  Implicit input, a list of integers x.
              L  Length of x (call it n).
             Ḋ   List of divisors.
            ½    Split at the middle.
          →←     Take last element of first part.
                 This is a divisor d that minimizes d + n/d.
        P¹       List of permutations of x.
      MC         Cut each into slices of length d.
ḟ                Find the first of these matrices that satisfies this:
     ∂            Take anti-diagonals,
    Σ             flatten them,
 ȯΛ≤              check that the result is sorted (each adjacent pair is non-decreasing).

0

C (gcc) , 269 Bytes

j,w,h,x,y;f(A,l)int*A;{int B[l];for(w=l;w-->1;)for(j=0;j<w;)if(A[j++]>A[j]){h=A[~-j];A[~-j]=A[j];A[j]=h;}for(w=h=j=2;w*h-l;j++)l%j||(w=h,h=j),h*h-l||(w=j);for(x=0;x<w*h;x++)for(y=0;y<=x;y++)x-y<w&y<h&&(B[x-y+y*w]=*A++);for(j=0;j<l;j++)j%w||puts(""),printf("%d ",B[j]);}

Probieren Sie es online!


0

JavaScript (ES6), 233 Byte

f=s=>{l=s.length;i=Math.sqrt(l)|0;for(;l%++i;);p=(x)=>(x/i|0+x%i)*l+x%i;m=[...Array(l).keys()].sort((x,y)=>p(x)-p(y));return s.sort((a,b)=>a-b).map((x,i)=>m.indexOf(i)).reduce((a,b,d,g)=>!(d%i)?a.concat([g.slice(d,d+i)]):a,[])}

Erläuterung

f=s=>{                         // Take array `s` of numbers as input
  l=s.length                   // short-hand for length
  i=Math.sqrt(l)|0             // = Math.floor(Math.sqrt(l))
  for(;l%++i;);                // i = width           
  j=l/i                        // j = height

  p=(x)=>(x/i|0+x%i)*l+x%i     // helper to calculate (sort-of) ~manhattan
                                 // distance (horizontal distance weighted
                                 // slightly stronger), from top-left corner
                                 // to the number x, if numbers 0,...,l are
                                 // arranged left-to-right, top-to-bottom
                                 // in an l=i*j grid

  m=[...Array(l).keys()]         // range array
  .sort((x,y)=>p(x)-p(y)),       // manhatten-sorted, sort-of...

  return s.sort((a,b)=>a-b)      // sort input array by numbers,
    .map((x,i,w)=>w[m.indexOf(i)])    // then apply inverse permutation of the
                                 // range-grid manhatten-sort mapping.
    .reduce(                     // slice result into rows
      (a,b,d,g)=>!(d%i)?a.concat([g.slice(d,d+i)]):a
      ,[]
     )
}

0

Java 10, 199 188 186 Bytes

a->{int j=a.length,m=0,n,i=0,k=0;for(n=m+=Math.sqrt(j);m*n<j;n=j/++m);var R=new int[m][n];for(java.util.Arrays.sort(a);i<m+n;i++)for(j=0;j<=i;j++)if(i-j<n&j<m)R[j][i-j]=a[k++];return R;}

Probieren Sie es online aus.

Basierend auf meiner Antwort hier .

Erläuterung:

a->{                        // Method with int-array parameter and int-matrix return-type
  int j=a.length,           //  Length of the input-array
      m=0,n,                //  Amount of rows and columns
      i=0,k=0;              //  Index integers
   for(n=m+=Math.sqrt(j);   //  Set both `m` and `n` to floor(√ `j`)
       m*n<j;               //  Loop as long as `m` multiplied by `n` is not `j`
       n=j/++m);            //   Increase `m` by 1 first with `++m`
                            //   and then set `n` to `j` integer-divided by this new `m`
   var R=new int[m][n];     //  Result-matrix of size `m` by `n`
   for(java.util.Arrays.sort(a);
                            //  Sort the input-array
       i<m+n;)              //  Loop as long as `i` is smaller than `m+n`
     for(j=0;j<=i;j++)      //   Inner loop `j` in range [0,`i`]
       if(i-j<n&j<m)        //    If `i-j` is smaller than `n`, and `j` smaller than `m`
                            //    (So basically check if they are still within bounds)
         R[j][i-j]=a[k++];  //     Add the number of the input array at index `k`,
                            //     to the matrix in the current cell at `[j,i-j]`
  return R;}                //  Return the result-matrix
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.