2

This is related to this question, but I also want the corresponding complement ordered list that contains the element not chosen in an efficient way using python or c++. For example, with an ordered list list=(0,1,1,2,3,3) when we choose 3 elements, one possible return pair should be (0,1,3) and (1,2,3). Additionally, I want the function to return a total of C(n,k) terms, so that the pair (0,1,3) and (1,2,3) should repeat 4 times in the returned result.

Full example of a short input: define a function foo(list,k), then foo([0,1,1],1) should return a list r of length C(3,1)=3,

r(0)=[[0],[1,1]] (choose 0, complement list is [1,1])
r(1)=[[1],[0,1]] (choose first 1, complement list is [0,1])
r(2)=[[1],[0,1]] (choose second 1, complement list is [0,1])
Community
  • 1
  • 1
egwene sedai
  • 383
  • 3
  • 15
  • i'm not sure i understand, maybe add some examples or explanation. For example what exactly is the "*complement ordered list*"? What exactly does this mean "when we choose 3 elements, one possible return pair should be (0,1,3) and (1,2,3)"? – Nikos M. Mar 11 '15 at 16:27
  • I added an example according to your suggestions. The complement list is a list containing the element not chosen. – egwene sedai Mar 11 '15 at 16:33

2 Answers2

2

You can use a basic combinations-algorithm, with the exception that it returns a tuple: the elements that are "in" and those that are "out". Then just recursively generate combinations for the rest of the list and add the first element to either the "in" or the "out" list, respectively.

Here's some Python code:

def comb_and_comp(lst, n):
    # no combinations
    if len(lst) < n:
        return
    # trivial 'empty' combination
    if n == 0 or lst == []:
        yield [], lst
    else:
        first, rest = lst[0], lst[1:]
        # combinations that contain the first element
        for in_, out in comb_and_comp(rest, n - 1):
            yield [first] + in_, out
        # combinations that do not contain the first element
        for in_, out in comb_and_comp(rest, n):
            yield in_, [first] + out

This will create both the "in" and "out" lists in one go, instead of creating the complement in a second pass.

tobias_k
  • 74,298
  • 11
  • 102
  • 155
1

Ok then use the algorithm here to generate all combinations of k over n and then use this algorithm to get the complementary list

(assume that the combination is given in indices and not actual values) for your example this would be:

foo([0,1,1],1) // i.e indices are [0,1,2] with values [0,1,1]
r(0)=[[0],[1,2]] (choose 0, complement list is [1,2])
r(1)=[[1],[0,2]] (choose first 1, complement list is [0,2])
r(2)=[[1],[0,1]] (choose second 1, complement list is [0,1])

The algorithm is (adapted from this post):

def complement(n, k, combination):
    # assume the combination values/indices are given in ascending order (i.e lexicographic)
    complement = []
    i=0 
    j=0 
    while i < n:
        if j >= k or i<combination[j]: complement.append(i)
        else: j+=1
        i+=1
    return complement
Community
  • 1
  • 1
Nikos M.
  • 6,741
  • 3
  • 27
  • 38
  • Which algorithm/implementation in https://stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n do you mean exactly? – moi Oct 23 '19 at 17:25
  • @moi, oops sorry I misread your comment and referring to another answer. Actually it doesn matter which algorithm one will choose as long as it generates combinations of k over n. Choose one that suits you, although being able to generate the indexes instead of only ther values is a requirement – Nikos M. Oct 25 '19 at 11:22