Urutkan daftar menjadi sebuah matriks

18

Diberikan daftar bilangan bulat unik positif yang tidak disortir, pilah secara minimal ke dalam matriks 2D. Daftar input dijamin panjang komposit, yang berarti matriks output tidak harus persegi, tetapi n x mdengan ukuran n,m > 1.

"Sortasi minimal" di sini berarti yang berikut:

  • Sortir daftar dalam urutan menaik.
  • Kompak output matriks sebanyak mungkin - meminimalkan jumlah dimensi dari matriks (misalnya, untuk 20elemen masukan sebagai input, 5x4atau 4x5matriks output yang diperlukan, dan tidak 2x10).
  • Kompak angka yang diurutkan sejauh mungkin ke kiri atas matriks, dimulai dengan elemen pertama dalam daftar yang diurutkan.
  • Ini dapat dianggap sebagai pengurutan daftar, kemudian mengirisnya sepanjang matriks anti-diagonal, dimulai dari kiri atas.

Contoh:

Untuk input 1..20output adalah matriks 5x4 atau 4x5 sebagai berikut:

 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

Untuk input [3, 5, 12, 9, 6, 11]output adalah 2x3 atau 3x2 sebagai berikut

3  5  9
6 11 12

 3  5
 6  9
11 12

Untuk input [14, 20, 200, 33, 12, 1, 7, 99, 58], output adalah 3x3 sebagai berikut

 1   7  14
12  20  58
33  99 200

Untuk input 1..10, output harus 2x5 atau 5x2 sebagai berikut

1 2 4 6  8
3 5 7 9 10

1  2
3  4
5  6
7  8
9 10

Untuk input [5, 9, 33, 65, 12, 7, 80, 42, 48, 30, 11, 57, 69, 92, 91]output adalah 5x3 atau 3x5 sebagai berikut

 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

Aturan

  • Input dapat diasumsikan sesuai dengan tipe integer asli bahasa Anda.
  • Input dan output dapat diberikan dengan metode apa pun yang mudah .
  • Program lengkap atau fungsi dapat diterima. Jika suatu fungsi, Anda dapat mengembalikan output daripada mencetaknya.
  • Celah standar dilarang.
  • Ini adalah sehingga semua aturan golf biasa berlaku, dan kode terpendek (dalam byte) menang.
AdmBorkBork
sumber
1
Oh, wow, kata yang belum pernah saya lihat sejak Aljabar Linier; mudah diabaikan. Permintaan maaf saya.
Magic Octopus Mm
@LuisMendo Menambahkan 15case test elemen.
AdmBorkBork

Jawaban:

10

Jelly , 24 22 20 byte

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

Cobalah online!

Disimpan 2 byte berkat @ Jonathan Allan .

Penjelasan

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)
mil
sumber
L%J¬TżṚ$-> LÆDżṚ$harus menyelamatkan dua kurasa
Jonathan Allan
Tautan pertama bisa menjadi pSÞỤs.
Dennis
4

Python 2 , 160 158 153 151 byte

-2 byte terima kasih kepada Erik the Outgolfer
-2 byte terima kasih kepada Tn. 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

Cobalah online! atau Coba semua test case

tongkat
sumber
Saya percaya Anda bisa menggunakan max(0,n-x)untuk -2 byte.
Tn. 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)}

Cobalah online!

Bagaimana itu bekerja

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 menyimpan 15 byte (!) Kekalahan dengan trik-trik berikut

  • mengganti length(x)dengan sum(x|1)(-1 byte)
  • floor()tidak diperlukan sebagai :putaran ke bawah (-7)
  • ^.5lebih pendek dari sqrt()(-3)
  • menggunakan col(X) + row(X)alih-alih outer(baik!)
  • tidak bisa menyingkirkan t(X)meskipun - mengecewakan;)

Solusi asli

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

Itu akan terlihat lebih mewah dengan outerdigantikan oleh row(X)+col(X), tetapi itu akan perlu untuk menginisialisasi matriks keluaran Xterlebih dahulu.

Cobalah online!

Michael M.
sumber
2
Sangat bagus! Anda bisa turun ke 95 byte
Giuseppe
1
Mungkin bisa menggunakan sesuatu dari solusi saya untuk tantangan terkait untuk membantu di sini juga.
Giuseppe
Ini memang terkait erat. Pendekatan yang sangat bagus!
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)

Penjelasan

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

Uji Kasus

Herman L.
sumber
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}

Cobalah online!

Subroutine mengembalikan array 2-D. TIO link termasuk kode footer untuk menampilkan hasil tes.

Xcali
sumber
3

Oktaf , 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

Menggunakan tiga jenis konstruksi loop yang berbeda.

Cobalah online!

Belum dibuka:

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
Steadybox
sumber
Jawaban bagus! Mengapa 'di nnz(v') diperlukan?
Luis Mendo
1
@LuisMendo Terima kasih! Ternyata 'tidak diperlukan jika saya membungkus ekspresi rentang, misalnya 1:20, di sekitar tanda kurung ( [1:20]) di situs panggilan (untuk membuatnya menjadi vektor yang sebenarnya). Rupanya di Octave, operator usus besar tidak membuat vektor , tetapi rentang konstan yang mengambil lebih sedikit ruang dalam memori. Untuk beberapa alasan, nnz()tidak bekerja dengan tipe itu, tetapi mentransposasikan kisaran konstan menghasilkan vektor, sehingga ia bekerja dengan tanda kutip. Memanggil fungsi dengan vektor aktual menghilangkan kebutuhan untuk '.
Steadybox
1
Terima kasih untuk penjelasannya. Saya tidak tahu bahwa ekspresi jangkauan memiliki perlakuan khusus di Octave. Bagaimanapun, fakta bahwa itu tidak membuat vektor untuk efisiensi memori harus transparan kepada programmer. Artinya, fakta bahwa nnz(1:20)tidak bekerja mungkin bug ( max(1:20), sum(1:20)dll yang valid).
Luis Mendo
1
Kita harus melaporkannya . Mungkin mempengaruhi fungsi selain nnz. Apakah Anda ingin melakukannya sendiri, atau haruskah saya?
Luis Mendo
1
Dilaporkan . Ini juga mempengaruhi MATL; sekarang terpecahkan . Terima kasih telah memperhatikan ini!
Luis Mendo
0

Sekam , 15 byte

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

Ini bekerja dengan brute force, sehingga test case yang lebih lama mungkin habis. Cobalah online!

Penjelasan

ḟȯΛ≤Σ∂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).
Zgarb
sumber
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]);}

Cobalah online!

Jonathan Frech
sumber
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,[])}

Penjelasan

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
      ,[]
     )
}
trollkotze
sumber
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;}

Cobalah online.

Berdasarkan jawaban saya di sini .

Penjelasan:

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
Kevin Cruijssen
sumber