Reputation: 63
I have a string show the step going in m x n grid like this problem: https://leetcode.com/problems/unique-paths/
step = 'DDRR'
D mean go Down and R mean go to Right I want to show permutations without replacement, and i found the itertools built-in on Python.But it's say:
Elements are treated as unique based on their position, not on their value. So if the input elements are unique, there will be no repeat values.
So that when I using itertools.permutation(step,4), it's contain many replications.
>>> itertools.permutations(step,4)
('D', 'D', 'R', 'R')
('D', 'R', 'D', 'R')
('D', 'R', 'R', 'D')
('D', 'R', 'D', 'R')
('D', 'R', 'R', 'D')
('D', 'D', 'R', 'R')
('D', 'D', 'R', 'R')
('D', 'R', 'D', 'R')
('D', 'R', 'R', 'D')
('D', 'R', 'D', 'R')
('D', 'R', 'R', 'D')
('R', 'D', 'D', 'R')
('R', 'D', 'R', 'D')
('R', 'D', 'D', 'R')
('R', 'D', 'R', 'D')
('R', 'R', 'D', 'D')
('R', 'R', 'D', 'D')
('R', 'D', 'D', 'R')
('R', 'D', 'R', 'D')
('R', 'D', 'D', 'R')
('R', 'D', 'R', 'D')
('R', 'R', 'D', 'D')
('R', 'R', 'D', 'D')
I want something like:
('R', 'D', 'R', 'D')
('R', 'D', 'D', 'R')
('D', 'R', 'R', 'D')
('D', 'D', 'R', 'R')
('D', 'R', 'D', 'R')
('R', 'R', 'D', 'D')
I found some answer using set(itertools.permutations(step,4)), but because apply set() method, the itertools.permutation() method still calculate all possibilities. Is there anyway to avoid it, or is there any built-in function can do permutation without repetitions in Python?
Upvotes: 1
Views: 4452
Reputation: 6573
To get the answer you need, you could use multiset_permutations
>>> from sympy.utilities.iterables import multiset_permutations
>>> from pprint import pprint
>>> pprint(list(multiset_permutations(['D','D','R','R'])))
[['D', 'D', 'R', 'R'],
['D', 'R', 'D', 'R'],
['D', 'R', 'R', 'D'],
['R', 'D', 'D', 'R'],
['R', 'D', 'R', 'D'],
['R', 'R', 'D', 'D']]
To get just the total number, use factorial of number of items divided by the product of factorials for the count of each unique item. Here there are 2 D's and 2 R's
>>> from math import factorial
>>> factorial(4)//(factorial(2)*factorial(2))
6
Upvotes: 6
Reputation: 106543
The leetcode problem only asks about the number of unique paths, not a list of unique paths, so to calculate the number you only need to use the combination formula of C(n, k) = n! / (k! x (n - k)!)
to find the number of positions where D
s (or R
s) can be placed out of all positions:
from math import factorial
def f(m, n):
return factorial(m + n - 2) / factorial(m - 1) / factorial(n - 1)
so that f(3, 2)
returns: 3
and that f(7, 3)
returns: 28
On the other hand, if you're interested in producing a list of unique paths, you can use itertools.combinations
to do the same as above; that is, to find the positions where D
s (or R
s) can be placed out of all positions:
from itertools import combinations
def f(m, n):
for positions in map(set, combinations(range(m + n - 2), m - 1)):
yield ''.join('DR'[i in positions] for i in range(m + n - 2))
so that:
print(*f(7, 3), sep='\n')
outputs:
RRRRRRDD
RRRRRDRD
RRRRRDDR
RRRRDRRD
RRRRDRDR
RRRRDDRR
RRRDRRRD
RRRDRRDR
RRRDRDRR
RRRDDRRR
RRDRRRRD
RRDRRRDR
RRDRRDRR
RRDRDRRR
RRDDRRRR
RDRRRRRD
RDRRRRDR
RDRRRDRR
RDRRDRRR
RDRDRRRR
RDDRRRRR
DRRRRRRD
DRRRRRDR
DRRRRDRR
DRRRDRRR
DRRDRRRR
DRDRRRRR
DDRRRRRR
Upvotes: 3
Reputation: 27588
It's a terribly inefficient solution anyway. Just compute the number directly:
math.comb(m + n - 2, m - 1)
Upvotes: 3
Reputation: 337
Try using itertools.combinationss(step,4) instead of itertools.permutations(step,4)
Upvotes: -2