Calculate all the possible sums of rolling x die with y sides - python

I'm writing a function that helps me calculate the possible outcomes of summing a variable numbe of die with a variable number of sides (for instance, the total sum of two six-sided die and a four sided die) and I've been stumped for a while.
Rolling two three sided die for instance should output an array with all 9 possible combinations:
[[1,1],
[1,2],
[1,3],
[2,1],
(etc.)
[3,2],
[3,3]]
And I can't quite figure it out. I've managed to generate range to enumerate on, but I can't quite make it.
dice = [6,6]
diceRanges = [range(0, die) for die in dice]
diceIndex = [0 for die in dice]
outcomes = []
for idx, rng in enumerate(diceRanges):
for var in rng:
diceIndex[idx] = var
outcomes.append([val for val in diceIndex])
outcomes
I've seen some things around but never quite as simple as it seems to be.
Cheers

It's simple if you use itertools:
import itertools
outcomes = list(itertools.product(*diceRanges))

Using numpy only
dice_sides = 6
dices_values = np.arange(1,dice_sides+1)
outcome = np.dstack(np.meshgrid(dices_values, dices_values)).reshape(-1,2)
Out[313]:
array([[1, 1],
[2, 1],
[3, 1],
[4, 1],
[5, 1],
[6, 1],
[1, 2],
[2, 2],
[3, 2],
[4, 2],
[5, 2],
[6, 2],
[1, 3],
[2, 3],
[3, 3],
[4, 3],
[5, 3],
[6, 3],
[1, 4],
[2, 4],
[3, 4],
[4, 4],
[5, 4],
[6, 4],
[1, 5],
[2, 5],
[3, 5],
[4, 5],
[5, 5],
[6, 5],
[1, 6],
[2, 6],
[3, 6],
[4, 6],
[5, 6],
[6, 6]])

Related

Faster and more pythonic way to reproduce unique set of unordered random numbers inside nested list

I wanted to create a domino game. I'm in the beginning of my journey to become a python dev.
I have made enough progress but I'm wondering if i could refactor my unique set generator function more elegant - pythonic and shorter.
This is my function and i think it is working as it should be. All the other functions in the program are depended on this.
The main job of the function is creating a list of unique set of two random numbers (0-6(including)) range and all of those lists are inside a list.
For ex. [1,2] and [2,1] are the same and should appear only once in the final array.
from random import randrange
length = 28
def unique_set_generator(set_size):
unique_set = set()
main_set = []
while len(unique_set) != set_size:
x, y = randrange(7), randrange(7)
if (x, y) not in unique_set and (y, x) not in unique_set:
unique_set.add((x, y))
set_to_list = list(unique_set)
for i in range(set_size):
main_set.append(list(set_to_list[i]))
return main_set
print(unique_set_generator(length))
Outcome:
[[4, 3], [5, 4], [2, 2], [1, 0], [1, 3], [6, 5], [4, 2], [3, 3], [5, 0], [3, 6], [5, 3], [1, 2], [0, 4], [1, 5], [6, 1], [6, 4], [3, 2], [5, 2], [4, 4], [5, 5], [0, 0], [1, 1], [0, 3], [2, 0], [1, 4], [2, 6], [6, 0], [6, 6]]
Use the tools Python provides:
import random
dominos = [(i,j) for i in range(7) for j in range(i,7)]
print(dominos)
random.shuffle(dominos)
print(dominos)

How can I sort the lists in the list?

I'd like to know how to sort the lists in the list. However, I don't want to align by key. I'd like to change it according to the following method.
arr = [[2, 3], [5, 1], [4, 1], [5, 3], [4, 2]]
# solution...
I_want_arr = [[2, 3], [1, 5], [1, 4], [3, 5], [2, 4]]
i tried it
for i in arr:
i.sort()
but, it didn't work
using list comprehenstion:
arr = [[2, 3], [5, 1], [4, 1], [5, 3], [4, 2]]
sorted_output = [sorted(l) for l in arr]
using map():
sorted_output = list(map(sorted, arr))
#Gabip's solution includes this and a more time efficient one, check that out first!
How about
arr = [[2, 3], [5, 1], [4, 1], [5, 3], [4, 2]]
I_want_arr = [sorted(x) for x in arr]
This outputs
[[2, 3], [1, 5], [1, 4], [3, 5], [2, 4]]

Can I "rotate" and slice in one numpy operation?

I have data like this:
[[[1, 2, 3]
[4, 5, 6]]
[[7, 8, 9]
[0, 1, 2]]]
and I need to get it into this "shape":
[[[1, 4], [2, 5], [3, 6]]
[[7, 0], [8, 1], [9, 2]]]
The best method I have for doing this so far is:
for i in range(2):
pairs = tuple(
array[i, :, j] for j in range(3) # ---axis-2-length---
)
print(pairs)
to produce:
([1, 4], [2, 5], [3, 6])
([7, 0], [8, 1], [9, 2])
While this gets the job done, that's a lot of interpreted Python, especially as these datasets grow. So I was wondering if I could somehow get this done with fancy indexing or transposition or something else my numpy-fu is not yet strong enough to conceive of myself.
Does anyone know how to get this done more elegantly with numpy?
Transposition with ndarray.transpose will work here.
>>> x.transpose(0, 2, 1)
array([[[1, 4],
[2, 5],
[3, 6]],
[[7, 0],
[8, 1],
[9, 2]]])

How do I make each list in the list of lists sort in ascending order?

I have the following lists:
[[1, 5], [3, 7], [4, 2], [7, 8], [6, 3], [2, 5], [4, 1]]
And I am trying to sort them by the first value, after making the list go in ascending order:
Desired output:
[[1, 4], [1, 5], [2, 4], [2, 5], [3, 6], [3, 7], [7, 8]]
However, list.sort() only gives the following:
>>> mylist = [[1, 5], [3, 7], [4, 2], [7, 8], [6, 3], [2, 5], [4, 1]]
>>> mylist.sort()
>>> mylist
[[1, 5], [2, 5], [3, 7], [4, 1], [4, 2], [6, 3], [7, 8]]
>>>
Of course, I could always loop each list in the list of lists and sort it:
>>> mylist
[[1, 5], [2, 5], [3, 7], [4, 1], [4, 2], [6, 3], [7, 8]]
>>> for k in range(len(mylist)):
... mylist[k] = sorted(mylist[k])
...
>>> mylist
[[1, 5], [2, 5], [3, 7], [1, 4], [2, 4], [3, 6], [7, 8]]
>>> sorted(mylist)
[[1, 4], [1, 5], [2, 4], [2, 5], [3, 6], [3, 7], [7, 8]]
But is there a one liner to solve this?
You can do:
sorted(sorted(sublist) for sublist in mylist)
This is a little better than your loop:
for sublist in mylist:
sublist.sort()
mylist.sort()
Of course, this changes each sublist in-place. Judging by your examples, it looks like that is what you want, but I thought I should mention it just in case.
Here is a one liner that does the sort in-place
>>> mylist = [[1, 5], [3, 7], [4, 2], [7, 8], [6, 3], [2, 5], [4, 1]]
>>> mylist.sort(key=lambda x:x.sort() or x)
>>> mylist
[[1, 4], [1, 5], [2, 4], [2, 5], [3, 6], [3, 7], [7, 8]]

declaring and initialising 2d array in python

I am declaring multidimensional array in python
Nbrs[23][2] = [[1, 1], [1, 2], [2, 1],
[2, 3], [3, 2], [1, 3],
[3, 1], [1, 4], [3, 4],
[4, 3], [4, 1], [1, 5],
[2, 5], [3, 5], [4, 5],
[5, 4], [5, 3], [5, 2],
[5, 1], [1, 6], [5, 6],
[6, 5], [6, 1]
]
It gives me error as:
NameError: name 'Nbrs' is not defined
I cannot declare 2 dimensional array in python by this way?
Assignment statement:
Nbrs[23][2] = [[1, 1], [1, 2], [2
# ^ ^ you can't index Nbrs before it created
should be:
Nbrs = [[1, 1], [1, 2], [2
# now after this statement, Nbrs a list of list you can access
# its elements useng `Nbrs[i][j]` for i < len(Nbrs) and j < 2
I think you confuses because of C, C++ declarations!
You don't need to specify the dimensions when defining lists in python. When you type Nbrs[23][2] python is trying to find what's at [23][2] in Nbrs but in this case Nbrs doesn't exist because you are trying to define it for the first time here.
Instead do this:
Nbrs = [[1, 1], [1, 2], [2, 1], ....
That's not the right syntax. You don't need to include anything about the variable's type on the left-hand side; in particular, drop the dimensions.
Nbrs = [[1, 1], [1, 2], [2, 1], [2, 3], [3, 2], [1, 3], [3, 1], [1, 4], [3, 4], [4, 3], [4, 1], [1, 5], [2, 5], [3, 5], [4, 5], [5, 4], [5, 3], [5, 2], [5, 1], [1, 6], [5, 6], [6, 5], [6, 1]]
What you've written tries to assign to an element of Nbrs, which doesn't exist yet.

Categories

Resources