1

I have a word, for example SANTACLAUSE and want to calculate all permutations of variable length, but each letter can only be used as often as it it used in SANTACLAUSE.

For length = 11 its $\frac{11!}{3!2!}$. For length = 0 its 1, for length = 1 its 11 - 3 = 8. But I have no idea how to get a general formula for length n.

I am currently brute forcing it with python to get a feel for the number, but it takes a while and it gets big...

I thought about first selecting the n elements we use from all elements and then permutating the selected elements, that would be $\binom{11}{n} * n!$ but I would get duplicates and I don't know how I can eliminate them...

hardmath
  • 37,015
  • 1
    If I had a nickel for every time this question has been asked !! – Asinomás Jan 12 '16 at 17:06
  • 3
    Not fun, but we can do it by cases: (i) all letters distinct; (ii) two E's and one, two three A's; (iii) no more than one E, and two, three A's. – André Nicolas Jan 12 '16 at 17:10
  • 2
    Yeah, I hadn't read that you wanted variable lengths at first. that makes it more interesting. Of course we can just iterate over all possible combinations of multiplicity for each letter and use multinomial coefficients – Asinomás Jan 12 '16 at 17:11

3 Answers3

1

One way (again, not much fun) is to find and sum up the coefficient of $x^k$

$$\sum_{k=1}^{11} k!(1+x)^6(1+x+x^2/2!)(1+x+x^2/2!+x^3/3!)$$

The method has been explained in another answer here

0

What you want is the multinomial coefficient. Specifically, it describes the number of permutations on a set with repeated elements.

Bob Krueger
  • 6,226
0

In c++

#include <bits/stdc++.h>
using namespace std;

vector <int> W(26);
vector <int> V(26);
long long F[20];
string S;

int push(){
    for(int i=0;i<26;i++){
        if(V[i]<W[i]){
            V[i]++;
            for(int j=i-1;j>=0;j--){
                V[j]=0;
            }
            return(1);
        }
    }
    return(0);
}

long long multi(){
    long long res=0;
    for(int i=0;i<26;i++){
        res+=V[i];
    }
    res=F[res];
    for(int i=0;i<26;i++){
        res/=F[V[i]];
    }
    return(res);
}

int main(){
    F[0]=1;
    long long res=0;
    for(int i=1;i<20;i++){
        F[i]=F[i-1]*i;
    }
    cin >> S;
    for(int i=0;i<S.length();i++){
        W[S[i]-'A']++;
    }
    while(push()){
        res+=multi();
    }
    cout << res << endl;
}

All this does it try for all the possible multiplicities for each letter, and count each one with multinomial coefficients. To use it you must enter the word in ** big caps**. Also, make sure the word does not include any one letter more than $19$ times.

For "SANTACLAUSE" the answer seems to be $9,392,913$.

Asinomás
  • 105,651