Bir listeyi en az bir matrise ayırın


18

Benzersiz kesinlikle pozitif tamsayıların sıralanmamış bir listesi göz önüne alındığında, minimal bir 2D matrisine sıralayın. Giriş listesi çıkış matris mutlaka kare olmadığı anlamına gelir bileşik uzunluğunun garantilidir, ancak boyutta olan bir n x mile n,m > 1.

"Minimally sort" burada şu anlama gelir:

  • Listeyi artan düzende sıralayın.
  • Çıkış matrisini olabildiğince sıkıştırın - matrisin boyutlarının toplamını en aza indirin (örneğin, 20giriş elemanları olarak a 5x4veya 4x5çıkış matrisi gereklidir, a değil 2x10).
  • Sıralanan sayılar, sıralanan listedeki ilk öğeden başlayarak mümkün olduğunca matrisin sol üst köşesine sıkıştırılır.
  • Bu listeyi sıralamak, daha sonra sol üst köşeden başlayarak matrisin anti-köşegenleri boyunca dilimlemek olarak düşünülebilir.

Örnekler:

Giriş 1..20çıkışı için 5x4 veya 4x5 matris aşağıdaki gibidir:

 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

Giriş [3, 5, 12, 9, 6, 11]çıkışı için 2x3 veya 3x2 aşağıdaki gibidir

3  5  9
6 11 12

 3  5
 6  9
11 12

Giriş için [14, 20, 200, 33, 12, 1, 7, 99, 58]çıkış aşağıdaki gibi 3x3'tür

 1   7  14
12  20  58
33  99 200

Giriş 1..10için çıkış aşağıdaki gibi 2x5 veya 5x2 olmalıdır

1 2 4 6  8
3 5 7 9 10

1  2
3  4
5  6
7  8
9 10

Giriş [5, 9, 33, 65, 12, 7, 80, 42, 48, 30, 11, 57, 69, 92, 91]çıkışı için 5x3 veya 3x5 aşağıdaki gibidir

 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

kurallar

  • Girişin, dilinizin yerel tamsayı türüne uygun olduğu varsayılabilir.
  • Giriş ve çıkış herhangi bir uygun yöntemle verilebilir .
  • Tam bir program veya bir işlev kabul edilebilir. Bir işlev varsa, çıktıyı yazdırmak yerine döndürebilirsiniz.
  • Standart boşluklar yasaktır.
  • Bu bu nedenle her zamanki golf kuralları geçerlidir ve en kısa kod (bayt cinsinden) kazanır.

1
Oh, vay be, Doğrusal Cebir'den beri görmediğim bir kelime; kolayca gözden kaçan. Özür dilerim.
Sihirli Ahtapot Urn

@LuisMendo Bir 15eleman test durumu eklendi.
AdmBorkBork

Yanıtlar:


10

Jöle , 24 22 20 bayt

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

Çevrimiçi deneyin!

@ Jonathan Allan sayesinde 2 bayt kurtardı .

açıklama

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żṚ$Sanırım iki kurtarmalı
Jonathan Allan

İlk bağlantı olabilir pSÞỤs.
Dennis


4

R 110 95 bayt

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

Çevrimiçi deneyin!

Nasıl çalışır

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 aşağıdaki püf noktaları ile 15 (!) Bayt kurtardı

  • değiştirilmesi length(x)ile sum(x|1)(-1 bayt)
  • floor():yine de mermi olarak gerekli değil (-7)
  • ^.5 daha kısa sqrt()(-3) '
  • col(X) + row(X)yerine kullanmakouter (nice!)
  • t(X)olsa kurtulmak - hayal kırıklığı;)

Orijinal çözüm

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

outerDeğiştirilmesiyle daha süslü görünecektir row(X)+col(X), ancak bunun çıkış matrisini başlatması gerekirX .

Çevrimiçi deneyin!


2
Çok hoş! 95 bayta
Giuseppe

1
Burada da yardımcı olmak için çözümümden ilgili bir zorluğa kadar bir şeyler kullanabilir .
Giuseppe

Gerçekten yakından ilişkilidir. Çok hoş bir yaklaşım!
Michael M

3

JavaScript (ES6), 172 bayt

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)

açıklama

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

Test Durumları


3

Perl 5 , 132 bayt

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}

Çevrimiçi deneyin!

Altyordam 2 boyutlu bir dizi döndürür. TIO bağlantısı, test sonucunu görüntülemek için altbilgi kodu içerir.


3

Oktav , 151 bayt

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

Üç farklı döngü yapısı kullanmak.

Çevrimiçi deneyin!

unrolled:

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

Güzel cevap! Neden olduğu 'içinde nnz(v') gerekli?
Luis Mendo

1
@LuisMendo Teşekkürler! Dışarı Dönüşler 'Ben aralık ifadesini, örneğin sarın eğer gerekli değildir 1:20parantez etrafında ( [1:20]) çağrısı sitesinde (gerçek bir vektör yapmaya). Görünüşe göre Octave'de, kolon operatörü bir vektör değil , bellekte çok daha az yer kaplayan bir aralık sabiti oluşturuyor. Bazı nedenlerden dolayı, nnz()bu türle çalışmaz, ancak aralık sabitinin transpozisyonu bir vektör verir, bu nedenle kesme işareti ile çalışır. İşlevin gerçek bir vektörle çağrılması ',.
Steadybox

1
Açıklama için teşekkürler. Bir dizi ifadenin Octave'de bu özel muameleye sahip olduğunu bilmiyordum. Her neyse, bellek verimliliği için bir vektör oluşturmadığı gerçeği programcıya şeffaf olmalıdır. Olduğunu, aslında nnz(1:20)işi değil muhtemelen bir hata (olduğu max(1:20), sum(1:20)vb vardır geçerlidir).
Luis Mendo

1
Bunu rapor etmeliyiz . Bunun dışındaki işlevleri etkileyebilir nnz. Bunu kendiniz yapmak ister misiniz yoksa ben mi?
Luis Mendo

1
Bildirildi . Ayrıca MATL'yi de etkiledi; Şimdi çözüldü . Bunu fark ettiğiniz için teşekkürler!
Luis Mendo

0

Kabuk , 15 bayt

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

Bu kaba kuvvet ile çalışır, bu nedenle daha uzun test vakaları zaman aşımına uğrayabilir. Çevrimiçi deneyin!

açıklama

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

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

Çevrimiçi deneyin!


0

JavaScript (ES6), 233 bayt

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

açıklama

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 bayt

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

Çevrimiçi deneyin.

Buradaki cevabım temel alınarak .

Açıklama:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.