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

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.

Replies are listed 'Best First'.
Re^4: Permutation with repetitions
by umeboshi (Acolyte) on Jun 07, 2010 at 10:22 UTC
    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}";