모든 벡터 파티션을 효율적으로 생성


12

벡터 파티션은 벡터를 일련의 벡터로 분할하여 합계가 원래가되도록합니다. 다음은 몇 개의 파티션입니다.

[3, 1, 2] = [3, 1, 2]
[3, 1, 2] = [0, 0, 1] + [0, 0, 1] + [0, 1, 0] + [1, 0, 0] + [2, 0, 0]
[3, 1, 2] = [1, 1, 2] + [2, 0, 0]

여기서 벡터 추가는 요소별로 수행됩니다. 유효한 파티션에는 음의 정수를 가진 벡터 나 0이 아닌 벡터가 없습니다.

이제 목표 벡터가 주어지면 가능한 모든 벡터 파티션을 생성하는 프로그램이나 함수를 작성하는 것이 과제입니다. 이것은 비교적 쉬운 것처럼 들릴 수 있습니다 ...

...하지만 비틀기가 있습니다. 입력 벡터의 크기가 L이고 생성하는 가장 큰 파티션에 M 개의 요소가있는 경우 O (L * M) 이상의 메모리를 사용할 수 없습니다.

정수가 O (1) 메모리를 사용한다고 가정 할 수 있습니다. 즉, 파티션을 생성 할 때 파티션을 출력해야합니다. 또한 각 파티션을 정확히 한 번만 출력해야합니다. 예를 들어, 이들은 동일한 파티션입니다.

[3, 1, 2] = [3, 0, 2] + [0, 1, 0]
[3, 1, 2] = [0, 1, 0] + [3, 0, 2]

당신이 출력했다면 두 대답 모두 유효하지 않습니다.


의 모든 파티션 [3, 2]:

[3, 2]
[0, 1] + [3, 1]
[0, 1] + [0, 1] + [3, 0]
[0, 1] + [0, 1] + [1, 0] + [2, 0]
[0, 1] + [0, 1] + [1, 0] + [1, 0] + [1, 0]
[0, 1] + [1, 0] + [2, 1]
[0, 1] + [1, 0] + [1, 0] + [1, 1]
[0, 1] + [1, 1] + [2, 0]
[0, 2] + [3, 0]
[0, 2] + [1, 0] + [2, 0]
[0, 2] + [1, 0] + [1, 0] + [1, 0]
[1, 0] + [2, 2]
[1, 0] + [1, 0] + [1, 2]
[1, 0] + [1, 1] + [1, 1]
[1, 1] + [2, 1]
[1, 2] + [2, 0]

답을 테스트하려면에서 실행하십시오 [3, 2, 5, 2]. 17939 개의 파티션을 생성해야합니다.이 파티션은 모두 합쳐지고 [3, 2, 5, 2]고유합니다 (먼저 사전에 각 파티션을 정렬하여 고유성을 테스트 할 수 있음).


바이트 단위의 최단 코드가 이깁니다.

답변:


3

파이썬 2, 289 바이트

간단한 무차별 대입 알고리즘. 전체 목록을 밑 max(input)+1( b) 의 숫자로 취급 하고 범위의 각 "숫자"를 확인하여 다음과 같은지 확인 [0, b**(L*M))합니다.

  1. 정확한 금액으로 합산
  2. 알파벳 순서로 표시됩니다 (고유성 보장)

리스트가이 기준과 일치하면 프로그램은 모든 0으로 설정된 벡터를 모두 제거하여 출력합니다.

메모리 사용량

이 프로그램에서 사용하는 가장 큰 데이터 구조는 이중 중첩 목록으로, 메모리 를주기 위해 Mliss 길이 L를 포함 하는 목록 길이 O(L*M)입니다.

다른 데이터 구조의 경우 3 개의 전역 int O(3), 1 목록 길이 L( O(L)), 1 배열 길이 M( O(M)) 및 출력 할 때 가장 큰 배열의 사본 ( O(L*M))이 있습니다.

전체적으로 이것은 나에게 메모리 사용 O(2*L*M + L + M + 3)을 단순화 O(L*M)하여 기준을 충족시킵니다.

시간 복잡성

무차별 대입 알고리즘이기 때문에이 알고리즘은 매우 느립니다. while 루프가 종료 되려면 배열의 마지막 int가이어야 b-1합니다. 루프가 b**(L*M)발생하기 전에 실행 시간이 필요 합니다.

또한 목록이 실행될 때마다 두 가지 조건을 모두 확인하고 L*M+L+M반복을 사용하여 최악의 경우 목록을 인쇄해야합니다 . 이것은 전체 적으로 단순화됩니다 O(L*M * b**(L*M)). 에 프로그램을 테스트하려고했지만 [3, 2, 5, 2]45 분 후에 포기했습니다.

골프 프로그램

v=input()
L=len(v)
M=sum(v)
b=max(v)
R=range
t=[L*[0]for i in R(M)]
def A(l,i):
 if i<L*M-1and~-b<l[i/L][i%L]:A(l,i+1)
 l[i/L][i%L]=-~l[i/L][i%L]%-~b
while t[-1][-1]<b:
 if v==[sum(q[i]for q in t)for i in R(L)]and all(`t[i]`>=`t[i+1]`for i in R(M-1)):print[x for x in t if[0]*L!=x]
 A(t,0)

나는 이것을 조금 더 골프, 특히 증분 부분으로 골프를 칠 수 있습니다. Ungolfed 코드가 온다.


확실히 효율성 내가이 질문을 게시 할 때 기대했다,하지만 난 생각이 기술적 문제 : 해결
orlp
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.