8

For example, I might want to generate all length n=6 words on the alphabet {A, B, C} that have one A, three B's and two C's. An example of such a word is: 'ABBBCC'. I'd like to generate all such words.

I've already tried generating all permutations of a particular string (like 'ABBBCC') and deleting all duplicates. This is too slow for my purposes.

rm -rf
  • 88,781
  • 21
  • 293
  • 472
rjkaplan
  • 1,083
  • 1
  • 8
  • 15

1 Answers1

8

Permutations is already duplicate-aware:

Permutations[{"A", "A", "B"}]
{{"A", "A", "B"}, {"A", "B", "A"}, {"B", "A", "A"}}

Perhaps you are looking for combinations of a particular length (which can then be permuted). One way to get those is this:

f[k_, {}, c__] := If[+c == k, {{c}}, {}]

f[k_, {x_, r___}, c___] := Join @@ (f[k, {r}, c, #] & /@ 0~Range~Min[x, k - +c])

Use:

f[4, {1, 3, 2}]
{{0, 2, 2}, {0, 3, 1}, {1, 1, 2}, {1, 2, 1}, {1, 3, 0}}

These represent the words of length 4 for a list with unique items repeated, 1, 3, and 2 times at most.

You can then construct the actual words from these lists, e.g.:

char = {"A", "B", "C"};

StringJoin@MapThread[ConstantArray, {char, #}] & /@ f[4, {1, 3, 2}]
{"BBCC", "BBBC", "ABCC", "ABBC", "ABBB"}

Or:

Inner[#2 ~Table~ {#} &, f[4, {1, 3, 2}], char, StringJoin]
{"BBCC", "BBBC", "ABCC", "ABBC", "ABBB"}

And with permutations:

Inner[#2 ~Table~ {#} &, f[4, {1, 3, 2}], char, Join]

Permutations /@ %
{{B,B,C,C},{B,B,B,C},{A,B,C,C},{A,B,B,C},{A,B,B,B}}

{{{B,B,C,C},{B,C,B,C},{B,C,C,B},{C,B,B,C},{C,B,C,B},{C,C,B,B}}, . . . }

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Sigh. I didn't bother to look at the documentation for permutations because I assumed it wasn't. Thank you! – rjkaplan May 03 '12 at 00:42
  • 3
    Could you please avoid (or stop) the use of quote block for output? I find the thin grey bar on yellow BG highly distracting and really, serves no purpose. I think enclosing it in (* *) is cleaner and since it's shown in subtle grey, it's not too distracting either... – rm -rf May 03 '12 at 00:44
  • Your first answer was sufficient. Thank you :D – rjkaplan May 03 '12 at 00:44
  • @rjkaplan you're welcome. Hopefully the rest of the answer addresses a related problem. – Mr.Wizard May 03 '12 at 00:48
  • 6
    @R.M I don't really know what to say; I much prefer this format. I seem to recall this was on Meta; I'll look for the popular opinion. – Mr.Wizard May 03 '12 at 00:48
  • @Mr.Wizard AFAIK, this is the only discussion regarding it and the question notes that it is an abuse of the markup and is a feature request for support from SE. I've also noted my objection there to this usage – rm -rf May 03 '12 at 00:53
  • @R.M there is also my answer here. At present it has three upvotes and no downvotes. – Mr.Wizard May 03 '12 at 03:58
  • Unfortunately, one of those is mine. I now realize why— the quote block on meta is the same shade of grey as the comment block, and so I couldn't tell the difference when you presented it and thought it'd work. Needless to say, after seeing it on main all these days, it's very jarring. I don't think that the suggestion to change the quote block to the same shade (maybe whuber's) is good, because we do need visually different elements that serve different purposes. I'd edit your post to change my upvote to down, but I don't want to bump it (yet). Consider my vote reversed and the net score at 1 – rm -rf May 03 '12 at 04:48
  • @R.M Okay. Just for reference, what visual offset would you use for output? (no (* *) shenanigans) ;-) – Mr.Wizard May 03 '12 at 05:01
  • 4
    @R.M besides not very copyable I don't have much problems with this style. I find it visually more clear and attractive than the one I proposed myself in the Meta. It mimics one of mma's own styles. – Sjoerd C. de Vries May 03 '12 at 06:54