Related
I wanted to build a dice Stats Simulator in Python. The idea is that you have a starting array, containing [1,...,1] for the lowest possible dice rolls, a one. I already have one example for 4d4 and this works so I want my code to do it for every combination. So I wrote Variables and Functions, for recursive use. But it gives me an output, which is not right and much too high. Maybe somebody can help me and if you need explanation, then you can ask.
sides = 4
rolls = 4
constant = sides**rolls
beginningtable = []
for i in range(rolls):
beginningtable.append(1)
values = {rolls : 0}
check = True
print("-------------")
def checking(valuetable):
print(valuetable)
sum = 0
checker = 0
for i in valuetable:
sum = sum + i
for i in values.keys():
if sum == i:
values[i] = values [i] + 1
checker = 1
if checker == 0:
values[sum] = 1
def gothroughindex(table, index):
checking(table)
for i in range(sides-1):
table[index] += 1
checking(table)
return table
def loop(looptable, loopcounter):
for i in range(loopcounter):
if i != (loopcounter-1):
looptable[i] = 1
else:
looptable[i] += 1
return looptable
def recursiveloop(table,counter, loopvalue):
if counter == rolls:
for i in range(rolls):
print("\ncounter == counter\n")
recursiveloop(table, counter-1, loopvalue-1)
table = loop(table, loopvalue)
elif counter == 1:
for i in range(rolls-1):
print("\ncounter == 1\n")
print(loopvalue)
gothroughindex(table, 0)
table = loop(table, loopvalue+1)
else:
for i in range(rolls):
print("\nelse\n")
print(str(loopvalue) + " here I am")
recursiveloop(table, counter-1, loopvalue-1)
gothroughindex(table, 0)
table = loop(table, loopvalue)
def mainthing(maintable):
counter = rolls
loopvalue = rolls
recursiveloop(maintable, counter, loopvalue)
"""
for i in range(rolls): #Das sind die ersten vier
for i in range(rolls): #Das sind die ersten drei
for i in range(rolls-1): #Das sind die ersten beiden
gothroughindex(maintable, 0)
maintable = loop(maintable, 2)
gothroughindex(maintable, 0)
maintable = loop(maintable, 3)
maintable = loop(maintable, 4)
"""
print("---------")
print(maintable)
print(values)
sum = 0
for i in values.keys():
sum = values[i] + sum
print(sum)
mainthing(beginningtable)
Couldnt you just simplyfiy all this and use itertools product method to generate these?
generate a range for the number of sides of the dice, and then use that as the iterator for product to pick from. specify the number of dice as the repeat so that product will generate that many items
you can read more on itertools here https://docs.python.org/3/library/itertools.html#itertools.product
itertools.product(*iterables, repeat=1)
Cartesian product of input
iterables.
To compute the product of an iterable with itself, specify the number
of repetitions with the optional repeat keyword argument. For example,
product(A, repeat=4) means the same as product(A, A, A, A).
from itertools import product
def roll_combos(num_dice, num_sides):
return product(range(1, num_sides + 1), repeat=num_dice)
print(list(roll_combos(2, 3)))
print(list(roll_combos(4, 4)))
OUTPUT
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
[(1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3), (1, 1, 1, 4), (1, 1, 2, 1), (1, 1, 2, 2), (1, 1, 2, 3), (1, 1, 2, 4), (1, 1, 3, 1), (1, 1, 3, 2), (1, 1, 3, 3), (1, 1, 3, 4), (1, 1, 4, 1), (1, 1, 4, 2), (1, 1, 4, 3), (1, 1, 4, 4), (1, 2, 1, 1), (1, 2, 1, 2), (1, 2, 1, 3), (1, 2, 1, 4), (1, 2, 2, 1), (1, 2, 2, 2), (1, 2, 2, 3), (1, 2, 2, 4), (1, 2, 3, 1), (1, 2, 3, 2), (1, 2, 3, 3), (1, 2, 3, 4), (1, 2, 4, 1), (1, 2, 4, 2), (1, 2, 4, 3), (1, 2, 4, 4), (1, 3, 1, 1), (1, 3, 1, 2), (1, 3, 1, 3), (1, 3, 1, 4), (1, 3, 2, 1), (1, 3, 2, 2), (1, 3, 2, 3), (1, 3, 2, 4), (1, 3, 3, 1), (1, 3, 3, 2), (1, 3, 3, 3), (1, 3, 3, 4), (1, 3, 4, 1), (1, 3, 4, 2), (1, 3, 4, 3), (1, 3, 4, 4), (1, 4, 1, 1), (1, 4, 1, 2), (1, 4, 1, 3), (1, 4, 1, 4), (1, 4, 2, 1), (1, 4, 2, 2), (1, 4, 2, 3), (1, 4, 2, 4), (1, 4, 3, 1), (1, 4, 3, 2), (1, 4, 3, 3), (1, 4, 3, 4), (1, 4, 4, 1), (1, 4, 4, 2), (1, 4, 4, 3), (1, 4, 4, 4), (2, 1, 1, 1), (2, 1, 1, 2), (2, 1, 1, 3), (2, 1, 1, 4), (2, 1, 2, 1), (2, 1, 2, 2), (2, 1, 2, 3), (2, 1, 2, 4), (2, 1, 3, 1), (2, 1, 3, 2), (2, 1, 3, 3), (2, 1, 3, 4), (2, 1, 4, 1), (2, 1, 4, 2), (2, 1, 4, 3), (2, 1, 4, 4), (2, 2, 1, 1), (2, 2, 1, 2), (2, 2, 1, 3), (2, 2, 1, 4), (2, 2, 2, 1), (2, 2, 2, 2), (2, 2, 2, 3), (2, 2, 2, 4), (2, 2, 3, 1), (2, 2, 3, 2), (2, 2, 3, 3), (2, 2, 3, 4), (2, 2, 4, 1), (2, 2, 4, 2), (2, 2, 4, 3), (2, 2, 4, 4), (2, 3, 1, 1), (2, 3, 1, 2), (2, 3, 1, 3), (2, 3, 1, 4), (2, 3, 2, 1), (2, 3, 2, 2), (2, 3, 2, 3), (2, 3, 2, 4), (2, 3, 3, 1), (2, 3, 3, 2), (2, 3, 3, 3), (2, 3, 3, 4), (2, 3, 4, 1), (2, 3, 4, 2), (2, 3, 4, 3), (2, 3, 4, 4), (2, 4, 1, 1), (2, 4, 1, 2), (2, 4, 1, 3), (2, 4, 1, 4), (2, 4, 2, 1), (2, 4, 2, 2), (2, 4, 2, 3), (2, 4, 2, 4), (2, 4, 3, 1), (2, 4, 3, 2), (2, 4, 3, 3), (2, 4, 3, 4), (2, 4, 4, 1), (2, 4, 4, 2), (2, 4, 4, 3), (2, 4, 4, 4), (3, 1, 1, 1), (3, 1, 1, 2), (3, 1, 1, 3), (3, 1, 1, 4), (3, 1, 2, 1), (3, 1, 2, 2), (3, 1, 2, 3), (3, 1, 2, 4), (3, 1, 3, 1), (3, 1, 3, 2), (3, 1, 3, 3), (3, 1, 3, 4), (3, 1, 4, 1), (3, 1, 4, 2), (3, 1, 4, 3), (3, 1, 4, 4), (3, 2, 1, 1), (3, 2, 1, 2), (3, 2, 1, 3), (3, 2, 1, 4), (3, 2, 2, 1), (3, 2, 2, 2), (3, 2, 2, 3), (3, 2, 2, 4), (3, 2, 3, 1), (3, 2, 3, 2), (3, 2, 3, 3), (3, 2, 3, 4), (3, 2, 4, 1), (3, 2, 4, 2), (3, 2, 4, 3), (3, 2, 4, 4), (3, 3, 1, 1), (3, 3, 1, 2), (3, 3, 1, 3), (3, 3, 1, 4), (3, 3, 2, 1), (3, 3, 2, 2), (3, 3, 2, 3), (3, 3, 2, 4), (3, 3, 3, 1), (3, 3, 3, 2), (3, 3, 3, 3), (3, 3, 3, 4), (3, 3, 4, 1), (3, 3, 4, 2), (3, 3, 4, 3), (3, 3, 4, 4), (3, 4, 1, 1), (3, 4, 1, 2), (3, 4, 1, 3), (3, 4, 1, 4), (3, 4, 2, 1), (3, 4, 2, 2), (3, 4, 2, 3), (3, 4, 2, 4), (3, 4, 3, 1), (3, 4, 3, 2), (3, 4, 3, 3), (3, 4, 3, 4), (3, 4, 4, 1), (3, 4, 4, 2), (3, 4, 4, 3), (3, 4, 4, 4), (4, 1, 1, 1), (4, 1, 1, 2), (4, 1, 1, 3), (4, 1, 1, 4), (4, 1, 2, 1), (4, 1, 2, 2), (4, 1, 2, 3), (4, 1, 2, 4), (4, 1, 3, 1), (4, 1, 3, 2), (4, 1, 3, 3), (4, 1, 3, 4), (4, 1, 4, 1), (4, 1, 4, 2), (4, 1, 4, 3), (4, 1, 4, 4), (4, 2, 1, 1), (4, 2, 1, 2), (4, 2, 1, 3), (4, 2, 1, 4), (4, 2, 2, 1), (4, 2, 2, 2), (4, 2, 2, 3), (4, 2, 2, 4), (4, 2, 3, 1), (4, 2, 3, 2), (4, 2, 3, 3), (4, 2, 3, 4), (4, 2, 4, 1), (4, 2, 4, 2), (4, 2, 4, 3), (4, 2, 4, 4), (4, 3, 1, 1), (4, 3, 1, 2), (4, 3, 1, 3), (4, 3, 1, 4), (4, 3, 2, 1), (4, 3, 2, 2), (4, 3, 2, 3), (4, 3, 2, 4), (4, 3, 3, 1), (4, 3, 3, 2), (4, 3, 3, 3), (4, 3, 3, 4), (4, 3, 4, 1), (4, 3, 4, 2), (4, 3, 4, 3), (4, 3, 4, 4), (4, 4, 1, 1), (4, 4, 1, 2), (4, 4, 1, 3), (4, 4, 1, 4), (4, 4, 2, 1), (4, 4, 2, 2), (4, 4, 2, 3), (4, 4, 2, 4), (4, 4, 3, 1), (4, 4, 3, 2), (4, 4, 3, 3), (4, 4, 3, 4), (4, 4, 4, 1), (4, 4, 4, 2), (4, 4, 4, 3), (4, 4, 4, 4)]
This is the array I require:
N = 6
A = [[x,y,z] for x in range(N+1) for y in range(N+1) for z in range(N+1) if x+y+z== N]
Is there any other way of doing this by only specifying the variable N and 3 instead of x,y,z?
I tried []*3 but can't get the required output.
You are looking for iterttols.product:
from itertools import product
N = 6
A = [(x,y,z) for x in range(N+1) for y in range(N+1) for z in range(N+1) if x+y+z== N]
B = [tup for tup in product(range(N+1), repeat=3) if sum(tup) == N]
print(A, B, A == B, sep='\n')
Gives:
[(0, 0, 6), (0, 1, 5), (0, 2, 4), (0, 3, 3), (0, 4, 2), (0, 5, 1), (0, 6, 0), (1, 0, 5), (1, 1, 4), (1, 2, 3), (1, 3, 2), (1, 4, 1), (1, 5, 0), (2, 0, 4), (2, 1, 3), (2, 2, 2), (2, 3, 1), (2, 4, 0), (3, 0, 3), (3, 1, 2), (3, 2, 1), (3, 3, 0), (4, 0, 2), (4, 1, 1), (4, 2, 0), (5, 0, 1), (5, 1, 0), (6, 0, 0)]
[(0, 0, 6), (0, 1, 5), (0, 2, 4), (0, 3, 3), (0, 4, 2), (0, 5, 1), (0, 6, 0), (1, 0, 5), (1, 1, 4), (1, 2, 3), (1, 3, 2), (1, 4, 1), (1, 5, 0), (2, 0, 4), (2, 1, 3), (2, 2, 2), (2, 3, 1), (2, 4, 0), (3, 0, 3), (3, 1, 2), (3, 2, 1), (3, 3, 0), (4, 0, 2), (4, 1, 1), (4, 2, 0), (5, 0, 1), (5, 1, 0), (6, 0, 0)]
True
Use itertools.combinations_with_replacement:
from itertools import combinations_with_replacement
n = 6
k = 3
# If you want a list of tuples:
lst = [item for item in list(combinations_with_replacement(range(n), k)) if sum(item) == n]
print(lst)
# [(0, 1, 5), (0, 2, 4), (0, 3, 3), (1, 1, 4), (1, 2, 3), (2, 2, 2)]
# If you want a list of lists:
lst = [list(item) for item in list(combinations_with_replacement(range(n), k)) if sum(item) == n]
print(lst)
# [[0, 1, 5], [0, 2, 4], [0, 3, 3], [1, 1, 4], [1, 2, 3], [2, 2, 2]]
Input list
[(1, 0, 3), '21:40:44', (1, 3, 9), (1, 4, 6), '.273']
[(1, 0, 3), '21:43:37', (1, 3, 9), (1, 4, 6), '.060']
[(1, 0, 3), '21:45:27', (1, 3, 9), (1, 4, 6), '.410']
And the result should be like:
[(1, 0, 3), ['21:40:44', '21:43:37', '21:45:27'], (1, 3, 9), (1, 4, 6), ['.273', '.060', '.410']
The goal is to reduce the duplicates, the unique elements in a column should be stored in a list.
How about using zip. It will merge the 3 list and give you output with duplicates. later use set to remove duplicates. and since you don not want list of tuple for single element only, use list(set(x))[0] if len(set(x))==1 else list(set(x))
a=[(1, 0, 3), '21:40:44', (1, 3, 9), (1, 4, 6), '.273']
b=[(1, 0, 3), '21:43:37', (1, 3, 9), (1, 4, 6), '.060']
c=[(1, 0, 3), '21:45:27', (1, 3, 9), (1, 4, 6), '.410']
l=[list(set(x))[0] if len(set(x))==1 else list(set(x)) for x in list(zip(a,b,c))]
print(l)
>>>[(1, 0, 3), ['21:45:27', '21:40:44', '21:43:37'], (1, 3, 9), (1, 4, 6), ['.060', '.273', '.410']]
the simplest way is this:
in_data = [
[(1, 0, 3), '21:40:44', (1, 3, 9), (1, 4, 6), '.273'],
[(1, 0, 3), '21:43:37', (1, 3, 9), (1, 4, 6), '.060'],
[(1, 0, 3), '21:45:27', (1, 3, 9), (1, 4, 6), '.410']
]
res = []
for i in range(len(in_data[0])):
data = list(set([x[i] for x in in_data ]))
data = data[0] if len(data) == 1 else data
res.append(data)
print(res)
>>> [(1, 0, 3), ['21:43:37', '21:40:44', '21:45:27'], (1, 3, 9), (1, 4, 6), ['.273', '.060', '.410']]
I want to know how to randomly pick k items from a list of n size for ALL possible combinations.
For example, let A = [1, 2, 3, 4] and K = 3. Then it should return [1, 2, 3], [1, 2, 4], [1, 3, 4], and [2, 3, 4].
You are looking for itertools.combinations. For example:
>>> my_list = A = [1, 2, 3, 4]
>>> k = 3
>>> from itertools import combinations
>>> list(combinations(my_list, k))
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
If the ordering inside the results matters you might use itertools.permutations to get all permutations as well - putting them into a set removes duplicates stemming from duplicate numbers in your list
import itertools
n = 3
my_list = [1, 2, 3, 2 ,1]
print( set(itertools.permutations(my_list, n))) # or list, see below
Output:
{(1, 2, 1), (3, 1, 2), (2, 3, 2), (1, 3, 2), (3, 1, 1), (3, 2, 1), (1, 2, 2),
(1, 1, 3), (2, 2, 1), (2, 1, 1), (1, 3, 1), (2, 3, 1), (1, 2, 3), (1, 1, 2), ...}
# with set: 17 items
[(1, 2, 3), (1, 2, 2), (1, 2, 1), (1, 3, 2), (1, 3, 2), (1, 3, 1), (1, 2, 2),
(1, 2, 3), (1, 2, 1), (1, 1, 2), (1, 1, 3), (1, 1, 2), (2, 1, 3), (2, 1, 2), ...]
# with list: 60 items
Difference between permutations and combinations:
# permutations - based on all values on any position in the resulttuple
[(1, 2, 3), (1, 2, 2), (1, 2, 1), (1, 3, 2), (1, 3, 2), (1, 3, 1), (1, 2, 2), (1
, 2, 3), (1, 2, 1), (1, 1, 2), (1, 1, 3), (1, 1, 2), (2, 1, 3), (2, 1, 2), (2, 1
, 1), (2, 3, 1), (2, 3, 2), (2, 3, 1), (2, 2, 1), (2, 2, 3), (2, 2, 1), (2, 1, 1
), (2, 1, 3), (2, 1, 2), (3, 1, 2), (3, 1, 2), (3, 1, 1), (3, 2, 1), (3, 2, 2),
(3, 2, 1), (3, 2, 1), (3, 2, 2), (3, 2, 1), (3, 1, 1), (3, 1, 2), (3, 1, 2), (2,
1, 2), (2, 1, 3), (2, 1, 1), (2, 2, 1), (2, 2, 3), (2, 2, 1), (2, 3, 1), (2, 3,
2), (2, 3, 1), (2, 1, 1), (2, 1, 2), (2, 1, 3), (1, 1, 2), (1, 1, 3), (1, 1, 2)
, (1, 2, 1), (1, 2, 3), (1, 2, 2), (1, 3, 1), (1, 3, 2), (1, 3, 2), (1, 2, 1), (
1, 2, 2), (1, 2, 3)]
# combinations - based on position in source list not on value order in tuple preserved
[(1, 2, 3), (1, 2, 2), (1, 2, 1), (1, 3, 2), (1, 3, 1), (1, 2, 1), (2, 3, 2), (2
, 3, 1), (2, 2, 1), (3, 2, 1)]
Press any key to continue . . .
Lets say I have a list of values
my_list = [1,2,3,4]
I user itertools.permutations to find all combinations of this list
perms = itertools.permutations(my_list)
Which creates
[(1, 2, 3, 4),
(1, 2, 4, 3),
(1, 3, 2, 4),
(1, 3, 4, 2),
(1, 4, 2, 3),
(1, 4, 3, 2),
(2, 1, 3, 4),
(2, 1, 4, 3),
(2, 3, 1, 4),
(2, 3, 4, 1),
(2, 4, 1, 3),
(2, 4, 3, 1),
(3, 1, 2, 4),
(3, 1, 4, 2),
(3, 2, 1, 4),
(3, 2, 4, 1),
(3, 4, 1, 2),
(3, 4, 2, 1),
(4, 1, 2, 3),
(4, 1, 3, 2),
(4, 2, 1, 3),
(4, 2, 3, 1),
(4, 3, 1, 2),
(4, 3, 2, 1)]
I begin iterating through this and find that I no longer need any items in perms which begin with (4,1... or (3,1....
How can I recreate this list with those specific omissions? Iterating through and removing items is not viable as this needs to scale to very large sizes.
EDIT: For clarification (4,1,2,3) should be removed as it starts with (4,1...), but not (4,2,1,3) as it starts with (4,2...).
>>> from itertools import permutations
>>> my_list = [1,2,3,4]
>>> perms = permutations(my_list)
>>> perms
<itertools.permutations object at 0x107a63ad0>
>>> perms = filter(lambda x: x[:2] != (4,1) and x[:2] != (3,1), perms)
>>> perms
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
Since you state
Iterating through and removing items is not viable as this needs to
scale to very large sizes.
The best is to wrap the interator produced by permutations that will generate the tuples you want and skip the tuples you do not want:
my_list = [1,2,3,4]
def my_perms(my_list, f):
for e in permutations(my_list):
if f(e):
yield e
>>> list(my_perms(my_list, lambda t: t[:2] not in {(4,1), (3,1)}))
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
Or, use ifilter from itertools:
>>> list(ifilter(lambda t: t[:2] not in {(4,1), (3,1)}, permutations(my_list)))
Or, filter directly on Python 3+ since that also creates an iterator vs creating a list as filter on Python 2 does.
You can use a list comprehension to get the expected permutations :
>>> [i for i in perms if i[0] not in {3,4}]
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1)]
Note that using a set container has O(1) for check the membership.and it would be more efficient if you have more filter numbers!
If you don't want the tuples that starts with 3,1 and 4,1 you can just simply do :
>>> perms = it.permutations(my_list)
>>> [i for i in perms if i[:2] !=[4,1] and i[:2] !=[4,1]]
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
>>>