Sắp xếp tối thiểu một danh sách vào một ma trận


18

Đưa ra một danh sách chưa được sắp xếp của các số nguyên dương duy nhất, sắp xếp tối thiểu nó thành một ma trận 2D. Danh sách đầu vào được đảm bảo có độ dài tổng hợp, có nghĩa là ma trận đầu ra không nhất thiết phải là hình vuông, nhưng có kích thước n x mbằng n,m > 1.

"Sắp xếp tối thiểu" ở đây có nghĩa như sau:

  • Sắp xếp danh sách theo thứ tự tăng dần.
  • Nén ma trận đầu ra càng nhiều càng tốt - giảm thiểu tổng kích thước của ma trận (ví dụ, đối với 20các yếu tố đầu vào như đầu vào, một 5x4hoặc 4x5ma trận đầu ra là cần thiết, và không phải là một 2x10).
  • Nén các số được sắp xếp càng xa về phía trên bên trái của ma trận càng tốt, bắt đầu bằng phần tử đầu tiên trong danh sách được sắp xếp.
  • Điều này có thể được coi là sắp xếp danh sách, sau đó cắt nó dọc theo các đường chéo của ma trận, bắt đầu từ phía trên bên trái.

Ví dụ:

Đối với đầu 1..20ra đầu vào là ma trận 5x4 hoặc 4x5 như sau:

 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

Đối với đầu [3, 5, 12, 9, 6, 11]ra đầu vào là 2x3 hoặc 3x2 như sau

3  5  9
6 11 12

 3  5
 6  9
11 12

Đối với đầu vào [14, 20, 200, 33, 12, 1, 7, 99, 58], đầu ra là 3x3 như sau

 1   7  14
12  20  58
33  99 200

Đối với đầu vào 1..10, đầu ra phải là 2x5 hoặc 5x2 như sau

1 2 4 6  8
3 5 7 9 10

1  2
3  4
5  6
7  8
9 10

Đối với đầu [5, 9, 33, 65, 12, 7, 80, 42, 48, 30, 11, 57, 69, 92, 91]ra đầu vào là 5x3 hoặc 3x5 như sau

 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

Quy tắc

  • Đầu vào có thể được coi là phù hợp với kiểu số nguyên của ngôn ngữ của bạn.
  • Đầu vào và đầu ra có thể được cung cấp bởi bất kỳ phương pháp thuận tiện .
  • Một chương trình đầy đủ hoặc một chức năng được chấp nhận. Nếu một chức năng, bạn có thể trả lại đầu ra thay vì in nó.
  • Sơ hở tiêu chuẩn bị cấm.
  • Đây là vì vậy tất cả các quy tắc chơi gôn thông thường đều được áp dụng và mã ngắn nhất (tính bằng byte) sẽ thắng.

1
Ồ, wow, một từ tôi chưa từng thấy từ Đại số tuyến tính; dễ bị bỏ qua. Lời xin lỗi của tôi.
Bạch tuộc ma thuật Urn

@LuisMendo Đã thêm 15trường hợp kiểm tra phần tử.
admBorkBork

Câu trả lời:


10

Thạch , 24 22 20 byte

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

Hãy thử trực tuyến!

Đã lưu 2 byte nhờ @ Jonathan Allan .

Giải trình

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żṚ$nên lưu hai tôi nghĩ
Jonathan Allan

Liên kết đầu tiên có thể trở thành pSÞỤs.
Dennis


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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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 đã tiết kiệm được 15 byte (!) Bằng các thủ thuật sau

  • thay thế length(x)bằng sum(x|1)(-1 byte)
  • floor()không bắt buộc vì làm :tròn xuống dù sao (-7)
  • ^.5ngắn hơn sqrt()(-3)
  • sử dụng col(X) + row(X)thay vì outer(tốt đẹp!)
  • không thể thoát khỏi t(X)mặc dù - đáng thất vọng;)

Giải pháp ban đầu

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

Nó sẽ trông lạ mắt hơn outerkhi được thay thế bởi row(X)+col(X), nhưng điều đó sẽ yêu cầu khởi tạo ma trận đầu ra Xtrước tiên.

Hãy thử trực tuyến!


2
Rất đẹp! Bạn có thể nhận được tới 95 byte
Giuseppe

1
Có thể có thể sử dụng một cái gì đó từ giải pháp của tôi đến một thách thức liên quan để giúp đỡ ở đây.
Giuseppe

Nó thực sự có liên quan chặt chẽ. Cách tiếp cận rất hay!
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)

Giải trình

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

Các trường hợp thử nghiệm


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}

Hãy thử trực tuyến!

Chương trình con trả về mảng 2 chiều. Liên kết TIO bao gồm mã chân trang để hiển thị kết quả kiểm tra.


3

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

Sử dụng ba loại cấu trúc vòng lặp khác nhau.

Hãy thử trực tuyến!

Chưa được kiểm soát:

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

Câu trả lời tốt đẹp! Tại sao là 'trong nnz(v') yêu cầu?
Luis Mendo

1
@LuisMendo Cảm ơn! Hóa ra 'không bắt buộc nếu tôi bọc biểu thức phạm vi, ví dụ: 1:20xung quanh ngoặc ( [1:20]) tại trang web cuộc gọi (để biến nó thành một vectơ thực tế). Rõ ràng trong Octave, toán tử dấu hai chấm không tạo ra một vectơ , nhưng một hằng số phạm vi chiếm ít không gian hơn trong bộ nhớ. Vì một số lý do, nnz()không hoạt động với loại đó, nhưng hoán vị hằng số phạm vi mang lại một vectơ, vì vậy nó hoạt động với dấu nháy đơn. Gọi hàm với một vectơ thực tế loại bỏ sự cần thiết cho '.
Steadybox

1
Cảm ơn đã giải thích. Tôi không biết rằng một biểu hiện phạm vi có cách đối xử đặc biệt đó ở Octave. Dù sao, thực tế là nó không tạo ra một vectơ cho hiệu quả bộ nhớ nên trong suốt đối với người lập trình. Đó là, thực tế là nnz(1:20)không hoạt động có thể là một lỗi ( max(1:20), sum(1:20)vv hợp lệ).
Luis Mendo

1
Chúng ta nên báo cáo nó . Nó có thể ảnh hưởng đến các chức năng khác hơn nnz. Bạn có muốn tự làm điều đó không?
Luis Mendo

1
Báo cáo . Nó cũng ảnh hưởng đến MATL; Bây giờ đã giải quyết . Cảm ơn vì đã chú ý điều này!
Luis Mendo

0

Husk , 15 byte

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

Điều này hoạt động bằng vũ lực, vì vậy các trường hợp thử nghiệm lâu hơn có thể hết thời gian. Hãy thử trực tuyến!

Giải trình

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

Hãy thử trực tuyến!


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

Giải trình

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

Hãy thử trực tuyến.

Dựa trên câu trả lời của tôi ở đây .

Giải trình:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.