Search code examples
stringperlshift

How do I circular shift some characters/bits?


I need to circular shift some characters/bit using Perl

For example, with the following input (reversing character strings):

1010
1110
hello

I need to obtain:

0101
0111
olleh

How do I achieve this using Perl?


Solution

  • However, if you really want to circular shift values, it's easy to write a function that does it with arbitrary lists for training:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    use feature 'say';
    
    # circular shift lists
    sub circular {
        my ($i, @values) = @_;
        return @values[ map +($_ + $i) % @values => 0 .. $#values ];
    }
    
    say circular  4, 1 .. 9;                # 567891234
    say circular -2, 1 .. 9;                # 891234567
    say circular  3, split '' => 'hello';   # lohel
    

    A few words of explanation for the return line of circular:

    return @values[ ... ];
    

    We're returning an array slice of @values here, which means we evaluate it with a list of indices and return the list of values.

    map ... => 0 .. $#values
    

    We're returning a list of values here that we calculate from all indices of @values, 0 is the first, $#values is the last.

    +($_ + $i) % @values
    

    This is what we do with these indices. The + sign is only used to tell perl that the parantheses are not the argument paratheses for map. We add $i to the index and to prevent that it becomes > $#values we modulo divide it by the length of @values. Note that it's not important to call length @values here because % evaluates its second operand in scalar context and arrays in scalar context evaluate to their length.

    I leave it up to you as a simple exercise to convert your things like hello or 1110 to lists and back to scalars.