How to generate and filter efficiently all combinations of a list of list productHow do I check if a list is empty?How do I sort a list of dictionaries by a value of the dictionary?How to randomly select an item from a list?How do you split a list into evenly sized chunks?How to make a flat list out of list of listsHow do I get the number of elements in a list?How do I concatenate two lists in Python?How to clone or copy a list?How do I list all files of a directory?How to read a file line-by-line into a list?

I asked for a graduate student position from a professor. He replied "welcome". What does that mean?

What is and what isn't ullage in rocket science?

Were Roman public roads build by private companies?

Real mode flat model

Planar regular languages

Parallel resistance in electric circuits

Why did it become so much more expensive to start a university?

POSIX compatible way to get user name associated with a user ID

Newly created XFS filesystem shows 78 GB used

Relocation error involving libgnutls.so.30, error code (127) after last updates

How are unbalanced coaxial cables used for broadcasting TV signals without any problems?

Does my opponent need to prove his creature has morph?

Why do sellers care about down payments?

How are aircraft depainted?

Why did they ever make smaller than full-frame sensors?

Cannot find Database Mail feature in SQL Server Express 2012 SP1

2000s space film where an alien species has almost wiped out the human race in a war

What was the ultimate objective of The Party in 1984?

Diffraction of a wave passing through double slits

Can you add polynomial terms to multiple linear regression?

What is my breathable atmosphere composed of?

Will the UK home office know about 5 previous visa rejections in other countries?

getting syntax error in simple bash script

Telling my mother that I have anorexia without panicking her



How to generate and filter efficiently all combinations of a list of list product


How do I check if a list is empty?How do I sort a list of dictionaries by a value of the dictionary?How to randomly select an item from a list?How do you split a list into evenly sized chunks?How to make a flat list out of list of listsHow do I get the number of elements in a list?How do I concatenate two lists in Python?How to clone or copy a list?How do I list all files of a directory?How to read a file line-by-line into a list?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








0















Hello guys here is the problem. I have something like this in input [[1,2,3],[4,5,6],[7,8,9]]...etc



And i want to generate all possible combination of product of those list and then multiply each elements of the resulting combination beetween them to finally filter the result in a interval.



So first input a n list [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]...etc



Which will then give (1,4,7,10)
(1,4,7,11)
(1,4,7,12)
and so on



Then combination of those result for k in n like (1,4,7)(1,4,10)(1,7,10) for the first row



The multiplication of x as 1*4*7 = 28, 1*4*10 = 40, 1*7*10 = 70



And from this get only the unique combination and the result need in the interval choosed beforehand : if x > 50 and x < 100 i will get (1,7,10) : 70



I did try



 def mult(lst): #A function mult i'm using later
r = 1
for element in lst:
r *= element
return round(r)

s = [] #Where i add my list of list
for i in range(int(input1)):
b = input("This is line %s : " % (i+1)).split()
for i in range(len(b)):
b[i] = float(b[i])
s.append(b)

low_result = input("Expected low_result : ")
high_result = input("Expected high_result : ")

combine = []
my_list = []

for element in itertools.product(*s):
l= [float(x) for x in element]
comb = itertools.combinations([*l], int(input2))
for i in list(comb):
combine.append(i)
res = mult(i)
if res >= int(low_result) and res <= int(high_result):
my_list.append(res)
f = open("list_result.txt","a+")
f.write("%s : result is %sn" % (i, res))
f.close()


And it always result in memory error cause there is too many variation with what i'm seeking.



What i would like is a way to generate from a list of list of 20 elements or more all the product and resulting combination of k in n for the result(interval) that i need.










share|improve this question


























  • If you are looking for the AXBXCX... And then trying to take a subset dim = n-1 , might as well start with choosing (n-1) spaces? Or am I missing something ?

    – Born Tbe Wasted
    Mar 28 at 10:33











  • Try to replace the lists by generators, replace [] by () they will save you some memory

    – geckos
    Mar 28 at 10:41











  • Also [*l] is the same as l if l is a list

    – geckos
    Mar 28 at 10:42











  • And I think numpy will help you with some performance. But I'm not the Python numbers guy

    – geckos
    Mar 28 at 10:43











  • If i replace [] by () it won't do with the combination because it will give it too much argument no ?

    – Exramas
    Mar 28 at 11:50

















0















Hello guys here is the problem. I have something like this in input [[1,2,3],[4,5,6],[7,8,9]]...etc



And i want to generate all possible combination of product of those list and then multiply each elements of the resulting combination beetween them to finally filter the result in a interval.



So first input a n list [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]...etc



Which will then give (1,4,7,10)
(1,4,7,11)
(1,4,7,12)
and so on



Then combination of those result for k in n like (1,4,7)(1,4,10)(1,7,10) for the first row



The multiplication of x as 1*4*7 = 28, 1*4*10 = 40, 1*7*10 = 70



And from this get only the unique combination and the result need in the interval choosed beforehand : if x > 50 and x < 100 i will get (1,7,10) : 70



I did try



 def mult(lst): #A function mult i'm using later
r = 1
for element in lst:
r *= element
return round(r)

s = [] #Where i add my list of list
for i in range(int(input1)):
b = input("This is line %s : " % (i+1)).split()
for i in range(len(b)):
b[i] = float(b[i])
s.append(b)

low_result = input("Expected low_result : ")
high_result = input("Expected high_result : ")

combine = []
my_list = []

for element in itertools.product(*s):
l= [float(x) for x in element]
comb = itertools.combinations([*l], int(input2))
for i in list(comb):
combine.append(i)
res = mult(i)
if res >= int(low_result) and res <= int(high_result):
my_list.append(res)
f = open("list_result.txt","a+")
f.write("%s : result is %sn" % (i, res))
f.close()


And it always result in memory error cause there is too many variation with what i'm seeking.



What i would like is a way to generate from a list of list of 20 elements or more all the product and resulting combination of k in n for the result(interval) that i need.










share|improve this question


























  • If you are looking for the AXBXCX... And then trying to take a subset dim = n-1 , might as well start with choosing (n-1) spaces? Or am I missing something ?

    – Born Tbe Wasted
    Mar 28 at 10:33











  • Try to replace the lists by generators, replace [] by () they will save you some memory

    – geckos
    Mar 28 at 10:41











  • Also [*l] is the same as l if l is a list

    – geckos
    Mar 28 at 10:42











  • And I think numpy will help you with some performance. But I'm not the Python numbers guy

    – geckos
    Mar 28 at 10:43











  • If i replace [] by () it won't do with the combination because it will give it too much argument no ?

    – Exramas
    Mar 28 at 11:50













0












0








0


0






Hello guys here is the problem. I have something like this in input [[1,2,3],[4,5,6],[7,8,9]]...etc



And i want to generate all possible combination of product of those list and then multiply each elements of the resulting combination beetween them to finally filter the result in a interval.



So first input a n list [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]...etc



Which will then give (1,4,7,10)
(1,4,7,11)
(1,4,7,12)
and so on



Then combination of those result for k in n like (1,4,7)(1,4,10)(1,7,10) for the first row



The multiplication of x as 1*4*7 = 28, 1*4*10 = 40, 1*7*10 = 70



And from this get only the unique combination and the result need in the interval choosed beforehand : if x > 50 and x < 100 i will get (1,7,10) : 70



I did try



 def mult(lst): #A function mult i'm using later
r = 1
for element in lst:
r *= element
return round(r)

s = [] #Where i add my list of list
for i in range(int(input1)):
b = input("This is line %s : " % (i+1)).split()
for i in range(len(b)):
b[i] = float(b[i])
s.append(b)

low_result = input("Expected low_result : ")
high_result = input("Expected high_result : ")

combine = []
my_list = []

for element in itertools.product(*s):
l= [float(x) for x in element]
comb = itertools.combinations([*l], int(input2))
for i in list(comb):
combine.append(i)
res = mult(i)
if res >= int(low_result) and res <= int(high_result):
my_list.append(res)
f = open("list_result.txt","a+")
f.write("%s : result is %sn" % (i, res))
f.close()


And it always result in memory error cause there is too many variation with what i'm seeking.



What i would like is a way to generate from a list of list of 20 elements or more all the product and resulting combination of k in n for the result(interval) that i need.










share|improve this question
















Hello guys here is the problem. I have something like this in input [[1,2,3],[4,5,6],[7,8,9]]...etc



And i want to generate all possible combination of product of those list and then multiply each elements of the resulting combination beetween them to finally filter the result in a interval.



So first input a n list [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]...etc



Which will then give (1,4,7,10)
(1,4,7,11)
(1,4,7,12)
and so on



Then combination of those result for k in n like (1,4,7)(1,4,10)(1,7,10) for the first row



The multiplication of x as 1*4*7 = 28, 1*4*10 = 40, 1*7*10 = 70



And from this get only the unique combination and the result need in the interval choosed beforehand : if x > 50 and x < 100 i will get (1,7,10) : 70



I did try



 def mult(lst): #A function mult i'm using later
r = 1
for element in lst:
r *= element
return round(r)

s = [] #Where i add my list of list
for i in range(int(input1)):
b = input("This is line %s : " % (i+1)).split()
for i in range(len(b)):
b[i] = float(b[i])
s.append(b)

low_result = input("Expected low_result : ")
high_result = input("Expected high_result : ")

combine = []
my_list = []

for element in itertools.product(*s):
l= [float(x) for x in element]
comb = itertools.combinations([*l], int(input2))
for i in list(comb):
combine.append(i)
res = mult(i)
if res >= int(low_result) and res <= int(high_result):
my_list.append(res)
f = open("list_result.txt","a+")
f.write("%s : result is %sn" % (i, res))
f.close()


And it always result in memory error cause there is too many variation with what i'm seeking.



What i would like is a way to generate from a list of list of 20 elements or more all the product and resulting combination of k in n for the result(interval) that i need.







python python-3.x






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 28 at 10:26









Aran-Fey

20.8k5 gold badges45 silver badges84 bronze badges




20.8k5 gold badges45 silver badges84 bronze badges










asked Mar 28 at 10:26









ExramasExramas

32 bronze badges




32 bronze badges















  • If you are looking for the AXBXCX... And then trying to take a subset dim = n-1 , might as well start with choosing (n-1) spaces? Or am I missing something ?

    – Born Tbe Wasted
    Mar 28 at 10:33











  • Try to replace the lists by generators, replace [] by () they will save you some memory

    – geckos
    Mar 28 at 10:41











  • Also [*l] is the same as l if l is a list

    – geckos
    Mar 28 at 10:42











  • And I think numpy will help you with some performance. But I'm not the Python numbers guy

    – geckos
    Mar 28 at 10:43











  • If i replace [] by () it won't do with the combination because it will give it too much argument no ?

    – Exramas
    Mar 28 at 11:50

















  • If you are looking for the AXBXCX... And then trying to take a subset dim = n-1 , might as well start with choosing (n-1) spaces? Or am I missing something ?

    – Born Tbe Wasted
    Mar 28 at 10:33











  • Try to replace the lists by generators, replace [] by () they will save you some memory

    – geckos
    Mar 28 at 10:41











  • Also [*l] is the same as l if l is a list

    – geckos
    Mar 28 at 10:42











  • And I think numpy will help you with some performance. But I'm not the Python numbers guy

    – geckos
    Mar 28 at 10:43











  • If i replace [] by () it won't do with the combination because it will give it too much argument no ?

    – Exramas
    Mar 28 at 11:50
















If you are looking for the AXBXCX... And then trying to take a subset dim = n-1 , might as well start with choosing (n-1) spaces? Or am I missing something ?

– Born Tbe Wasted
Mar 28 at 10:33





If you are looking for the AXBXCX... And then trying to take a subset dim = n-1 , might as well start with choosing (n-1) spaces? Or am I missing something ?

– Born Tbe Wasted
Mar 28 at 10:33













Try to replace the lists by generators, replace [] by () they will save you some memory

– geckos
Mar 28 at 10:41





Try to replace the lists by generators, replace [] by () they will save you some memory

– geckos
Mar 28 at 10:41













Also [*l] is the same as l if l is a list

– geckos
Mar 28 at 10:42





Also [*l] is the same as l if l is a list

– geckos
Mar 28 at 10:42













And I think numpy will help you with some performance. But I'm not the Python numbers guy

– geckos
Mar 28 at 10:43





And I think numpy will help you with some performance. But I'm not the Python numbers guy

– geckos
Mar 28 at 10:43













If i replace [] by () it won't do with the combination because it will give it too much argument no ?

– Exramas
Mar 28 at 11:50





If i replace [] by () it won't do with the combination because it will give it too much argument no ?

– Exramas
Mar 28 at 11:50












1 Answer
1






active

oldest

votes


















1
















As suggested above, I think this can be done without exploding your memory by never holding an array in memory at any time. But the main issue is then runtime.



The maths



As written we are:



  • Producing every combination of m rows of n items n ** m

  • Then taking a choice of c items from those m values C(m, c)

This is very large. If we have m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** m * C(m, c)


  • = 3 ** 25 * 2300 - n Choose r calculator

  • = 1.948763802×10¹⁵

If instead we:



  • Choose c rows from the m rows: C(m, c) as before

  • Then pick every combination of n items from these c rows: n ** c

With m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** c * C(m, c)

  • = 3 ** 3 * 2300

  • = 20700

This is now a solvable problem.



The code



from itertools import product, combinations


def mult(values, min_value, max_value):
"""
Multiply together the values, but return None if we get too big or too
small
"""
output = 1

for value in values:
output *= value

# Early return if we go too big
if output > max_value:
return None

# Early return if we goto zero (from which we never return)
if output == 0 and min_value != 0:
return None

if output < min_value:
return None

return output


def yield_valid_combos(values, choose, min_value, max_value):
# No doubt an even fancier list compression would get this too
for rows in combinations(values, choose):
for combos in product(*rows):
value = mult(combos, min_value, max_value)

if value is not None:
yield combos, value


values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]


with open('list_result.txt', 'w') as fh:
for selection, value in yield_valid_combos(
values, choose=3, min_value=50, max_value=100):
fh.write(': result is n'.format(selection, value))


This solution also returns no duplicate answers (unless the same value appears in multiple rows).



As an optimisation the multiplication method attempts to return early if we detect the result will be too big or small. We also only open the file once and then keep adding rows to it as they come.



Further optimisation



You can also optimise your set of values ahead of time by screening out values which cannot contribute to a solution. But for smaller values of c, you may find this is not even necessary.



The smallest possible combination of values is c items from the set of the smallest values in each row. If we take the c - 1 smallest items from the set of smallest values, mutliply them together and then divide the maximum by this number, it gives us an upper bound for the largest value which can be in a solution. We can then then screen out all values above this value (cutting down on permutations)






share|improve this answer



























  • Sadly the values does not lokk like these more like [[1.16,6.3,12],[1.27,5.5,9],[2.42,3.3,2.85],[1.3,5.4,9.5],[2.78,3.35,2.32],[2.45,2,1.88]] up to maybe 25 element or more. That's why i'm really curious about the way you present at the end of your answer cause the time need for treating all those combination look near infinite no ?

    – Exramas
    Mar 28 at 12:50











  • It's possible to generalise the logic above for arbitrary values. If we collect the set of the smallest values from each set, we can create an upper bound for the largest value that can be a part of our solution by: removing the largest value from this set, multiplying the rest together, dividing our maximum by that value. We can then remove values from sets which are above this value. This will speed up the process as it cuts on permutations, but if we find any particular set is empty, we also know there is no solution before we start.

    – Jon Betts
    Mar 28 at 13:31











  • Ahh... sorry it's actually take the choose - 1 smallest values from the set of smallest values, then divide the max by that.

    – Jon Betts
    Mar 28 at 13:39











  • I think I've cracked it, the product and the choice should be the other way around... I'll update the answer.

    – Jon Betts
    Mar 28 at 14:03










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);














draft saved

draft discarded
















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55395280%2fhow-to-generate-and-filter-efficiently-all-combinations-of-a-list-of-list-produc%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1
















As suggested above, I think this can be done without exploding your memory by never holding an array in memory at any time. But the main issue is then runtime.



The maths



As written we are:



  • Producing every combination of m rows of n items n ** m

  • Then taking a choice of c items from those m values C(m, c)

This is very large. If we have m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** m * C(m, c)


  • = 3 ** 25 * 2300 - n Choose r calculator

  • = 1.948763802×10¹⁵

If instead we:



  • Choose c rows from the m rows: C(m, c) as before

  • Then pick every combination of n items from these c rows: n ** c

With m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** c * C(m, c)

  • = 3 ** 3 * 2300

  • = 20700

This is now a solvable problem.



The code



from itertools import product, combinations


def mult(values, min_value, max_value):
"""
Multiply together the values, but return None if we get too big or too
small
"""
output = 1

for value in values:
output *= value

# Early return if we go too big
if output > max_value:
return None

# Early return if we goto zero (from which we never return)
if output == 0 and min_value != 0:
return None

if output < min_value:
return None

return output


def yield_valid_combos(values, choose, min_value, max_value):
# No doubt an even fancier list compression would get this too
for rows in combinations(values, choose):
for combos in product(*rows):
value = mult(combos, min_value, max_value)

if value is not None:
yield combos, value


values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]


with open('list_result.txt', 'w') as fh:
for selection, value in yield_valid_combos(
values, choose=3, min_value=50, max_value=100):
fh.write(': result is n'.format(selection, value))


This solution also returns no duplicate answers (unless the same value appears in multiple rows).



As an optimisation the multiplication method attempts to return early if we detect the result will be too big or small. We also only open the file once and then keep adding rows to it as they come.



Further optimisation



You can also optimise your set of values ahead of time by screening out values which cannot contribute to a solution. But for smaller values of c, you may find this is not even necessary.



The smallest possible combination of values is c items from the set of the smallest values in each row. If we take the c - 1 smallest items from the set of smallest values, mutliply them together and then divide the maximum by this number, it gives us an upper bound for the largest value which can be in a solution. We can then then screen out all values above this value (cutting down on permutations)






share|improve this answer



























  • Sadly the values does not lokk like these more like [[1.16,6.3,12],[1.27,5.5,9],[2.42,3.3,2.85],[1.3,5.4,9.5],[2.78,3.35,2.32],[2.45,2,1.88]] up to maybe 25 element or more. That's why i'm really curious about the way you present at the end of your answer cause the time need for treating all those combination look near infinite no ?

    – Exramas
    Mar 28 at 12:50











  • It's possible to generalise the logic above for arbitrary values. If we collect the set of the smallest values from each set, we can create an upper bound for the largest value that can be a part of our solution by: removing the largest value from this set, multiplying the rest together, dividing our maximum by that value. We can then remove values from sets which are above this value. This will speed up the process as it cuts on permutations, but if we find any particular set is empty, we also know there is no solution before we start.

    – Jon Betts
    Mar 28 at 13:31











  • Ahh... sorry it's actually take the choose - 1 smallest values from the set of smallest values, then divide the max by that.

    – Jon Betts
    Mar 28 at 13:39











  • I think I've cracked it, the product and the choice should be the other way around... I'll update the answer.

    – Jon Betts
    Mar 28 at 14:03















1
















As suggested above, I think this can be done without exploding your memory by never holding an array in memory at any time. But the main issue is then runtime.



The maths



As written we are:



  • Producing every combination of m rows of n items n ** m

  • Then taking a choice of c items from those m values C(m, c)

This is very large. If we have m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** m * C(m, c)


  • = 3 ** 25 * 2300 - n Choose r calculator

  • = 1.948763802×10¹⁵

If instead we:



  • Choose c rows from the m rows: C(m, c) as before

  • Then pick every combination of n items from these c rows: n ** c

With m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** c * C(m, c)

  • = 3 ** 3 * 2300

  • = 20700

This is now a solvable problem.



The code



from itertools import product, combinations


def mult(values, min_value, max_value):
"""
Multiply together the values, but return None if we get too big or too
small
"""
output = 1

for value in values:
output *= value

# Early return if we go too big
if output > max_value:
return None

# Early return if we goto zero (from which we never return)
if output == 0 and min_value != 0:
return None

if output < min_value:
return None

return output


def yield_valid_combos(values, choose, min_value, max_value):
# No doubt an even fancier list compression would get this too
for rows in combinations(values, choose):
for combos in product(*rows):
value = mult(combos, min_value, max_value)

if value is not None:
yield combos, value


values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]


with open('list_result.txt', 'w') as fh:
for selection, value in yield_valid_combos(
values, choose=3, min_value=50, max_value=100):
fh.write(': result is n'.format(selection, value))


This solution also returns no duplicate answers (unless the same value appears in multiple rows).



As an optimisation the multiplication method attempts to return early if we detect the result will be too big or small. We also only open the file once and then keep adding rows to it as they come.



Further optimisation



You can also optimise your set of values ahead of time by screening out values which cannot contribute to a solution. But for smaller values of c, you may find this is not even necessary.



The smallest possible combination of values is c items from the set of the smallest values in each row. If we take the c - 1 smallest items from the set of smallest values, mutliply them together and then divide the maximum by this number, it gives us an upper bound for the largest value which can be in a solution. We can then then screen out all values above this value (cutting down on permutations)






share|improve this answer



























  • Sadly the values does not lokk like these more like [[1.16,6.3,12],[1.27,5.5,9],[2.42,3.3,2.85],[1.3,5.4,9.5],[2.78,3.35,2.32],[2.45,2,1.88]] up to maybe 25 element or more. That's why i'm really curious about the way you present at the end of your answer cause the time need for treating all those combination look near infinite no ?

    – Exramas
    Mar 28 at 12:50











  • It's possible to generalise the logic above for arbitrary values. If we collect the set of the smallest values from each set, we can create an upper bound for the largest value that can be a part of our solution by: removing the largest value from this set, multiplying the rest together, dividing our maximum by that value. We can then remove values from sets which are above this value. This will speed up the process as it cuts on permutations, but if we find any particular set is empty, we also know there is no solution before we start.

    – Jon Betts
    Mar 28 at 13:31











  • Ahh... sorry it's actually take the choose - 1 smallest values from the set of smallest values, then divide the max by that.

    – Jon Betts
    Mar 28 at 13:39











  • I think I've cracked it, the product and the choice should be the other way around... I'll update the answer.

    – Jon Betts
    Mar 28 at 14:03













1














1










1









As suggested above, I think this can be done without exploding your memory by never holding an array in memory at any time. But the main issue is then runtime.



The maths



As written we are:



  • Producing every combination of m rows of n items n ** m

  • Then taking a choice of c items from those m values C(m, c)

This is very large. If we have m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** m * C(m, c)


  • = 3 ** 25 * 2300 - n Choose r calculator

  • = 1.948763802×10¹⁵

If instead we:



  • Choose c rows from the m rows: C(m, c) as before

  • Then pick every combination of n items from these c rows: n ** c

With m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** c * C(m, c)

  • = 3 ** 3 * 2300

  • = 20700

This is now a solvable problem.



The code



from itertools import product, combinations


def mult(values, min_value, max_value):
"""
Multiply together the values, but return None if we get too big or too
small
"""
output = 1

for value in values:
output *= value

# Early return if we go too big
if output > max_value:
return None

# Early return if we goto zero (from which we never return)
if output == 0 and min_value != 0:
return None

if output < min_value:
return None

return output


def yield_valid_combos(values, choose, min_value, max_value):
# No doubt an even fancier list compression would get this too
for rows in combinations(values, choose):
for combos in product(*rows):
value = mult(combos, min_value, max_value)

if value is not None:
yield combos, value


values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]


with open('list_result.txt', 'w') as fh:
for selection, value in yield_valid_combos(
values, choose=3, min_value=50, max_value=100):
fh.write(': result is n'.format(selection, value))


This solution also returns no duplicate answers (unless the same value appears in multiple rows).



As an optimisation the multiplication method attempts to return early if we detect the result will be too big or small. We also only open the file once and then keep adding rows to it as they come.



Further optimisation



You can also optimise your set of values ahead of time by screening out values which cannot contribute to a solution. But for smaller values of c, you may find this is not even necessary.



The smallest possible combination of values is c items from the set of the smallest values in each row. If we take the c - 1 smallest items from the set of smallest values, mutliply them together and then divide the maximum by this number, it gives us an upper bound for the largest value which can be in a solution. We can then then screen out all values above this value (cutting down on permutations)






share|improve this answer















As suggested above, I think this can be done without exploding your memory by never holding an array in memory at any time. But the main issue is then runtime.



The maths



As written we are:



  • Producing every combination of m rows of n items n ** m

  • Then taking a choice of c items from those m values C(m, c)

This is very large. If we have m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** m * C(m, c)


  • = 3 ** 25 * 2300 - n Choose r calculator

  • = 1.948763802×10¹⁵

If instead we:



  • Choose c rows from the m rows: C(m, c) as before

  • Then pick every combination of n items from these c rows: n ** c

With m=25 rows, of n=3 items each and pick c=3 items in them we get:



  • = n ** c * C(m, c)

  • = 3 ** 3 * 2300

  • = 20700

This is now a solvable problem.



The code



from itertools import product, combinations


def mult(values, min_value, max_value):
"""
Multiply together the values, but return None if we get too big or too
small
"""
output = 1

for value in values:
output *= value

# Early return if we go too big
if output > max_value:
return None

# Early return if we goto zero (from which we never return)
if output == 0 and min_value != 0:
return None

if output < min_value:
return None

return output


def yield_valid_combos(values, choose, min_value, max_value):
# No doubt an even fancier list compression would get this too
for rows in combinations(values, choose):
for combos in product(*rows):
value = mult(combos, min_value, max_value)

if value is not None:
yield combos, value


values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]


with open('list_result.txt', 'w') as fh:
for selection, value in yield_valid_combos(
values, choose=3, min_value=50, max_value=100):
fh.write(': result is n'.format(selection, value))


This solution also returns no duplicate answers (unless the same value appears in multiple rows).



As an optimisation the multiplication method attempts to return early if we detect the result will be too big or small. We also only open the file once and then keep adding rows to it as they come.



Further optimisation



You can also optimise your set of values ahead of time by screening out values which cannot contribute to a solution. But for smaller values of c, you may find this is not even necessary.



The smallest possible combination of values is c items from the set of the smallest values in each row. If we take the c - 1 smallest items from the set of smallest values, mutliply them together and then divide the maximum by this number, it gives us an upper bound for the largest value which can be in a solution. We can then then screen out all values above this value (cutting down on permutations)







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 28 at 14:23

























answered Mar 28 at 12:00









Jon BettsJon Betts

1,5987 silver badges9 bronze badges




1,5987 silver badges9 bronze badges















  • Sadly the values does not lokk like these more like [[1.16,6.3,12],[1.27,5.5,9],[2.42,3.3,2.85],[1.3,5.4,9.5],[2.78,3.35,2.32],[2.45,2,1.88]] up to maybe 25 element or more. That's why i'm really curious about the way you present at the end of your answer cause the time need for treating all those combination look near infinite no ?

    – Exramas
    Mar 28 at 12:50











  • It's possible to generalise the logic above for arbitrary values. If we collect the set of the smallest values from each set, we can create an upper bound for the largest value that can be a part of our solution by: removing the largest value from this set, multiplying the rest together, dividing our maximum by that value. We can then remove values from sets which are above this value. This will speed up the process as it cuts on permutations, but if we find any particular set is empty, we also know there is no solution before we start.

    – Jon Betts
    Mar 28 at 13:31











  • Ahh... sorry it's actually take the choose - 1 smallest values from the set of smallest values, then divide the max by that.

    – Jon Betts
    Mar 28 at 13:39











  • I think I've cracked it, the product and the choice should be the other way around... I'll update the answer.

    – Jon Betts
    Mar 28 at 14:03

















  • Sadly the values does not lokk like these more like [[1.16,6.3,12],[1.27,5.5,9],[2.42,3.3,2.85],[1.3,5.4,9.5],[2.78,3.35,2.32],[2.45,2,1.88]] up to maybe 25 element or more. That's why i'm really curious about the way you present at the end of your answer cause the time need for treating all those combination look near infinite no ?

    – Exramas
    Mar 28 at 12:50











  • It's possible to generalise the logic above for arbitrary values. If we collect the set of the smallest values from each set, we can create an upper bound for the largest value that can be a part of our solution by: removing the largest value from this set, multiplying the rest together, dividing our maximum by that value. We can then remove values from sets which are above this value. This will speed up the process as it cuts on permutations, but if we find any particular set is empty, we also know there is no solution before we start.

    – Jon Betts
    Mar 28 at 13:31











  • Ahh... sorry it's actually take the choose - 1 smallest values from the set of smallest values, then divide the max by that.

    – Jon Betts
    Mar 28 at 13:39











  • I think I've cracked it, the product and the choice should be the other way around... I'll update the answer.

    – Jon Betts
    Mar 28 at 14:03
















Sadly the values does not lokk like these more like [[1.16,6.3,12],[1.27,5.5,9],[2.42,3.3,2.85],[1.3,5.4,9.5],[2.78,3.35,2.32],[2.45,2,1.88]] up to maybe 25 element or more. That's why i'm really curious about the way you present at the end of your answer cause the time need for treating all those combination look near infinite no ?

– Exramas
Mar 28 at 12:50





Sadly the values does not lokk like these more like [[1.16,6.3,12],[1.27,5.5,9],[2.42,3.3,2.85],[1.3,5.4,9.5],[2.78,3.35,2.32],[2.45,2,1.88]] up to maybe 25 element or more. That's why i'm really curious about the way you present at the end of your answer cause the time need for treating all those combination look near infinite no ?

– Exramas
Mar 28 at 12:50













It's possible to generalise the logic above for arbitrary values. If we collect the set of the smallest values from each set, we can create an upper bound for the largest value that can be a part of our solution by: removing the largest value from this set, multiplying the rest together, dividing our maximum by that value. We can then remove values from sets which are above this value. This will speed up the process as it cuts on permutations, but if we find any particular set is empty, we also know there is no solution before we start.

– Jon Betts
Mar 28 at 13:31





It's possible to generalise the logic above for arbitrary values. If we collect the set of the smallest values from each set, we can create an upper bound for the largest value that can be a part of our solution by: removing the largest value from this set, multiplying the rest together, dividing our maximum by that value. We can then remove values from sets which are above this value. This will speed up the process as it cuts on permutations, but if we find any particular set is empty, we also know there is no solution before we start.

– Jon Betts
Mar 28 at 13:31













Ahh... sorry it's actually take the choose - 1 smallest values from the set of smallest values, then divide the max by that.

– Jon Betts
Mar 28 at 13:39





Ahh... sorry it's actually take the choose - 1 smallest values from the set of smallest values, then divide the max by that.

– Jon Betts
Mar 28 at 13:39













I think I've cracked it, the product and the choice should be the other way around... I'll update the answer.

– Jon Betts
Mar 28 at 14:03





I think I've cracked it, the product and the choice should be the other way around... I'll update the answer.

– Jon Betts
Mar 28 at 14:03








Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.







Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.




















draft saved

draft discarded















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55395280%2fhow-to-generate-and-filter-efficiently-all-combinations-of-a-list-of-list-produc%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript