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

Hi-

I'm trying to find all possible binary combinations of a given length. I do have a recursive code that does that but it's getting to be prohibitively slow for relatively long lengths.

If length is 3 i want my function to return:

000

001

010

011

100

101

110

111

help please!

Thanks

Replies are listed 'Best First'.
Re: all binary combinations
by FunkyMonk (Bishop) on Sep 04, 2009 at 15:59 UTC
    sub bits { glob join "", map "{0,1}", 1..$_[0] } say for bits(10); __END__ 0000000000 0000000001 0000000010 0000000011 0000000100 0000000101 ... 1111111011 1111111100 1111111101 1111111110 1111111111

    Update: On second thoughts, that's too long:

    sub bits { glob "{0,1}" x $_[0] }
    Yes, perlrocks, perl rocks!

    Unless I state otherwise, all my code runs with strict and warnings

      Yes, perlrocks, perl rocks!

      But glob is a re-implementation of csh's glob! ;)

        But that is one of Perl's strengths. It took the best of everything* that was out there, and stole it :-)

        *Apart from it's object system, obviously :-(

      mmmm thanks. But i don't really get it. Is there a way to save the solutions in a hash where each combination is a key? (i'm sure there is but i just don't know how :)
        To understand it, read the man page for glob. Then understand the following:

        print "$_\n" for glob "{0,1}"; # 0 1 print "$_\n" for glob "{0,1}{0,1}"; # 00 01 10 11 print "$_\n" for glob "{0,1}{0,1}{0,1}"; # 000 001 010 011 100 101 110 + 111

        Then read up on the repetition operator in perlop, and understand:

        print "AB" x 1; # AB print "AB" x 2; # ABAB print "AB" x 3; # ABABAB

        To use it to create keys in a hash, use something like

        use Data::Dumper; my %hash = map { $_ => 1 } glob "{0,1}" x 3; print Dumper \%hash; __END__ $VAR1 = { '011' => 1, '010' => 1, '111' => 1, '000' => 1, '101' => 1, '001' => 1, '100' => 1, '110' => 1 };


        Unless I state otherwise, all my code runs with strict and warnings
        Yes. Iterate over the results and use each result as a key.
Re: all binary combinations
by ikegami (Patriarch) on Sep 04, 2009 at 15:24 UTC
    my $length = 3; for (0..2**$length-1) { printf("%0${length}b\n", $_); }

    As a function:

    sub bits { my ($length) = @_; return map sprintf("%0${length}b\n", $_), 0..2**$length-1; }

    How long are you talking about?

    Length 10 generates ~1,000,000 results
    Length 20 generates ~1,000,000,000 results
    Length 30 generates ~1,000,000,000,000 results

    Update: Fixed placement of curlies.

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: all binary combinations
by tmharish (Friar) on Sep 04, 2009 at 15:35 UTC
    Showing your code will help understand where you are stuck and what it is you are doing; Is it a minor problem with the way you make your recursive calls or something else?

    But here is something that might help:

    If you look at the strings you are trying to generate you will notice that a recursive function will generate the same substring multiple times.

    For example, the string '01' is generated twice once for each of '001' and '101'. This is clearly not necessary.

    When you write out your recursive program you need to ensure that your code does not have to do this. One way to do that is to maintain an array ( potentially multidimensional ) which holds previously calculated values.

    Give this a shot - Let us know what you get.


Re: all binary combinations
by Perlbotics (Archbishop) on Sep 04, 2009 at 15:26 UTC

    Hi, the following seems to work here:

    perl -e '$n=3; print substr( unpack("B*", pack("N",$_)), -$n), "\n" fo +r (0..2**$n-1)'
    HTH as a starting point.

Re: all binary combinations
by Anonymous Monk on Sep 04, 2009 at 15:16 UTC
    Show your code.
Re: all binary combinations
by jwkrahn (Abbot) on Sep 04, 2009 at 15:31 UTC
    $ perl -le' my $length = 3; for ( my $i; ; ++$i ) { last if $i & 1 << $length; printf "%0*b\n", $length, $i; } ' 000 001 010 011 100 101 110 111

      While testing your code, i realized that when length >= 32, the number of results is incorrect. Do you have any idea why?

      Thanks a lot,

      Hadi

      Thanks. But i'm getting the following warning.

      Use of uninitialized value $i in bitwise and (&) at C:\Users\Hadi\Desktop\Academics\Research\0-recombination\testing1.pl line 6.

      Is there a way i can avoid it. Thanks

        initializing $i=0 worked fine :)
Re: all binary combinations
by perlrocks (Acolyte) on Sep 04, 2009 at 15:49 UTC
    Here is my code guys. I strongly favour non-recursive solutions given the long time it's taking to generate all the possible combinations.
    my $limit = 9; my @empty_array = (); generate_all_combinations_of_free_variables($limit, \@empty_array); sub generate_all_combinations_of_free_variables{ my $limit = shift; my $current_array = shift; my %combinations=(); if (@$current_array == $limit){ my $str = join("", @$current_array); $combinations{$str}++; return \%combinations; } if(@$current_array != $limit){ my @new_array = @$current_array; push @new_array, 0; my $combin1 = generate_all_combinations_of_free_variables($lim +it, \@new_array); @new_array = @$current_array; push @new_array, 1; my $combin2 = generate_all_combinations_of_free_variables($lim +it, \@new_array); my %combined_hash = (%$combin1, %$combin2); return \%combined_hash; } }