Start with a work queue containing (any, any, ..., any), 0 . The elements of this queue will be pairs consisting of a combination and several elements on the left that cannot be changed with any (this will make sense in the near future). Until the work queue is empty, remove one item from it and calculate the corresponding amount. If it does not meet the threshold, cancel it. Otherwise, report it as one of the desired combinations. For each any that can be changed, for each value in this column it puts a combination of the current one with any replaced by this value, while the index blocks all previous any values.
Given an output-sensitive estimate, this is within the polynomial optimal coefficient (in the general case, there can be exponentially many combinations).
In Python 3:
def overthreshold(data, threshold): queue = [(('any',) * len(data[0][0]), 0)] for combination, begin in queue: if sum(row[1] for row in data if all(x in {'any', y} for x, y in zip(combination, row[0]))) < threshold: continue yield combination for i in range(begin, len(combination)): if combination[i] == 'any': queue.extend((combination[:i] + (x,) + combination[i+1:], i + 1) for x in {row[0][i] for row in data}) def demo(): data = [ (('dog', 'house1', 'green'), 30), (('dog', 'house1', 'blue'), 15), (('cat', 'house1', 'green'), 20), (('cat', 'house2', 'red'), 5), (('turtle', 'house3', 'green'), 50), ] for combination in overthreshold(data, 50): print(combination)