반복적으로 조합 목록을 탐욕스럽게 분할하십시오. 모든 다중 집합의 교집합의 크기가 적어도 해당

먼저 몇 가지 정의가 있습니다.

  • 주어진 nand k, 정렬 된 다중 집합 목록을 고려하십시오. 각 다중 집합에 대해 반복과 함께 k숫자를 선택 합니다 {0, 1, ..., n-1}.

예를 들어 for n=5k=3에는 다음이 있습니다.

[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4), (0, 1, 1), ( 0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 2), (0, 2, 3), (0, 2, 4), (0, 3, 3), (0, 3, 4), (0, 4, 4), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 3), (1, 3, 4), (1, 4, 4) , (2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 3), (2, 3, 4), (2, 4, 4), ( 3, 3, 3), (3, 3, 4), (3, 4, 4), (4, 4, 4)]

  • 부분 부분에있는 모든 다중 집합의 교집합의 크기가 적어도 해당 부동산과 멀티 세트의 목록입니다 k-1. 즉, 모든 다중 집합을 가져 와서 다중 집합 교차를 사용하여 한 번에 교차시킵니다. 예를 들어, [(1, 2, 2), (1, 2, 3), (1, 2, 4)]교집합의 크기가 2 인 부분이지만 [(1, 1, 3),(1, 2, 3),(1, 2, 4)]교집합의 크기가 1이기 때문에 그렇지 않습니다.

직무

코드는 두 개의 인수를해야 n하고 k. 그런 다음이 멀티 세트를 정렬 된 순서로 탐욕스럽게 통과하고 목록의 일부를 출력해야합니다. 이 경우 n=5, k=3올바른 파티셔닝은 다음과 같습니다.

(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4)
(0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 1, 4)
(0, 2, 2), (0, 2, 3), (0, 2, 4)
(0, 3, 3), (0, 3, 4)
(0, 4, 4)
(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4)
(1, 2, 2), (1, 2, 3), (1, 2, 4)
(1, 3, 3), (1, 3, 4)
(1, 4, 4)
(2, 2, 2), (2, 2, 3), (2, 2, 4)
(2, 3, 3), (2, 3, 4)
(2, 4, 4)
(3, 3, 3), (3, 3, 4)
(3, 4, 4), (4, 4, 4)

에 대한 또 다른 예는 다음과 같습니다 n = 4, k = 4.

(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3)
(0, 0, 1, 1), (0, 0, 1, 2), (0, 0, 1, 3)
(0, 0, 2, 2), (0, 0, 2, 3)
(0, 0, 3, 3)
(0, 1, 1, 1), (0, 1, 1, 2), (0, 1, 1, 3)
(0, 1, 2, 2), (0, 1, 2, 3)
(0, 1, 3, 3)
(0, 2, 2, 2), (0, 2, 2, 3)
(0, 2, 3, 3), (0, 3, 3, 3)
(1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3)
(1, 1, 2, 2), (1, 1, 2, 3)
(1, 1, 3, 3)
(1, 2, 2, 2), (1, 2, 2, 3)
(1, 2, 3, 3), (1, 3, 3, 3)
(2, 2, 2, 2), (2, 2, 2, 3)
(2, 2, 3, 3), (2, 3, 3, 3)
(3, 3, 3, 3)

욕심의 의미에 대한 설명 : 각 다중 집합에 대해 기존 부분에 추가 할 수 있는지 확인합니다. 가능하다면 추가 할 수 있습니다. 그것이 우리가 새로운 부분을 시작할 수 없다면. 우리는 위에서 주어진 예제에서와 같이 멀티 세트를 정렬 된 순서로 봅니다.

산출

원하는 형식으로 분할을 출력 할 수 있습니다. 그러나 멀티 세트는 한 줄에 가로로 써야합니다. 즉, 개별 다중 집합을 세로로 쓰거나 여러 줄에 걸쳐서는 ​​안됩니다. 출력에서 부품 표현을 분리하는 방법을 선택할 수 있습니다.

가정

우리는 그것을 가정 할 수 있습니다 n >= k > 0.



답변

젤리 , 26 25 바이트

œ&µL‘<⁴ȧ⁹ȯ
œċµç\L€=⁴œṗµḊ’

리스트리스트의 표현을 인쇄하는 전체 프로그램. 각리스트는 예를 들어 n = 5, k = 3의 일부입니다.

[[[0, 0, 0], [0, 0, 1], [0, 0, 2], [0, 0, 3], [0, 0, 4]], [[0, 1, 1], [0, 1, 2], [0, 1, 3], [0, 1, 4]], [[0, 2, 2], [0, 2, 3], [0, 2, 4]], [[0, 3, 3], [0, 3, 4]], [0, 4, 4], [[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4]], [[1, 2, 2], [1, 2, 3], [1, 2, 4]], [[1, 3, 3], [1, 3, 4]], [1, 4, 4], [[2, 2, 2], [2, 2, 3], [2, 2, 4]], [[2, 3, 3], [2, 3, 4]], [2, 4, 4], [[3, 3, 3], [3, 3, 4]], [[3, 4, 4], [4, 4, 4]]]

참고 : 사용 된 표현 은 길이가 1 인 중복 [ 주변 목록을 제거합니다 ] .

온라인으로 사용해보십시오! 또는 예쁜 인쇄 버전 (3 바이트 비용)을참조하십시오

어떻게?

œ&µL‘<⁴ȧ⁹ȯ - Link 1, conditional multi-set intersection: list x, list y
œ&         - multi-set intersection(x, y)
  µ        - monadic chain separation (call that i)
   L       - length(i)
    ‘      - increment
     <     - less than?:
      ⁴    -     2nd program input, k
       ȧ   - logical and with:
        ⁹  -     link's right argument, y (y if i is too short, else 0)
         ȯ - logical or (y if i is too short, else i)

œċµç\L€=⁴œṗµḊ’ - Main link: n, k
œċ             - combinations with replacement(n, k) (sorted since n implies [1,n])
  µ            - monadic chain separation (call that w)
         œṗ    - partition w at truthy indexes of:
   ç\          -     reduce w with last link (1) as a dyad
     L€        -     length of €ach
        ⁴      -     2nd program input, k
       =       -     equal (vectorises)
           µ   - monadic chain separation
            Ḋ  - dequeue (since the result will always start with an empty list)
             ’ - decrement (vectorises) (since the Natural numbers were used by œċ)

답변

MATLAB, 272 바이트

function g(n,k);l=unique(sort(nchoosek(repmat(0:n-1,1,k),k),2),'rows');p=zeros(0,k);for i=1:size(l,1)p=[p;l(i,:)];a=0;for j=1:size(p,1)for m=1:size(p,1)b=0;for h=1:k if(p(j,h)==p(m,h))b=b+1;end;end;if(b<k-1)a=1;end;end;end;if(a)fprintf('\n');p=l(i,:);end;disp(l(i,:));end;

산출:

>> g(5,3)
 0     0     0

 0     0     1

 0     0     2

 0     0     3

 0     0     4


 0     1     1

 0     1     2

 0     1     3

 0     1     4


 0     2     2

 0     2     3

 0     2     4


 0     3     3

 0     3     4


 0     4     4


 1     1     1

 1     1     2

 1     1     3

 1     1     4


 1     2     2

 1     2     3

 1     2     4


 1     3     3

 1     3     4


 1     4     4


 2     2     2

 2     2     3

 2     2     4


 2     3     3

 2     3     4


 2     4     4


 3     3     3

 3     3     4


 3     4     4

 4     4     4

>> g(4,4)
 0     0     0     0

 0     0     0     1

 0     0     0     2

 0     0     0     3


 0     0     1     1

 0     0     1     2

 0     0     1     3


 0     0     2     2

 0     0     2     3


 0     0     3     3


 0     1     1     1

 0     1     1     2

 0     1     1     3


 0     1     2     2

 0     1     2     3


 0     1     3     3


 0     2     2     2

 0     2     2     3


 0     2     3     3

 0     3     3     3


 1     1     1     1

 1     1     1     2

 1     1     1     3


 1     1     2     2

 1     1     2     3


 1     1     3     3


 1     2     2     2

 1     2     2     3


 1     2     3     3

 1     3     3     3


 2     2     2     2

 2     2     2     3


 2     2     3     3

 2     3     3     3


 3     3     3     3

다른 부분 사이에 두 개의 빈 줄이 있습니다.

언 골프 드 :

function g(n,k);
l=unique(sort(nchoosek(repmat(0:n-1,1,k),k),2),'rows');
p=zeros(0,k);
for i=1:size(l,1)
    p=[p;l(i,:)];
    a=0;
    for j=1:size(p,1)
        for m=1:size(p,1)
            b=0;
            for h=1:k
                if(p(j,h)==p(m,h))
                    b=b+1;
                end;
            end;
                if(b<k-1)
                    a=1;
                end;
        end;
    end;
    if(a)
        fprintf('\n');
        p=l(i,:);
    end;
    disp(l(i,:));
end;

설명:

먼저 무차별 대입으로 모든 멀티 세트를 찾습니다.

l=unique(sort(nchoosek(repmat(0:n-1,1,k),k),2),'rows');

repmat(0:n-1, 1, k)값의 벡터 0를 여러 n-1 k번 반복합니다 .

nchoosek(x, k) 반복 된 벡터의 모든 k 조합을 포함하는 행렬을 반환합니다.

sort(x, 2)모든 k 조합을 정렬 한 다음 unique(x, 'rows')모든 중복 을 제거합니다.

p=zeros(0,k);k열 이있는 빈 행렬을 만듭니다 . 스택으로 사용하겠습니다. 가장 바깥 쪽 for루프가 반복 될 때마다 먼저 현재 다중 집합을 스택에 추가합니다 p=[p;l(i,:)];.

그런 다음 스택의 모든 다중 집합의 교차가 k-1다음 코드 로 적어도 길 intersect었는지 확인 합니다 (MATLAB 명령을 사용 하여 교차를 확인할 수는 없지만 집합을 반환하기 때문에 다중 집합이 필요합니다).

a=0;
for j=1:size(p,1)
    for m=1:size(p,1)
        b=0;
        for h=1:k
            if(p(j,h)==p(m,h))
                b=b+1;
            end;
        end;
        if(b<k-1)
            a=1;
        end;
    end;
end;

교차점이 충분히 길면 a == 0, 그렇지 않으면 a == 1.

교차로가 충분히 길지 않으면 줄 바꿈을 인쇄하고 스택을 비 웁니다.

if(a)
    fprintf('\n');
    p=l(i,:); % Only the current multiset will be left in the stack.
end;

그런 다음 현재 다중 집합을 인쇄합니다.

disp(l(i,:));

답변

MATL , 34 바이트

vi:qiZ^!S!Xu!"@!&vt1&dXasq?0&Y)0cb

공백이 포함 된 선으로 부품이 분리됩니다.

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

설명

면책 조항 :이 방법은 효과가있는 것으로 보이지만 (테스트 경우와 동일) 항상 작동한다는 증거는 없습니다

멀티 세트 (즉 MULTISET 외부 적, 내부적으로 (즉, 각 MULTISET 비 감소했다 항목) 분류되며, M은 MULTISET 앞에 오는 N 경우 M의 선행 N 사전 식).

다중 집합 교집합을 계산하기 위해 정렬 된 다중 집합이 행렬의 행으로 배열되고 각 열을 따라 연속적인 차이가 계산됩니다. 최대 하나를 제외한 모든 열의 차이가 모두 0 인 경우 다중 집합은 동일한 부분에 속합니다.

이 테스트는 같은 멀티 세트에 대한 허위 부정적인 결과를 줄 것 (1,2,3)등을 (2,3,4): 경우에도 2, 3공통 항목, 그들은이 일치하지 않는 컬럼에 있기 때문에 그들은 같은 감지되지 않습니다.

그러나 이것은 적어도 테스트 사례에서 문제가되지 않는 것 같습니다. 이 같은 멀티 세트와 테스트 나타납니다 1,2,32,3,4일부 중간 MULTISET가 부정적인 결과를주고, 그래서 그들은 이미 다른 부분에 있기 때문에 결코 사실이 수행되어야한다. 이것이 사실이라면, 그 이유는 다중 집합이 정렬되어 있다는 사실과 의심의 여지가 없습니다.

그러나 이것에 대한 증거는 없습니다. 그냥 작동하는 것 같습니다.

v           % Concatenate stack vertically: gives an empty array. This will
            % grow into the first part
i:q         % Input n. Push [0 1 ... n-1]
i           % Input k
Z^          % Cartesian power. Each Cartesian tuple is on a row
!S!         % Sort each row
Xu          % Unique rows. This gives all multisets, sorted, each on a row
!           % Transpose
"           % For each column
  @!        %   Push current multiset as a row
  &v        %   Vertically concatenate with the part so far
  t         %   Duplicate
  1&d       %   Consecutive differences along each column
  Xas       %   Number of columns that contain at least one non-zero entry
  q?        %   If that number is not 1 (this means that the current
            %   multiset should begin a new part)
    0&Y)    %     Push last row, then the array with the remaining rows.
            %     Said array is a part, which we now know is complete
    0c      %     Push character 0. This will be shown as a line containing
            %     a space. This is used as a separator between parts.
    b       %     Bubble up. This moves the loose row to the top. This row
            %     is the beginning of a new part
            %   Implicitly end if
            % Implicitly end for
            % Implicitly display

답변

PHP, 245 바이트

for(;$i<($n=$argv[1])**$m=$argv[2];$i++){for($a=[],$v=$i;$v|count($a)<$m;$v=$v/$n^0)array_unshift($a,$v%$n);sort($a);in_array($a,$r)?:$r[]=$a;}foreach($r as$k=>$v)$k&&count(array_diff_assoc($x[$c][0],$v))<2?$x[$c][]=$v:$x[++$c][]=$v;print_r($x);

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

넓히는

for(;$i<($n=$argv[1])**$m=$argv[2];$i++){ # loop till $argv[1]**$argv[2]
    for($a=[],$v=$i;$v|count($a)<$m;$v=$v/$n^0)
    array_unshift($a,$v%$n); # create base n array
    sort($a); #sort array
    in_array($a,$r)?:$r[]=$a; # if sorted array is not in result add it
}
foreach($r as$k=>$v)
    $k&& # > first item and
    count(array_diff_assoc($x[$c][0],$v))<2 # if difference is only 1 item between actual item and first item in last storage item
    ?$x[$c][]=$v # add item in last storage array
    :$x[++$c][]=$v; # make a new last storage array
print_r($x); # Output as array

문자열로 출력

foreach($x as$y){$p=[];
foreach($y as$z){$p[]=$o="(".join(",",$z).")";}
    echo join(", ",$p)."\n";
}

더 정밀한 n> 15

for($i=0;$i<bcpow($argv[1],$argv[2]);$i=bcadd($i,1)){
    for($a=[],$v=$i;$v|count($a)<$argv[2];$v=bcdiv($v,$argv[1]))
    array_unshift($a,bcmod($v,$argv[1]));
    sort($a);
    in_array($a,$r)?:$r[]=$a;
}