Minimalnie posortuj listę do macierzy


18

Biorąc pod uwagę nieposortowaną listę unikalnych ściśle dodatnich liczb całkowitych, minimalnie posortuj ją do macierzy 2D. Lista wejście jest gwarancją długość zespolonego, co oznacza, że matrycę wyjściowe nie musi być kwadratowe, ale ma wielkość n x mz n,m > 1.

„Minimalne sortowanie” oznacza tutaj:

  • Posortuj listę w porządku rosnącym.
  • Kompaktowy macierzy wyjściowej, jak to tylko możliwe - minimalizacja sumy wymiarów matrycy (na przykład w przypadku 20elementów wejściowych jak wejściowych, 5x4lub 4x5matryca wyjście jest to wymagane, a nie 2x10).
  • Zagęszczaj posortowane liczby jak najdalej w lewym górnym rogu macierzy, zaczynając od pierwszego elementu na posortowanej liście.
  • Można to traktować jako sortowanie listy, a następnie krojenie jej wzdłuż przekątnych matrycy, zaczynając od lewego górnego rogu.

Przykłady:

Dla danych 1..20wyjściowych jest to macierz 5x4 lub 4x5, jak następuje:

 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

Dla danych [3, 5, 12, 9, 6, 11]wyjściowych jest to 2x3 lub 3x2 w następujący sposób

3  5  9
6 11 12

 3  5
 6  9
11 12

W przypadku danych wejściowych [14, 20, 200, 33, 12, 1, 7, 99, 58]wyjściowy wynik to 3x3 w następujący sposób

 1   7  14
12  20  58
33  99 200

Dla danych wejściowych 1..10wyjście powinno wynosić 2x5 lub 5x2 w następujący sposób

1 2 4 6  8
3 5 7 9 10

1  2
3  4
5  6
7  8
9 10

[5, 9, 33, 65, 12, 7, 80, 42, 48, 30, 11, 57, 69, 92, 91]Wyjściowy sygnał wyjściowy to 5x3 lub 3x5 w następujący sposób

 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

Zasady

  • Można założyć, że dane wejściowe pasują do rodzimej liczby całkowitej w twoim języku.
  • Dane wejściowe i wyjściowe można podać dowolną dogodną metodą .
  • Dopuszczalny jest pełny program lub funkcja. Jeśli funkcja, możesz zwrócić dane wyjściowe zamiast je drukować.
  • Standardowe luki są zabronione.
  • To jest więc obowiązują wszystkie zwykłe zasady gry w golfa, a wygrywa najkrótszy kod (w bajtach).

1
Och, wow, słowo, którego nie widziałem od Algebry Liniowej; łatwo przeoczyć. Przepraszam.
Magic Octopus Urn

@LuisMendo Dodano 15element testowy elementu.
AdmBorkBork

Odpowiedzi:


10

Galaretka , 24 22 20 bajtów

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

Wypróbuj online!

Zaoszczędź 2 bajty dzięki @ Jonathan Allan .

Wyjaśnienie

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żṚ$powinienem uratować dwa
Jonathan Allan

Pierwszy link może zostać pSÞỤs.
Dennis


4

R 110 95 bajtów

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

Wypróbuj online!

Jak to działa

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 zapisał aż 15 (!) Bajtów dzięki następującym sztuczkom

  • zastępowanie length(x)przez sum(x|1)(-1 bajt)
  • floor()i tak nie jest wymagane, ponieważ :zaokrągla w dół (-7)
  • ^.5 jest krótszy niż sqrt() (-3)
  • za pomocą col(X) + row(X) zamiast outer(fajnie!)
  • nie mogłem się pozbyć t(X) - rozczarowujące;)

Oryginalne rozwiązanie

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

Wyglądałoby to bardziej wymyślne z outerzastąpione row(X)+col(X), ale to wymagałoby zainicjować macierz wyjściowąX pierwszy.

Wypróbuj online!


2
Bardzo dobrze! Możesz przejść do 95 bajtów
Giuseppe

1
Być może uda mi się również wykorzystać coś z mojego rozwiązania do pokrewnego wyzwania .
Giuseppe,

Jest to rzeczywiście ściśle powiązane. Bardzo fajne podejście!
Michael M,

3

JavaScript (ES6), 172 bajty

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)

Wyjaśnienie

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

Przypadki testowe


3

Perl 5 , 132 bajtów

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}

Wypróbuj online!

Podprogram zwraca tablicę 2-D. Łącze TIO zawiera kod stopki do wyświetlania wyniku testu.


3

Oktawa , 151 bajtów

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

Korzystanie z trzech różnych rodzajów konstrukcji pętli.

Wypróbuj online!

Rozwinięty:

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

Niezła odpowiedź! Dlaczego 'w nnz(v') wymagane?
Luis Mendo

1
@LuisMendo Thanks! Okazuje się, że 'nie jest wymagane, jeśli zawijam wyrażenie zakresu, np. 1:20Wokół nawiasów ( [1:20]) w miejscu wywołania (aby uczynić go faktycznym wektorem). Najwyraźniej w Octave operator dwukropka nie tworzy wektora , ale stałą zakresu, która zajmuje znacznie mniej miejsca w pamięci. Z jakiegoś powodu nnz()nie działa z tym typem, ale transpozycja stałej zakresu daje wektor, więc działa z apostrofem. Wywołanie funkcji z faktycznym wektorem eliminuje potrzebę '.
Steadybox

1
Dziękuję za wyjaśnienie. Nie wiedziałem, że wyraz twarzy ma specjalne traktowanie w Octave. W każdym razie fakt, że nie tworzy wektora wydajności pamięci, powinien być przezroczysty dla programisty. To jest fakt, że nnz(1:20)nie działa to prawdopodobnie bug ( max(1:20), sum(1:20)etc ważne).
Luis Mendo

1
Powinniśmy to zgłosić . Może wpływać na inne funkcje niż nnz. Chcesz to zrobić sam, czy powinienem?
Luis Mendo

1
Zgłoszone . Wpłynęło to również na MATL; teraz rozwiązany . Dzięki za zauważenie tego!
Luis Mendo

0

Łuska , 15 bajtów

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

Działa to z użyciem brutalnej siły, więc dłuższe przypadki testowe mogą przekroczyć limit czasu. Wypróbuj online!

Wyjaśnienie

ḟȯΛ≤Σ∂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 bajtów

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

Wypróbuj online!


0

JavaScript (ES6), 233 bajty

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

Wyjaśnienie

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 bajtów

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

Wypróbuj online.

Na podstawie mojej odpowiedzi tutaj .

Wyjaśnienie:

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.