2009-09-22 8 views
3

J'avais une mission combinatoire qui consistait à obtenir chaque mot de longueur inférieure ou égale à 6 à partir d'une combinaison spécifique de chaînes.Obtenir toutes les combinaisons de chaînes

Dans ce cas, c'était S = {'a', 'ab', 'ba'}. Le professeur a juste commencé à les énumérer, mais je pensais que ce serait plus facile à résoudre avec un programme. Le seul problème est que je ne peux pas obtenir un bon algorithme qui calcule réellement toutes les options possibles.

Si quelqu'un pouvait aider, je l'apprécierais. Je programme habituellement en Python mais j'ai vraiment besoin d'aide avec l'algorithme.

+0

Êtes-vous lookin pour quelque chose comme ça? http://stackoverflow.com/questions/361/generate-list-of-all-possible-permutations-of-a-string –

+0

Pouvez-vous développer votre exemple? Est-il correct de choisir le même article plusieurs fois? – cmcginty

Répondre

8

Vous pouvez générer de façon itérative toutes les chaînes composées d'une partie, de deux parties, de trois parties, etc. jusqu'à ce que toutes les chaînes générées dans une étape dépassent six caractères. D'autres étapes ne généreraient que des chaînes encore plus longues, de sorte que toutes les chaînes courtes possibles ont déjà été générées. Si vous collectez ces chaînes courtes dans chaque étape, vous obtenez un ensemble de toutes les chaînes courtes générées possibles.

En Python:

S = set(['a', 'ab', 'ba']) 

collect = set() 
step = set(['']) 
while step: 
    step = set(a+b for a in step for b in S if len(a+b) <= 6) 
    collect |= step 

print sorted(collect) 
8

En supposant que vous ne signifie combinaisons (pas de répétitions, l'ordre n'a pas d'importance):

import itertools 

S = [ 'a', 'ab', 'ba' ] 

for i in range(len(S)+1): 
    for c in itertools.combinations(S, i): 
    cc = ''.join(c) 
    if len(cc) <= 6: 
     print c 

émet toutes les possibilités:

() 
('a',) 
('ab',) 
('ba',) 
('a', 'ab') 
('a', 'ba') 
('ab', 'ba') 
('a', 'ab', 'ba') 

Si vous voulez dire quelque chose de différent de « combinaisons », il est juste un problème d'utilisation du bon itérateur ou du bon générateur dans le for (par exemple, itertools.permutations, ou autre chose de votre propre conception).

Modifier: si par exemple vous dire « répétitions et l'ordre sont importantes »,

def reps(seq, n): 
    return itertools.product(*[seq]*n) 

for i in range(7): 
    for c in reps(S, i): 
    cc = ''.join(c) 
    if len(cc) <= 6: 
     print c 

vous donnera les 85 nécessaires lignes de production.

Éditer à nouveau: J'avais une mauvaise limite de boucle (et donc une mauvaise longueur de sortie) - tx pour le commentateur qui l'a signalé. En outre, cette approche peut produire une chaîne> 1 fois, si les '' .join de tuples différents sont considérés comme équivalents; par exemple, il produit ('a', 'ba') distinct de ('ab', 'a') bien que leur '' .join soit le même (même "mot" de différentes "combinaisons", je suppose - la terminologie utilisée n'est pas entièrement claire).

+0

Cela ne crée pas 6 combinaisons de lettres comme 'a' 'ab' 'ba' 'a' – Unknown

+0

Ce n'est pas une combinaison, puisque 'a' est répété. Le terme ** combinaisons ** a une signification extrêmement claire et non ambiguë en maths (et c'est exactement ce que met en œuvre itertools.combination) et dans une «mission combinatoire», il mendie la croyance qu'il pourrait être utilisé de manière maladroite, imprécise ou erronée. –

+0

La question est les chaînes d'une combinaison; pas de combinaisons d'un ensemble. –

1

Le faire est une façon récursive:

cache = {} 
def words_of_length(s, n=6): 
    # memoise results 
    if n in cache: return cache[n] 

    # base cases 
    if n < 0: return [] 
    if n == 0: return [""] 

    # inductive case 
    res = set() 
    for x in s: 
     res |= set((x+y for y in words_of_length(s, n-len(x)))) 

    # sort and memoise result 
    cache[n] = sorted(res) 

    # sort results 
    return cache[n] 

def words_no_longer_than(s, n=6): 
    return sum([words_of_length(s, i) for i in range(n+1)], []) 
3
def combos(S,n): 
    if (n <= 0): return 
    for s in S: 
     if len(s) <= n: yield s 
     for t in combos(S,n-len(s)): yield s+t 

for x in combos(["a","ab","ba"],6): print x 

sortie Prints:

a 
aa 
aaa 
aaaa 
aaaaa 
aaaaaa 
aaaaab 
aaaaba 
aaaab 
aaaaba 
aaaba 
aaabaa 
aaab 
aaaba 
aaabaa 
aaabab 
aaabba 
aaba 
aabaa 
aabaaa 
aabaab 
aababa 
aab 
aaba 
aabaa 
aabaaa 
aabaab 
aababa 
aabab 
aababa 
aabba 
aabbaa 
aba 
abaa 
abaaa 
abaaaa 
abaaab 
abaaba 
abaab 
abaaba 
ababa 
ababaa 
ab 
aba 
abaa 
abaaa 
abaaaa 
abaaab 
abaaba 
abaab 
abaaba 
ababa 
ababaa 
abab 
ababa 
ababaa 
ababab 
ababba 
abba 
abbaa 
abbaaa 
abbaab 
abbaba 
ba 
baa 
baaa 
baaaa 
baaaaa 
baaaab 
baaaba 
baaab 
baaaba 
baaba 
baabaa 
baab 
baaba 
baabaa 
baabab 
baabba 
baba 
babaa 
babaaa 
babaab 
bababa 
+0

Note qui donne la même chaîne plusieurs fois - par exemple, aba = a + ba = ab + a. –

Questions connexes