1
votes

Python itertools permutations sans répétitions

J'ai une chaîne qui montre le pas dans la grille m x n comme ce problème: https://leetcode.com/problems/unique-paths/

('R', 'D', 'R', 'D')
('R', 'D', 'D', 'R')
('D', 'R', 'R', 'D')
('D', 'D', 'R', 'R')
('D', 'R', 'D', 'R')
('R', 'R', 'D', 'D')


11 commentaires

im obtenant une liste vide en utilisant itertools.permutations (step, 4) , peut-être que vous vouliez dire step = list ('DDRR')


Avez-vous essayé itertools.combinations () ?


@zamir désolé, j'ai édité ma question, l'étape est une chaîne pas une liste


@Daniel J'ai essayé des combinaisons, des combinaisons_with_replacement, des permutations et des produits aussi, mais je ne peux pas obtenir exactement ce que je veux


Je soupçonne que tout algorithme pour calculer les permutations sans répétition ne sera pas plus efficace (peut-être moins efficace) que les itertools et la méthode set que vous mentionnez dans votre question, donc probablement pas la peine de vous inquiéter à moins que vous n'utilisiez des chaînes beaucoup plus longues. .


@SimonN Combien de temps? Pour DDDDDRRRRR il y a déjà 3,6 millions de permutations mais seulement 252 différentes, donc une méthode raisonnable ne produisant que ces dernières ne devrait pas avoir de mal à être plus rapide.


Vous voulez donc calculer le nombre de combinaisons distinctes de disposer exactement (m-1) D symboles et (n-1) R , ou de manière équivalente n R < / code> symboles avec (m-1) barres | entre eux. (Vous n'avez pas besoin de calculer les combinaisons réelles, et pour m, n jusqu'à 100, ce serait prohibitif). Le nombre de façons est donné par la célèbre formule Stars-and-Bars


Tagué combinatoire


@SimonN: c'est totalement incorrect, rappelez-vous que C (n, k) est de l'ordre de O (2 ^ n), vous allez donc gaspiller la mémoire et le processeur très rapidement pour les valeurs non-jouets de n. [Souvenez-vous de l'identité que [somme (C (n, k)) sur k] = 2 ^ n]


@smci ouais, c'est exactement ce que je veux, mais je veux savoir comment nous pouvons le faire facilement (en codage) parce que je pense que c'est un problème courant.


Est-ce que cela répond à votre question? permutations avec des valeurs uniques


4 Réponses :


-2
votes

Essayez d'utiliser itertools.combinationss (étape, 4) au lieu de itertools.permutations (étape, 4)


4 commentaires

itertools.combinationss (step, 4) renverra uniquement ('D', 'D', 'R', 'R')


utilisez ceci alors, itertools.combinations_with_replacement (étape, 4)


J'ai essayé des combinaisons, des combinaisons_with_replacement, des permutations et des produits également, mais je ne peux pas obtenir exactement ce que je veux


Non. itertools.permutations énumère toutes les permutations (avec des tonnes de doublons), mais c'est exagéré.



2
votes

Le problème du code leet ne demande que le nombre de chemins uniques, pas une liste de chemins uniques, donc pour calculer le nombre, il vous suffit d'utiliser la formule de combinaison de C (n, k) = n! / (k! x (n - k)!) pour trouver le nombre de positions où les D s (ou R ) peuvent être placés hors de tout positions:

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

pour que f (3, 2) renvoie: 3

et que f (7, 3) renvoie: 28

En revanche, si vous souhaitez produire une liste de chemins uniques, vous pouvez utiliser itertools.combinations pour faire la même chose que ci-dessus; autrement dit, pour trouver les positions où les D (ou R ) peuvent être placés hors de toutes les positions:

print(*f(7, 3), sep='\n')

pour que:

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))

renvoie:

from math import factorial

def f(m, n):
    return factorial(m + n - 2) / factorial(m - 1) / factorial(n - 1)


0 commentaires

2
votes

De toute façon, c'est une solution terriblement inefficace. Calculez simplement le nombre directement:

math.comb(m + n - 2, m - 1)


2 commentaires

Notez que math.comb n'est disponible que dans Python 3.8+.


@blhsing Oui, et LeetCode exécute 3.8.1.



3
votes

Pour obtenir la réponse dont vous avez besoin, vous pouvez utiliser multiset_permutations

>>> from math import factorial
>>> factorial(4)//(factorial(2)*factorial(2))
6

Pour obtenir uniquement le nombre total, utilisez la factorielle du nombre d'éléments divisé par le produit des factorielles pour le nombre de chaque élément unique. Ici, il y a 2 D et 2 R

>>> 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']]


0 commentaires