I have the following task: Let us have a list (denoted by L, and for simplicity, the elements come from the interval [0,1]). We are given a parameter (denoted by C), and we want to find as many pairs as we cane (without using the same element twice) in our list, whose difference is at most C.
Example: For the input L=[0, 0.2, 0.4, 0.5, 0.6, 1] and C=0.2, my output should be [0, 0.2] and [0.4, 0.5]. If I had C=0.1, the output would be [0.4, 0.5], and with C=0.4, the output would also contain the pair [0.6, 1]. Getting a single solution is enough, as I know that there are more possible partitions. Note: the input list is not necessary sorted, therefore the pairs don't need to be adjacent.
This is the code that I have created. It tries to search all the possible partitions, then filter the good 2-partitions. As far as I know, it gives the correct solution. My only problem is the runtime: if the list is larger than 20 elements, I can't get the output in a normal time.
def partition(collection):
if len(collection) == 1:
yield [ collection ]
return
first = collection[0]
for smaller in partition(collection[1:]):
# insert `first` in each of the subpartition's subsets
for n, subset in enumerate(smaller):
yield smaller[:n] + [[ first ] + subset] + smaller[n+1:]
# put `first` in its own subset
yield [ [ first ] ] + smaller
def filter_partition(partition):
for elem in partition:
if len(elem) not in (1, 2):
return False
return True
def get_good_partitions(lista, C):
lista = lista.tolist()
all_partitions = list(partition(lista))
two_partitions = [p for p in all_partitions if filter_partition(p)]
max_pairs = 0
ret = []
for p in two_partitions:
is_ok = 0
for elem in p:
if len(elem) > 1:
diff = abs(elem[0] - elem[1])
if diff <= C or math.isclose(diff, C):
is_ok += 1
if is_ok > max_pairs:
max_pairs = is_ok
ret = p
return [elem for elem in ret if len(elem) == 2 and math.isclose(abs(elem[0] - elem[1]), C) or abs(elem[0] - elem[1]) <= C]
#test
L = numpy.array([random.uniform(0, 1) for _ in range(8)])
C = 0.1
res = get_good_partitions(L, C)
print(res)
C=0.1
, since0.6 - 0.5 == 0.1
(0.5 - 0.4
might also be, but that's not guaranteed in the usual IEEE-754 floating-point). Also, is the input list expected to be sorted? Do the pairs have to be adjacent elements, or can they be non-adjacent? \$\endgroup\$