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

The following python code enables me to take a string of words and replace spaces with hyphens in every possible combination:

from itertools import product def dashed_combos(inputstring): words = inputstring.split() for combo in product(' -', repeat=len(words) - 1): yield ''.join(w for pair in zip(words, combo + ('',)) for w in + pair)

This will produce the following combinations from the string 'convert perl to-python'

'convert perl-to python' 'convert-perl to python' 'convert perl-to-python' 'convert-perl-to python' 'convert-perl-to-python'

I'm now trying to do exactly the same with perl. I've found a few modules that can produce the cartesian product (e.g. Math::Cartesian::Product and nested loops from Algorithm::Loops), although not being that familiar with perl I've struggled to get these to work to do what had worked so well in python. If anyone would be so kind as to help me here that would be great, as I've spent quite a while trying now, but with little joy.

  • Comment on Python to perl: itertools product to replace a char in string in each possible position
  • Select or Download Code

Replies are listed 'Best First'.
Re: Python to perl: itertools product to replace a char in string in each possible position
by BrowserUk (Patriarch) on Aug 10, 2015 at 08:36 UTC
    will produce the following combinations from the string 'convert perl to-python'

    Assuming you typoed:

    #! perl -slw use strict; use Algorithm::Combinatorics qw[ variations_with_repetition ]; sub zip { my( $r1, $r2 ) = @_; my $n = @$r1 > @$r2 ? $#{$r1} : $#{$r2}; map{ ( $r1->[ $_ ] // '', $r2->[ $_ ] // '' ) } 0 .. $n; } sub dashedCombos { my @words = split ' ', shift; map { join '', zip( \@words, $_ ) } variations_with_repetition( [ +' ', '-' ], $#words ); } print for dashedCombos( 'convert perl to python' ); __END__ C:\test>1137970 convert perl to python convert perl to-python convert perl-to python convert perl-to-python convert-perl to python convert-perl to-python convert-perl-to python convert-perl-to-python

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
    I'm with torvalds on this Agile (and TDD) debunked I told'em LLVM was the way to go. But did they listen!
Re: Python to perl: itertools product to replace a char in string in each possible position (glob)
by LanX (Saint) on Aug 10, 2015 at 11:50 UTC
    actually Perl has a builtin glob for this use case.

    DB<123> $input="one two three" => "one two three" DB<124> $globber= join q|{' ','-'}| , split / +/, $input => "one{' ','-'}two{' ','-'}three" DB<125> print "$_\n" while glob($globber) one two three one two-three one-two three one-two-three

    please note that line 125 acts as an iterator looping over all results, like yield permits.

    for a flat list result just don't call glob in scalar context:

    DB<127> print join "\n", glob($globber) one two three one two-three one-two three one-two-three

    update

    just in case $input includes any meta characters or wildcards, you'll need to escape them before.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

Re: Python to perl: itertools product to replace a char in string in each possible position
by shmem (Chancellor) on Aug 10, 2015 at 11:24 UTC
    The following python code enables me to take a string of words and replace spaces with hyphens in every possible combination:

    The number of every possible combination in the string "convert perl to python" are 8, not 5, or am I missing something?

    my $str = 'convert perl-to python'; my $bits =()= $str =~ /[ -]/g; for (0 .. (1<<$bits)-1) { my @l = split//,unpack'b*',pack'C,',$_; (my $out = $str) =~ s/[ -]/(' ','-')[shift @l]/ge; print $out, $/; } __END__ convert perl to python convert-perl to python convert perl-to python convert-perl-to python convert perl to-python convert-perl to-python convert perl-to-python convert-perl-to-python

    You get more off that if you use the string "don't convert perl to python" which gives you 16 combinations.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
Re: Python to perl: itertools product to replace a char in string in each possible position
by anonymized user 468275 (Curate) on Aug 10, 2015 at 10:26 UTC
    Combinations are distinct subsets of a set. So I am not sure what the Python snippet is really meant to produce. If I were asked to produce all combinations of words in a string, I'd use the theory that the number of subsets of a set of N members is 2**N. The reason is that a bit-string of N bits, where each bit represents inclusion of an element, represents a combination and all possible combinations can therefore be represented by all possible numbers expressed as these bit strings from 0 to (2**N)-1 (of which there are 2**N, including the empty set). So converting the theory into Perl:-

    Update: I just noticed the OP wants to vary separators not words, so I'll address that further down...

    my @superset = split /\s+/, 'convert python to perl'; my $N = scalar @superset; for my $combo (0..((2**$N) - 1)) { # a combo is also a bit mask print "selection:"; for my $selector (0..($N-1)) { # a selector is also a bit (2**$selector) & $combo and print ' ' . $superset[$selector]; } print "\n"; }
    which produces the following output:
    selection: selection: convert selection: python selection: convert python selection: to selection: convert to selection: python to selection: convert python to selection: perl selection: convert perl selection: python perl selection: convert python perl selection: to perl selection: convert to perl selection: python to perl selection: convert python to perl

    Update: to vary spaces and hyphens (what I now understand is wanted), the same technique can apply

    my @superset = split /\s+/, 'convert python to perl'; my $N = $#superset; # one less element than in the previous example for my $combo (0..((2**$N) - 1)) { # a combo is a bit mask for my $selector (0..$N) { # a selector is also a bit position print $superset[$selector]; if ($selector == $N) { print "\n"; next; } if ((2**$selector) & $combo) { print ' '; } else { print '-'; } } }
    producing
    convert-python-to-perl convert python-to-perl convert-python to-perl convert python to-perl convert-python-to perl convert python-to perl convert-python to perl convert python to perl

    More update: Afterthought: 1 << $var is likely to be faster than, while being equivalent to:  2 ** $var.

    One world, one people

Re: Python to perl: itertools product to replace a char in string in each possible position
by LanX (Saint) on Aug 10, 2015 at 11:23 UTC
    Do you really need the python yield ?

    Then you will need to construct an iterator.

    Not sure what your list comprehension does, its hard to read.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!