비슷한 문제를 연구하는 동안이 질문에 부딪 혔습니다 : 층화를 줄이기 위해 액체를 최적으로 첨가하십시오. 내 솔루션이 귀하의 상황에도 적용되는 것 같습니다.
액체 A, B 및 C를 30,20,10 비율 (즉, 30 단위 A, 20 단위 B 및 10 단위 C)로 혼합하려는 경우 모두 추가하면 계층화로 끝납니다 더 작은 단위를 섞는 것이 좋습니다. 예를 들어, 시퀀스 [A, B, A, C, B, A]에서 단일 단위 추가를 수행하십시오. 그것은 계층화를 완전히 막을 것입니다.
내가 찾은 방법은 우선 순위 대기열을 사용하여 일종의 병합으로 처리하는 것입니다. 추가 사항을 설명하는 구조를 만드는 경우 :
MergeItem
Item, Count, Frequency, Priority
주파수는 "N마다 1"로 표시됩니다. 따라서 6 번 중 3 번을 더한 A의 빈도는 2 (6/3)입니다.
그리고 초기에 다음을 포함하는 힙을 초기화하십시오.
(A, 3, 2, 2)
(B, 2, 3, 3)
(C, 1, 6, 6)
이제 힙에서 첫 번째 항목을 제거하여 출력합니다. 그런 다음 계수를 1 씩 줄이고 빈도 별 우선 순위를 높이고 다시 힙에 추가하십시오. 결과 힙은 다음과 같습니다.
(B, 2, 3, 0)
(A, 2, 2, 4)
(C, 1, 6, 6)
그런 다음 힙에서 B를 제거하고 출력하여 업데이트 한 다음 힙에 다시 추가하십시오.
(A, 2, 2, 4)
(C, 1, 6, 6)
(B, 1, 3, 6)
그런 식으로 계속하면 원하는 혼합물을 얻습니다. 동일한 우선 순위 항목이 힙에 삽입 될 때 빈도 값이 가장 높은 항목 (즉, 빈도가 가장 적은 항목)이 먼저 주문되도록 사용자 정의 비교자를 사용합니다.
내 블로그에 문제와 솔루션에 대한 자세한 설명을 작성하고 작동하는 C # 코드를 제시했습니다. 목록에 항목 고르게 분배하기를 참조하십시오 .
댓글 후 업데이트
내 문제는 OP의 문제와 유사하다고 생각하므로 내 솔루션이 잠재적으로 유용합니다. OP의 질문 측면에서 답변을 더 틀리지 않은 점에 대해 사과드립니다.
내 솔루션이 0, 1 및 2 대신 A, B 및 C를 사용한다는 첫 번째 이의 제기는 쉽게 해결됩니다. 그것은 단순히 명명법의 문제입니다. 나는 "두 개의 1"보다는 "두 개의 A"를 생각하고 말하는 것이 더 쉽고 혼란스럽지 않다는 것을 안다. 그러나이 토론의 목적을 위해 OP의 명명법을 사용하도록 아래 출력을 수정했습니다.
물론 제 문제는 거리의 개념을 다룹니다. "사물을 골고루 퍼 뜨리려면"거리가 암시됩니다. 그러나 다시 한 번, 내 문제가 OP의 문제와 어떻게 비슷한 지 제대로 보여주지 못한 것은 저의 실패였습니다.
OP가 제공 한 두 가지 예제로 몇 가지 테스트를 실행했습니다. 그건:
[1,1,2,2,3,3] // which I converted to [0,0,1,1,2,2]
[0,0,0,0,1,1,1,2,2,3]
나의 명명법에서 그것들은 각각 [2,2,2]와 [4,3,2,1]로 표현됩니다. 즉, 마지막 예에서 "0 유형의 4 항목, 1 유형의 3 항목, 2 유형의 2 항목 및 3 유형의 1 항목"입니다.
테스트 프로그램을 실행하고 (아래에 설명 된대로) 결과를 게시했습니다. OP의 입력이 없으면 결과가 그의 결과와 비슷하거나 더 나쁘거나 더 나은지 말할 수 없습니다. 다른 사람이 게시하지 않았기 때문에 내 결과를 다른 사람의 결과와 비교할 수도 없습니다.
나는 알고리즘에 좋은 솔루션을 제공하는, 그러나 말할 수있는 내 액체를 혼합 할 때 계층화를 제거 문제. 그리고 그것은 OP의 문제에 대한 합리적인 해결책을 제공하는 것처럼 보입니다 .
아래에 표시된 결과를 위해 블로그 항목에 자세히 설명 된 알고리즘을 사용했습니다. 초기 우선 순위는로 설정 Frequency/2
하고 힙 비교기는보다 빈번한 항목을 선호하도록 수정했습니다. 수정 된 코드는 여기에 표시되며 수정 된 줄은 주석 처리됩니다.
private class HeapItem : IComparable<HeapItem>
{
public int ItemIndex { get; private set; }
public int Count { get; set; }
public double Frequency { get; private set; }
public double Priority { get; set; }
public HeapItem(int itemIndex, int count, int totalItems)
{
ItemIndex = itemIndex;
Count = count;
Frequency = (double)totalItems / Count;
// ** Modified the initial priority setting.
Priority = Frequency/2;
}
public int CompareTo(HeapItem other)
{
if (other == null) return 1;
var rslt = Priority.CompareTo(other.Priority);
if (rslt == 0)
{
// ** Modified to favor the more frequent item.
rslt = Frequency.CompareTo(other.Frequency);
}
return rslt;
}
}
OP의 첫 번째 예제로 테스트 프로그램을 실행하면 다음과 같은 결과를 얻습니다.
Counts: 2,2,2
Sequence: 1,0,2,1,0,2
Distances for item type 0: 3,3
Stddev = 0
Distances for item type 1: 3,3
Stddev = 0
Distances for item type 2: 3,3
Stddev = 0
그래서 내 알고리즘은 모든 카운트가 같은 사소한 문제에 작동합니다.
OP가 게시 한 두 번째 문제는 다음과 같습니다.
Counts: 4,3,2,1
Sequence: 0,1,2,0,1,3,0,2,1,0
Distances for item type 0: 3,3,3,1
Stddev = 0.866025403784439
Distances for item type 1: 3,4,3
Stddev = 0.471404520791032
Distances for item type 2: 5,5
Stddev = 0
Distances for item type 3: 10
Stddev = 0
Standard dev: 0.866025403784439,0.471404520791032,0,0
나는 그것을 개선 할 분명한 방법을 보지 못합니다. 항목 0 [2,3,2,3] 또는 2와 3의 다른 배열에 대한 거리를 재조정 할 수는 있지만 항목 1 및 / 또는 2의 편차가 변경됩니다. "최적"이이 상황에 있습니다. 더 자주 또는 덜 빈번한 항목에서 더 큰 편차를 갖는 것이 더 낫습니까?
OP의 다른 문제가 없었기 때문에 그의 설명을 사용하여 내 자신의 몇 가지를 구성했습니다. 그는 그의 직책에서 말했다 :
일반적인 목록에는 다양한 수량으로 ~ 15 개의 다른 값을 가진 ~ 50 개의 항목이 있습니다.
그래서 내 두 가지 테스트는 다음과 같습니다.
[8,7,6,5,5,4,3,3,2,2,2,1,1,1,1] // 51 items, 15 types
[12,6,5,4,4,3,3,3,2,2,2,1,1] // 48 items, 13 types
그리고 내 결과 :
Counts: 8,7,6,5,5,4,3,3,2,2,2,1,1,1,1
Sequence: 0,1,2,3,4,5,7,6,0,1,2,8,9,10,4,3,0,1,5,2,0,1,3,4,6,7,14,11,13,12,0,2,5,1,0,3,4,2,8,10,9,1,0,7,6,5,3,4,2,1,0
Distances for item type 0: 8,8,4,10,4,8,8,1
Stddev = 2.82566363886433
Distances for item type 1: 8,8,4,12,8,8,3
Stddev = 2.76272565797339
Distances for item type 2: 8,9,12,6,11,5
Stddev = 2.5
Distances for item type 3: 12,7,13,11,8
Stddev = 2.31516738055804
Distances for item type 4: 10,9,13,11,8
Stddev = 1.72046505340853
Distances for item type 5: 13,14,13,11
Stddev = 1.08972473588517
Distances for item type 6: 17,20,14
Stddev = 2.44948974278318
Distances for item type 7: 19,18,14
Stddev = 2.16024689946929
Distances for item type 8: 27,24
Stddev = 1.5
Distances for item type 9: 28,23
Stddev = 2.5
Distances for item type 10: 26,25
Stddev = 0.5
Distances for item type 11: 51
Stddev = 0
Distances for item type 12: 51
Stddev = 0
Distances for item type 13: 51
Stddev = 0
Distances for item type 14: 51
Stddev = 0
두 번째 예의 경우 :
Counts: 12,6,5,4,4,3,3,3,2,2,2,1,1
Sequence: 0,1,2,0,3,4,7,5,6,0,1,8,9,10,0,2,0,3,4,1,0,2,6,7,5,12,11,0,1,0,3,4,2,0,1,10,8,9,0,7,5,6,0,
4,3,2,1,0
Distances for item type 0: 3,6,5,2,4,7,2,4,5,4,5,1
Stddev = 1.68325082306035
Distances for item type 1: 9,9,9,6,12,3
Stddev = 2.82842712474619
Distances for item type 2: 13,6,11,13,5
Stddev = 3.44093010681705
Distances for item type 3: 13,13,14,8
Stddev = 2.34520787991171
Distances for item type 4: 13,13,12,10
Stddev = 1.22474487139159
Distances for item type 5: 17,16,15
Stddev = 0.816496580927726
Distances for item type 6: 14,19,15
Stddev = 2.16024689946929
Distances for item type 7: 17,16,15
Stddev = 0.816496580927726
Distances for item type 8: 25,23
Stddev = 1
Distances for item type 9: 25,23
Stddev = 1
Distances for item type 10: 22,26
Stddev = 2
Distances for item type 11: 48
Stddev = 0
Distances for item type 12: 48
Stddev = 0