Python’s combinations and combinations with replacement
A recent Stack Overflow question had me looking at how to find a list of four numbers each from -1 to 1 that sum up to 1.
Problem statement
Generate every combination of four numbers(a.k.a. quadruplets) from (-1, -0.99, -0.98, ..., 0.98, 0.99, 1)
that sum up to 1. Repetitions of numbers are allowed.
For example:
[0, 1, 0.12, -0.12], [0, 0, 0.5, 0.5], [1, 1, -1, 0]...
.
Solution using Python combination
I assume there will be only a set of unique lists that we should compute. This assumption drives me to use Python’s combination method to get a list of quadruplets from a list of numbers from -1.0
to +1.0
which sum up to 1.
Operating floating numbers are complex, so I multiplied the target sum with 100 and made integer calculations. I created a list from -100
to +100
and repeated the elements four times as the problem allowed repetitions of numbers. Later on, I made a list of quadruplets which sum is equal to 100. Finally, I divided each element by 100 to meet the problem statement.
So far, the code looks like the following snippet:
import csv
from itertools import combinations
def get_four_numbers(target_sum=100):
result = []
ar = list(range(-100, 101, 1)) * 4
for quadruplet in combinations(ar, 4):
if sum(quadruplet) == target_sum:
result.append([i / 100.0 for i in quadruplet])
return result
if __name__ == "__main__":
with open("output.csv", "w") as output_file:
csv_writer = csv.writer(output_file)
csv_writer.writerows(get_four_numbers())
Solution using Python combination
Later on, I found another method from the itertools
module called combination with replacement. This will allow me to get the targeted quadruplets without repeating the iterable list ar
four times manually. Updating the above snippet, we now have a much cleaner code with the same output quadruplets:
import csv
from itertools import combinations_with_replacement
def get_four_numbers(target_sum=100):
result = []
ar = list(range(-100, 101, 1))
for quadruplet in combinations_with_replacement(ar, 4):
if sum(quadruplet) == target_sum:
result.append([i / 100.0 for i in quadruplet])
return result
if __name__ == "__main__":
with open("output.csv", "w") as output_file:
csv_writer = csv.writer(output_file)
csv_writer.writerows(get_four_numbers())
Output from output.csv
(truncated due to filesize):
-1.0,0.0,1.0,1.0
-1.0,0.01,0.99,1.0
-1.0,0.02,0.98,1.0
-1.0,0.02,0.99,0.99
-1.0,0.03,0.97,1.0
-1.0,0.03,0.98,0.99
-1.0,0.04,0.96,1.0
.....
Reference
- Python official documentation on combination method
- Python official documentation on combination with replacement method
- Stackoverflow question: Four numbers each from -1 to 1 that sum up to 1
Advertisement