import random
import itertools
method_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
random.shuffle(method_list)
per = list(itertools.permutations(method_list, 4))
for ele in per:
ss = set(list(ele))
if len(ss) == 4:
if not ('h' in ss and 'i' in ss):
result.append(ss)
I want to make a total of 250 random combinations by taking 4 elements from my list.
like this:
{'c', 'b', 'd', 'a'}, {'c', 'e', 'b', 'a'}, {'c', 'b', 'f', 'a'}, {'c', 'b', 'g', 'a'}...
| no | name | count |
|---|---|---|
| 1 | a | 160 |
| 2 | b | 160 |
| 3 | c | 160 |
| 4 | d | 160 |
| 5 | e | 160 |
| 6 | f | 50 |
| 7 | g | 50 |
| 8 | h | 50 |
| 9 | i | 50 |
| 1000 |
But I don’t know how to make a combination that matches the number of elements according to the criteria in the table above.
The criteria are as follows.
- No duplicate alphabets in a combination.
- h and i are not in the same combination.
- total of 250 combinations while meeting the number of elements.
can anyone help me?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
The other answers don’t try to meet the requirements in the table (only the exclusion of a joint occurrence of h and i), which I see as the main challenge of the question. My answer also doesn’t do that exactly, only approximately:
from random import choices pop_1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] pop_2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i'] weights = [80, 80, 80, 80, 80, 25, 25, 50] combos_1 = [choices(pop_1, weights=weights, k=4) for _ in range(125)] combos_2 = [choices(pop_2, weights=weights, k=4) for _ in range(125)] combos = combos_1 + combos_2
The random.choices() function chooses randomly (without replacement) from a population, and accepts a weights sequence (which serves as kind of a preference for the choosing). So, as I said, this doesn’t solve your problem exactly, only approximately (the larger the sample size, the smaller the relative error). The result looks like:
part a b c d e f g h i sum -------- --- --- --- --- --- --- --- --- --- ----- combos_1 74 85 71 92 88 20 21 49 0 500 combos_2 71 90 81 74 78 24 28 0 54 500 combos 145 175 152 166 166 44 49 49 54 1000
If you want to make sure that there are only unique combinations, then this would be better:
combos = set()
while len(combos) < 250:
combos.add(tuple(choices(pop_1, weights=weights, k=4)))
combos.add(tuple(choices(pop_2, weights=weights, k=4)))
if len(combos) == 251:
combos.pop()
Method 2
Use this:
import random
result = list()
for _ in range(250):
x = random.sample(method_list,4)
if x.count('h')>0 and x.count('i')>0:
pass
else:
result.append(x)
print(result)
Method 3
The random library could be avoided if using set properly, since returns always an unordered collection of terms. The counting part can be delegate to Counter from the collections library.
import collections as cl
import itertools as it
l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
exclude = set('hi')
combinations = []
combinations = list(set(c for c in it.permutations(l, 4) if not exclude <= set(c)))[:250]
counter = cl.Counter(l)
counter.update(it.chain(*combinations))
counter_ordered_by_key = sorted(counter.items(), key=lambda c: c[0])
print(counter_ordered_by_key)
# [('a', 120), ('b', 128), ('c', 114), ('d', 110), ('e', 121), ('f', 131), ('g', 121), ('h', 79), ('i', 85)]
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0