목록을 행렬로 최소화


18

고유 한 양의 정수로 구성된 정렬되지 않은 목록이 있으면 2D 행렬로 최소한 정렬하십시오. 입력 목록은 복합 길이 여야합니다. 즉 출력 행렬이 반드시 정사각형 일 필요는 없지만 크기 n x mn,m > 1입니다.

여기서 "최소 정렬"은 다음을 의미합니다.

  • 목록을 오름차순으로 정렬하십시오.
  • 출력 행렬을 가능한 한 압축하십시오-행렬 크기의 합계를 최소화하십시오 (예 : 20입력 요소 인 입력 요소의 경우 a 5x4또는 4x5출력 행렬이 필요하지만 2x10).
  • 정렬 된 목록의 첫 번째 요소부터 시작하여 정렬 된 숫자를 가능한 한 행렬의 왼쪽 상단까지 압축합니다.
  • 이것은 목록을 정렬 한 다음 왼쪽 위부터 시작하여 행렬의 반 대각선을 따라 자르는 것으로 생각할 수 있습니다.

예 :

입력 1..20출력의 경우 다음과 같이 5x4 또는 4x5 매트릭스입니다.

 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

입력 [3, 5, 12, 9, 6, 11]출력의 경우 다음과 같이 2x3 또는 3x2입니다.

3  5  9
6 11 12

 3  5
 6  9
11 12

입력의 [14, 20, 200, 33, 12, 1, 7, 99, 58]경우 출력은 다음과 같이 3x3입니다.

 1   7  14
12  20  58
33  99 200

입력의 1..10경우 출력은 다음과 같이 2x5 또는 5x2 여야합니다.

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]출력의 경우 다음과 같이 5x3 또는 3x5입니다.

 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

규칙

  • 입력은 언어의 기본 정수 유형에 맞는 것으로 가정 할 수 있습니다.
  • 입력 및 출력은 편리한 방법 으로 제공 할 수 있습니다 .
  • 전체 프로그램 또는 기능이 허용됩니다. 함수 인 경우 출력하지 않고 출력을 반환 할 수 있습니다.
  • 표준 허점 은 금지되어 있습니다.
  • 이것은 이므로 모든 일반적인 골프 규칙이 적용되며 가장 짧은 코드 (바이트)가 이깁니다.

1
오, 와우, 선형 대수 이후로 보지 못한 단어; 쉽게 간과. 사과드립니다.
Magic Octopus Urn

@LuisMendo 15요소 테스트 사례를 추가했습니다 .
AdmBorkBork

답변:


10

젤리 , 24 22 20 바이트

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

온라인으로 사용해보십시오!

@ Jonathan Allan 덕분에 2 바이트를 절약했습니다 .

설명

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żṚ$내가 생각하는 두 가지를 저장해야합니다
Jonathan Allan

첫 번째 링크가 될 수 있습니다 pSÞỤs.
Dennis


4

R 110 95 바이트

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

온라인으로 사용해보십시오!

작동 원리

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
}

주세페 는 다음과 같은 트릭으로 무려 15 (!) 바이트를 절약했습니다.

  • 대체 length(x)하여 sum(x|1)(-1 바이트)
  • floor():어쨌든 반올림 할 필요가 없습니다 (-7).
  • ^.5sqrt()(-3) 보다 짧다
  • 사용하는 col(X) + row(X)대신에 outer(좋은!)
  • t(X)실망스러운;)를 제거 할 수 없었 습니다.)

독창적 인 솔루션

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

outer로 교체하면 더 멋지게 row(X)+col(X)보이지만 출력 행렬을 X먼저 초기화해야합니다 .

온라인으로 사용해보십시오!


2
아주 좋아요! 당신은 아래로 얻을 수있는 95 바이트
주세페

1
에서 무언가 사용할 수 있습니다 관련 문제에 내 솔루션을 여기뿐만 아니라 도움이됩니다.
Giuseppe

실제로 밀접한 관련이 있습니다. 아주 좋은 접근법!
Michael M

3

자바 스크립트 (ES6), 172 바이트

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)

설명

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

테스트 사례


3

펄 5 , 132 바이트

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}

온라인으로 사용해보십시오!

서브 루틴은 2 차원 배열을 반환합니다. TIO 링크에는 테스트 결과를 표시하기위한 바닥 글 코드가 포함되어 있습니다.


3

옥타브 , 151 바이트

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

세 가지 다른 종류의 루프 구성 사용

온라인으로 사용해보십시오!

풀림 :

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

좋은 대답입니다! 'nnz(v') 필요한 이유는 무엇 입니까?
Luis Mendo

1
@LuisMendo 감사합니다! 아웃 턴은 '내가 범위 표현, 예를 들면 포장하는 경우 필요하지 않습니다 1:20괄호 주위 ( [1:20]) 호출 사이트 (그것이 실제 벡터 만들기 위해). 분명히 옥타브 에서 콜론 연산자는 벡터를 만들지 않고 메모리에서 공간을 훨씬 적게 차지하는 범위 상수를 만듭니다 . 어떤 이유로 든 nnz()해당 유형에서는 작동하지 않지만 범위 상수를 조옮김하면 벡터가 생성되므로 아포스트로피와 함께 작동합니다. 실제 벡터로 함수를 호출하면에 대한 필요성이 제거 '됩니다.
Steadybox

1
설명 주셔서 감사합니다. 나는 옥타브에서 범위 표현이 그 특별한 대우를 받았다는 것을 몰랐다. 어쨌든 메모리 효율성을위한 벡터를 생성하지 않는다는 사실은 프로그래머에게 투명해야합니다. 즉, 사실 nnz(1:20)일을하지 않는 아마 버그 (이다 max(1:20), sum(1:20)이다 유효).
Luis Mendo

1
신고 해야 합니다 . 이외의 다른 기능에 영향을 줄 수 있습니다 nnz. 직접 하시겠습니까, 아니면 하시겠습니까?
Luis Mendo

1
보고되었습니다 . MATL에도 영향을 미쳤다. 이제 해결되었습니다 . 이것을 알아 주셔서 감사합니다!
Luis Mendo

0

껍질 , 15 바이트

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

이것은 무차별 적으로 작동하므로 더 긴 테스트 사례가 시간 초과 될 수 있습니다. 온라인으로 사용해보십시오!

설명

ḟȯΛ≤Σ∂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 바이트

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

온라인으로 사용해보십시오!


0

자바 스크립트 (ES6), 233 바이트

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

설명

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

자바 10 199 188 186 바이트

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

온라인으로 사용해보십시오.

내 대답을 바탕으로 여기에 .

설명:

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.