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

Hi all,

I have a string of 0s and 1s, for instance "1101000010101111". I want to reverse each group of 8 chars in it. For the above example: "0000101111110101"

The application is a string of bits, and the bits of each byte must be reversed.

I'm looking for the fastest way to achieve this, on strings of small length (up to a few hundred chars). The obvius solution, which is pretty fast is with substr() on each 8 bits (in a for loop). Any better ideas ?

Thanks in advance

  • Comment on Reversing chunks in a string (bits of byte in a bitstring)

Replies are listed 'Best First'.
Re: Reversing chunks in a string (bits of byte in a bitstring)
by broquaint (Abbot) on Feb 16, 2004 at 14:28 UTC
    This should be quite nippy.
    my $str = '1234567812345678'; $str =~ s/(.{8})/reverse $1/eg; print "str: $str\n"; __output__ str: 8765432187654321
    HTH

    _________
    broquaint

Re: Reversing chunks in a string (bits of byte in a bitstring)
by Tomte (Priest) on Feb 16, 2004 at 14:52 UTC

    I'd consider Bit::Vector to ensure a (supposed :) best combination of speed and platform-independence, not to mention ease of use:

    use Bit::Vector; my $size=16; my $bits = Bit::Vector->new_Bin($size,"1101000010101111"); print "orig:\t\t",$bits->to_Bin(), "\n"; $bits->Interval_Reverse(($_-1)*8,$_*8-1) for (1..($size/8)); print "byte-rev:\t",$bits->to_Bin(), "\n"; __END__ orig: 1101000010101111 byte-rev: 0000101111110101

    regards,
    tomte


    Hlade's Law:

    If you have a difficult task, give it to a lazy person --
    they will find an easier way to do it.

Re: Reversing chunks in a string (bits of byte in a bitstring)
by belg4mit (Prior) on Feb 16, 2004 at 14:36 UTC
    I should think the obvious implementation would be to use pack and unpack with a combination of little-endian and big-endian templates.

    --
    I'm not belgian but I play one on TV.

Re: Reversing chunks in a string (bits of byte in a bitstring)
by jmcnamara (Monsignor) on Feb 16, 2004 at 20:07 UTC

    Here is one way.
    #!/usr/bin/perl -wl my $str1 = "1101000010101111"; my $str2 = join "", unpack "b8b8", pack "B*", $str1; print for $str1, $str2; __END__ Prints: 1101000010101111 0000101111110101

    For this sort of task pack is usually the fastest method but to be sure you should benchmark it against the other solutions.

    --
    John.