in reply to Re: Permutation with repetitions
in thread Permutation with repetitions

Hi,

Thanks for replying. I don't think your code is what I am looking for. I'll try to explain again:

For the sake of illustration let's say the size of the substring I am looking for is 3. Ideally, what I would like in the end is a list for all possible permutations with repetitions and a count how often they occur. For this example, the list would look something like that:

aaa 0
aab 2
aac 1
aad 0
aba 2
abb 0
abc 1
abd 0
etc.
How can this be achieved?
Thanks
Hadassa

Replies are listed 'Best First'.
Re^3: Permutation with repetitions
by moritz (Cardinal) on Jun 07, 2010 at 10:15 UTC
    Ideally, what I would like in the end is a list for all possible permutations with repetitions and a count how often they occur.

    How often they occur... where? in which set/string/whatever?

    If you mean in the list of possible permutations, why are some of them 0?

    Perl 6 - links to (nearly) everything that is Perl 6.
      I am looking in a long string of the sort:

      aaaabdbbdaccdacdaaabdcd...

      and thus want to know the number of occurrences of any of the substrings of size 3 (as in the example). Sure, I could leave out the ones which are zero, don't need them. But I thought that I will have to loop over all possible substrings of size 3 anyway and count their occurrences.
      Thanks,
      Hadassa

        Oh, now your question is clearer. The easiest thing is to use a hash to track the frequencies, eg.

        my $str = "aaaabdbbdaccdacdaaabdcd"; my $n = 3; my %freq; for my $p (0 .. length($str) - $n) { $freq{substr($str, $p, $n)}++; } for my $ng (sort keys %freq) { printf "%3d %s\n", $freq{$ng}, $ng; }
        What ambrus says. However, what it won't do, is give you the names of permutations with no occurrence in the string.

        If you need those, I think I can find a shortcut. Think of such a string as a 4 digit number, in base 4, with an a posteriori mapping of

        ( 0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd' )
        or, in Perl code:
        tr/0-3/a-d/
        so all you really need is a 4 digit base 4 counter and this mapping. If you don't want to code this by hand, you might make use of a module like the one I found using a quick Google search, Math::BaseArith.
        Why loop (4*4*4*(23-2)) times when you can simply loop (23-2) times.
        $_ = 'aaaabdbbdaccdacdaaabdcd'; ++$counts{$1} while /(?=([abcd]{4}))/g; print("$_: $counts{$_}\n") for sort keys %counts;

        If you want to see the "0" results, you can loop (4*4*4)+(23-2) times.

        $_ = 'aaaabdbbdaccdacdaaabdcd'; ++$counts{$1} while /(?=([abcd]{4}))/g; print("$_: $counts{$_}\n") for glob "{a,b,c,d}{a,b,c,d}{a,b,c,d}";