Ordinare minimamente un elenco in una matrice


18

Dato un elenco non ordinato di interi univoci strettamente positivi, ordinalo minimamente in una matrice 2D. L'elenco di input è garantito per essere di lunghezza composita, il che significa che la matrice di output non è necessariamente quadrata, ma è di dimensioni n x mcon n,m > 1.

"Ordinamento minimo" qui significa quanto segue:

  • Ordina l'elenco in ordine crescente.
  • Compattare la matrice di uscita il più possibile - minimizzare la somma delle dimensioni della matrice (ad esempio, per 20elementi di input come input, una 5x4o 4x5è necessaria matrice di uscita, e non 2x10).
  • Compatta i numeri ordinati il ​​più possibile nella parte superiore sinistra della matrice, iniziando dal primo elemento nell'elenco ordinato.
  • Questo può essere pensato come l'ordinamento dell'elenco, quindi tagliandolo lungo le anti-diagonali della matrice, iniziando dalla parte superiore sinistra.

Esempi:

Per l' 1..20output di input è una matrice 5x4 o 4x5 come segue:

 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

Per l'ingresso in [3, 5, 12, 9, 6, 11]uscita è un 2x3 o 3x2 come segue

3  5  9
6 11 12

 3  5
 6  9
11 12

Per input [14, 20, 200, 33, 12, 1, 7, 99, 58], output è un 3x3 come segue

 1   7  14
12  20  58
33  99 200

Per l'ingresso 1..10l'uscita deve essere un 2x5 o 5x2 come segue

1 2 4 6  8
3 5 7 9 10

1  2
3  4
5  6
7  8
9 10

Per l'ingresso in [5, 9, 33, 65, 12, 7, 80, 42, 48, 30, 11, 57, 69, 92, 91]uscita è un 5x3 o 3x5 come segue

 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

Regole

  • Si può presumere che l'input si adatti al tipo intero nativo della tua lingua.
  • L'input e l'output possono essere forniti con qualsiasi metodo conveniente .
  • È accettabile un programma completo o una funzione. Se una funzione, è possibile restituire l'output anziché stamparlo.
  • Sono vietate le scappatoie standard .
  • Si tratta di quindi si applicano tutte le normali regole del golf e vince il codice più breve (in byte).

1
Oh, wow, una parola che non vedo da Linear Algebra; facilmente trascurato. Mie scuse.
Magic Octopus Urn,

@LuisMendo Aggiunto un 15test case element.
AdmBorkBork,

Risposte:


10

Gelatina , 24 22 20 byte

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

Provalo online!

Salvato 2 byte grazie a @ Jonathan Allan .

Spiegazione

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żṚ$Dovrei salvarne due penso
Jonathan Allan,

Il primo link può diventare pSÞỤs.
Dennis,

4

Python 2 , 160 158 153 151 byte

-2 byte grazie a Erik the Outgolfer
-2 byte grazie a Mr. Xcoder

s=sorted(input())
l=len(s)
x=int(l**.5)
while l%x:x+=1
n=1
o=eval(`l/x*[[]]`)
while s:
 for i in range(l/x)[max(0,n-x):n]:o[i]+=s.pop(0),
 n+=1
print o

Provalo online! oppure Prova tutti i casi di test


Credo che tu possa usare max(0,n-x)per -2 byte.
Mr. Xcoder,

4

R 110 95 byte

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

Provalo online!

Come funziona

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 ha salvato un enorme 15 (!) Byte con i seguenti trucchi

  • sostituendo length(x)con sum(x|1)(-1 byte)
  • floor()non è richiesto come :arrotondamento per difetto (-7)
  • ^.5è più corto di sqrt()(-3)
  • usando col(X) + row(X)invece di outer(bello!)
  • non riuscivo a liberarmi del t(X)- deludente;)

Soluzione originale

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

Sarebbe più bello se outervenisse sostituito row(X)+col(X), ma ciò richiederebbe prima di inizializzare la matrice di output X.

Provalo online!


2
Molto bella! È possibile scendere a 95 byte
Giuseppe,

1
Potrebbe essere in grado di utilizzare qualcosa dalla mia soluzione a una sfida correlata per aiutare anche qui.
Giuseppe,

È infatti strettamente correlato. Approccio molto bello!
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)

Spiegazione

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

Casi test


3

Perl 5 , 132 byte

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}

Provalo online!

La subroutine restituisce un array 2-D. Il collegamento TIO include il codice piè di pagina per la visualizzazione dei risultati del test.


3

Ottava , 151 byte

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

Utilizzando tre diversi tipi di costrutti loop.

Provalo online!

srotolato:

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

Bella risposta! Perché la 'a nnz(v') richiesta?
Luis Mendo,

1
@LuisMendo Grazie! Risulta che 'non è necessario se avvolgo l'espressione di intervallo, ad esempio 1:20, tra parentesi ( [1:20]) nel sito di chiamata (per renderlo un vettore reale). Apparentemente in Octave, l'operatore due punti non crea un vettore , ma una costante di intervallo che occupa molto meno spazio in memoria. Per qualche motivo, nnz()non funziona con quel tipo, ma trasporre la costante di intervallo produce un vettore, quindi funziona con l'apostrofo. Chiamare la funzione con un vettore reale elimina la necessità di '.
Steadybox,

1
Grazie per la spiegazione. Non sapevo che un'espressione a distanza avesse quel trattamento speciale in Octave. Comunque, il fatto che non crei un vettore per l'efficienza della memoria dovrebbe essere trasparente per il programmatore. Cioè, il fatto che nnz(1:20)non funzioni è probabilmente un bug ( max(1:20), sum(1:20)ecc. Sono validi).
Luis Mendo,

1
Dovremmo segnalarlo . Potrebbe influire su altre funzioni oltre a nnz. Vuoi farlo da solo, o dovrei?
Luis Mendo,

1
Segnalato . Colpì anche MATL; ora risolto . Grazie per averlo notato!
Luis Mendo,

0

Buccia , 15 byte

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

Funziona con la forza bruta, quindi i casi di test più lunghi possono scadere. Provalo online!

Spiegazione

ḟȯΛ≤Σ∂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 byte

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

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

Spiegazione

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 byte

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;}

Provalo online.

Sulla base della mia risposta qui .

Spiegazione:

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
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.