from itertools import combinations
from collections import Counter
def most_equal_pairs(seq, n=None):
seq_mapping = dict(enumerate(seq))
if len(seq_mapping) < 2:
raise ValueError()
if len(seq_mapping) == 2:
first, second = seq_mapping.values()
yield [first], [second], abs(first - second)
return
ids = set(seq_mapping)
def get_chunk_by_ids(ids):
return [seq_mapping[i] for i in ids]
def get_chunk_sum_by_ids(ids):
return sum(get_chunk_by_ids(ids))
pairs = Counter()
for comb_len in range(1, len(ids) - 1):
for first_comb in combinations(ids, comb_len):
second_comb = tuple(ids - set(first_comb))
first_sum = get_chunk_sum_by_ids(first_comb)
second_sum = get_chunk_sum_by_ids(second_comb)
diff = abs(first_sum - second_sum)
pairs[(first_comb, second_comb)] = -diff
for (first_comb_ids, second_comb_ids), diff in pairs.most_common(n):
first_comb = get_chunk_by_ids(first_comb_ids)
second_comb = get_chunk_by_ids(second_comb_ids)
yield first_comb, second_comb, abs(diff)
def test(seq):
pairs = list(most_equal_pairs(seq))
diff_seq = []
for first, second, diff in pairs:
assert abs(sum(first) - sum(second)) == abs(diff)
diff_seq.append(diff)
assert tuple(sorted(diff_seq)) == tuple(diff_seq)
best_pair = pairs[0]
first, second, diff = best_pair
return first, second, sum(first), sum(second), diff
result
>>> test([10, 1, 1, 1])
([10], [1, 1, 1], 10, 3, 7)
>>> test([2, 5, 9, 5, 1, 1])
([2, 9, 1], [5, 5, 1], 12, 11, 1)
>>> test([9, 5, 5, 8, 2, 2, 18, 8, 3, 9, 4])
([5, 8, 2, 2, 8, 3, 9], [9, 5, 4, 18], 37, 36, 1)
>>> test([17, 15, 2, 18, 7, 20, 3, 20, 12, 7])
([18, 3, 20, 12, 7], [17, 15, 2, 7, 20], 60, 61, 1)
>>> test([19, 8, 9, 1, 14, 1, 16, 4, 15, 5])
([19, 9, 14, 4], [8, 1, 1, 16, 15, 5], 46, 46, 0)