0

I want to find an efficient way for computer to handle LARGE NUMBER OF VARIABLES (say 50: x1, ... , x50) that do something like this: find ALL combinations [x1,x2,x3] satisfying:

  1. 0 <= x1 <= x2 <= x3

  2. x1 + x2 + x3 = 100

Here is an example of finding all combinations with sum = 100 but [1,99] and [99,1] are considered to be different here:

x=[]
for i, j in itertools.product(range(0,101), range(0,101)):
    if i+j==100:
       x.append([i,j])

I want to find a way to reduce the number of loops and give only things like:

[0,100], [1,99], [2,98], .........., [50,50]

And nothing from [51,49].

The main goal is doing this with 50 variables (x_1,...x_50) which sums up to 100.

It is not likely to do it with normal loop

lrh09
  • 557
  • 4
  • 13
  • How many is a "large number"? – kindall Feb 11 '18 at 05:54
  • Can you think of a faster way to find a `j` for a given `i` such that `i + j == 100`? – Ry- Feb 11 '18 at 05:58
  • possible duplicate of [Finding all possible combinations of numbers to reach a given sum](https://stackoverflow.com/questions/4632322/finding-all-possible-combinations-of-numbers-to-reach-a-given-sum) – avigil Feb 11 '18 at 06:00
  • @avigil: This problem is not as hard as that one. (And it isn’t about subsets of {1, …, 100}.) – Ry- Feb 11 '18 at 06:06
  • You can try `list(itertools.chain(*[((i,100-i),(100-i,i)) if i!=100-i else ((i,i),) for i in range(51)]))` – Sohaib Farooqi Feb 11 '18 at 06:11
  • @kindall about 50-80 variables to sum up to 100, that's huge – lrh09 Feb 11 '18 at 06:21
  • @avigil it is definitely not a duplicate, because I have viewed and try the approach. The answers proposed there can only handle small number of recursions. I used it for my purpose, it gives:RecursionError: maximum recursion depth exceeded in comparison – lrh09 Feb 11 '18 at 06:22
  • its a case of the [subset sum problem](https://en.wikipedia.org/wiki/Subset_sum_problem) – avigil Feb 11 '18 at 06:24
  • @Ryan it isn't about subset, it can be repeated. But the number of total combinations that makes things like [100,0] and [0,100] different with 53 variables is 1.742x10^41 combinations. Need optimization to handle it – lrh09 Feb 11 '18 at 06:25
  • in this context, subset does not mean the numbers can't repeat, only that we are taking slices of the original set of numbers and finding groups that sum to the desired value. – avigil Feb 11 '18 at 06:29
  • Your question says the `{x_i}` are non-negative integers. Hence this is an ***integer partition*** problem. (Not a subset sum problem, which involves negative and positive integers). – smci Feb 11 '18 at 06:32
  • ok fair enough- I was thinking too broadly (subset sum is the generalized version of partition problem) – avigil Feb 11 '18 at 06:47
  • @lrh09: I’ll give you a hint: `j = 100 - i`. Then you can do the rest as nested loops (or equivalent) in time proportional to the size of the list, which is as good as it’s going to get as long as you’re asking for the results in a list. – Ry- Feb 11 '18 at 07:04
  • hey guys, @Ryan and others... Please look at the question and think of the nested loops of 50 variables. i, j are simple. – lrh09 Feb 11 '18 at 07:26
  • You can do it using a recursive function. You can even copy and paste a loop 50 times. Very little difference as long as you need that list. – Ry- Feb 11 '18 at 07:28
  • @Ryan, if you are able to get sum of 50 variables combinations to 100 in 1 week using your computer. Write your code here :) Thanks – lrh09 Feb 11 '18 at 07:33
  • As I was saying, it takes time proportional to the size of the list, and that’s as good as it’s going to get as long as you’re asking for the results in a list. With 50, the list is too big to fit in memory. So are you sure you’re actually required to *list* them, or do you just need some fact about the collection? – Ry- Feb 11 '18 at 08:21
  • @Irh09 pls check my answer, i optimized the multiple loops to the best i can into a recursive function – Albin Paul Feb 11 '18 at 08:21

2 Answers2

1

For 3 variables of form i+j+k==100 we need two for loops and for n variables we need n-1 for loops to produce the result

for i in range(0,101):
    for j in range(i,101):
        if(100-j-i>=j):
            print i,j,100-j-i

Result

0 0 100
0 1 99
0 2 98
0 3 97
0 4 96
0 5 95
......
......
32 33 35
32 34 34
33 33 34

Edit 1

or if you dont want to write the code for n-1 loops use this recurisive function and it will be faster as i did some optimization to reduce its runtime

def foo(numberofvariables,sumofvar):
    templist=[0]*(numberofvariables)

    def fun(depthofrecursion,tempsum,sumofvar,var):

        if(depthofrecursion<numberofvariables-1):
            for i in range(var,(sumofvar/(numberofvariables-depthofrecursion)+2)):

                templist[depthofrecursion]=i;
                fun(depthofrecursion+1,tempsum+i,sumofvar,i)
        else:

            if(sumofvar-tempsum>=var):
                templist[numberofvariables-1]=sumofvar-tempsum
                for i in range(0,numberofvariables):
                    print templist[i],

                print 

    fun(0,0,sumofvar,0)

foo(3,100)

here the n is 3 (number of variables)and sum is 100 produces the same output as above

Albin Paul
  • 3,330
  • 2
  • 14
  • 30
1

what about combinaison ??

import random
from itertools import combinations
l = random.sample(range(1, 10000), 100)

alist =[(x1,x2,x3) if  (0 <= x1 <= x2 <= x3 and sum([x1,x2,x3]) == 100) else None for x1,x2,x3 in combinations(sorted(l), 3)]
L = list(filter(None, alist))

output

[(1, 4, 95),
 (1, 7, 92),
 (1, 10, 89),
 (1, 12, 87),
 (1, 17, 82),
 (1, 18, 81),
 (1, 30, 69),
 (1, 32, 67),
 (1, 34, 65),
 (1, 38, 61),
 (1, 49, 50),
 (2, 3, 95),
 (2, 5, 93),
 (2, 7, 91),
 (2, 10, 88),
 (2, 12, 86),
 (2, 17, 81),
 (2, 18, 80),
 (2, 22, 76),
 (2, 30, 68),
 (2, 33, 65),
 (3, 4, 93),
 (3, 5, 92),
 (3, 7, 90),
 (3, 10, 87),
 (3, 12, 85),
 (3, 17, 80),
Espoir Murhabazi
  • 5,973
  • 5
  • 42
  • 73
  • your codes don't work... you may copy paste and try it yourself – lrh09 Feb 11 '18 at 07:38
  • I think you mean `list(filter(lambda x: x is not None, alist))`. – avigil Feb 11 '18 at 07:39
  • which version of python are you using ?? – Espoir Murhabazi Feb 11 '18 at 07:40
  • @avigil yes or anyway to remove None values from a list – Espoir Murhabazi Feb 11 '18 at 07:41
  • there is a problem with this if the input is not sorted ascending because for example `combinations(range(100,0, -1), 3)` will throw out all possible answers – avigil Feb 11 '18 at 07:45
  • @avigil isn't the list L=[ ]? I just ran it and got this. Regardless where L is empty or not, I get the idea. But try this on 5/6 variables, you will get stuck there long enough. I am looking for 50 variables here, please read the problem. – lrh09 Feb 11 '18 at 09:20
  • @irh09, your problem has a large time complexity, and it will take a lot of time, let me update the answer explaining the time complexity – Espoir Murhabazi Feb 11 '18 at 09:25