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?
CodePudding user response:
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)
CodePudding user response:
The other answer doesn't try to meet the requirements in the table (apart from the exclusion of a joint occurrence of h
and i
). 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()
CodePudding user response:
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)]