cbdoc has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I'm trying to do the following in Perl and would appreciate any help with the simplest approach to do this!
$string = 'fred' %substitution = ( 2 => 'xy' 3 => 'ab' ) someFunction($string, %substitution); print;
Output should be:
fred fxed fyed frad frbd fxad fxbd fyad fybd

Any help would be awesome! In essence I'd like to substitute a string with characters at specific positions in all possible combinations.

Replies are listed 'Best First'.
Re: String Replace - Permutation, Combination?
by ikegami (Patriarch) on Dec 14, 2010 at 03:52 UTC
    use feature qw( say ); use Algorithm::Loops qw( NestedLoops ); sub someFunction { my ($s, $subs) = @_; my @loops = map [ $_ ], split //, $s; for (keys(%$subs)) { push @{ $loops[$_-1] }, split //, $subs->{$_}; } return NestedLoops(\@loops, sub { join('', @_) }); } my $s = 'fred'; my %subs = ( 2 => 'xy', 3 => 'ab', ); say for someFunction($s, \%subs);

    Algorithm::Loops

    Updated: Fixed syntax errors in the parts I copied from the OP.

      Amazing. Very nice and elegant. Thank you very much for the help!!
Re: String Replace - Permutation, Combination?
by Marshall (Canon) on Dec 14, 2010 at 01:22 UTC
    Using glob or the <> operator looks like the ticket. Consider:
    #!/usr/bin/perl -w use strict; print "$_\n" for (<{f}{r,x,y}{e,a,b}{d}>); __END__ program: op's post fred fred frad fxed frbd fyed fxed frad fxad frbd fxbd fxad fyed fxbd fyad fyad fybd fybd
    Update: Thought I had x,y and a,b reversed in previous code. Note the order is different than the op's post, but the combinations are the same.

    Continuing on.. a straightforward implementation of a sub to generate the glob string is shown below.. took a couple of more steps than I thought it would.

    #!/usr/bin/perl -w use strict; my $string = 'fred'; my %substitution = ( 2 => 'xy', 3 => 'ab' ); my @variants = gen_variants($string, %substitution); print join("\n",@variants),"\n"; sub gen_variants { my ($string, %substitution) = @_; my @letters = split(//,$string); foreach my $pos (keys %substitution) { my @newltrs = split(//,$substitution{$pos}); $letters[$pos-1] = join(',',$letters[$pos-1],@newltrs); } @letters = map{"{$_}"}@letters; my $globstr = join('',@letters); print "glob string = $globstr\n"; return (glob($globstr)); } __END__ prints: glob string = {f}{r,x,y}{e,a,b}{d} fred frad frbd fxed fxad fxbd fyed fyad fybd
      Injection bug. You don't properly insert the letters into the glob pattern. I think using quotemeta on the literals will do the trick.
      Thanks for the answer. Very impressive!
Re: String Replace - Permutation, Combination?
by Anonymous Monk on Dec 14, 2010 at 01:04 UTC
    I'm trying to do the following in Perl and would appreciate any help with the simplest approach to do this!

    Ask the oracle, really! Permutations and combinations

Re: String Replace - Permutation, Combination?
by locked_user sundialsvc4 (Abbot) on Dec 14, 2010 at 14:59 UTC

    Once again demonstrating that “Perl is Voodoo.”