http://www.perlmonks.org?node_id=1025122

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

I have a sring like $string = "abcdefghi"; i need to reverse the string in place i.e without using any other array or built-in function. The algorithm used for this is swapping the numbers like below:
function reverse_in_place(a[0..n]) for i from 0 to floor(n/2) tmp := a[i] a[i] := a[n - 1 - i] a[n - 1 -; i] := tmp
Can you please tell me is there any regular expression that can be used to reverse the string or any perl code will be helpful. Thanks in advance.

Replies are listed 'Best First'.
Re: reverse a string in place
by choroba (Cardinal) on Mar 24, 2013 at 07:33 UTC
    In Perl, a string is not an array of characters as in C. Reversing a string is easy, though: use reverse:
    $string = reverse $string;

    Update: What do you mean by doing it "without using any built-in function"? In your example, are you going to implement floor yourself?

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      choroba,
      You really made laugh my heart out with your comment: "What do you mean by doing it "without using any built-in function"? In your example, are you going to implement floor yourself?"
      Tripple ++ to you....

        by 'without using any built-in' i meant the 'reverse' function in perl which is used to reverse the string.
Re: reverse a string in place
by kcott (Archbishop) on Mar 24, 2013 at 09:23 UTC

    Perhaps this will satisfy your teacher:

    $ perl -e ' + $x = "abcdefghi"; print +($x =~ /./g)[-$_] for (1 .. $#{[$x =~ /./g]} + 1); ' ihgfedcba

    -- Ken

Re: reverse a string in place
by tobyink (Canon) on Mar 24, 2013 at 09:47 UTC
    my $string = "abcdefghi"; $string =~ s/(.)/substr($string, length($string)-pos($string)-1, 1)/eg +; print $string, "\n";
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: reverse a string in place
by CountZero (Bishop) on Mar 24, 2013 at 07:42 UTC
    What is wrong with using the available tools and functions? Unless this is homework, it is a silly requirement.

    And if it is homework, it still is silly.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
Re: reverse a string in place
by Athanasius (Archbishop) on Mar 24, 2013 at 08:04 UTC

    Just want to point out that the algorithm as given is incorrect. n is the number of elements in the array, so the first line should read:

    function reverse_in_place(a[0 .. (n - 1)])

    Alternatively, you would need to change the arithmetic:

    function reverse_in_place(a[0 .. n]) for i from 0 to floor( ((n + 1) / 2) - 1 ) tmp := a[i] a[i] := a[n - i] a[n - i] := tmp

    Update 1: Implementing the algorithm in Perl is straightforward, provided you are allowed to use the built-in functions split and join (scalar isn’t really needed in the sub):

    use strict; use warnings; my $string = 'abcdefghi'; print 'Original string: ', $string, "\n"; print 'Using function: ', reverse_in_place($string), "\n"; print 'Using reverse: ', scalar reverse ($string), "\n"; # For c +omparison sub reverse_in_place { my ($string) = @_; my @array = split //, $string; my $n = scalar @array; for (0 .. $n / 2 - 1) { my $tmp = $array[$_]; $array[$_] = $array[$n - $_ - 1]; $array[$n - $_ - 1] = $tmp; } return join('', @array); }

    Update 2: Fixed out-by-one error in the for loop. Thanks to j0se for pointing it out.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Hello, your Perl solution seems to have problems with strings that have an even number of characters:

      Original string: ab Using function: ab Using reverse: ba Original string: abcd Using function: dbca Using reverse: dcba

      Excellence is an art won by training and habituation: we do not act rightly because we have virtue or excellence, but we rather have these because we have acted rightly. -- Will Durant

      I don't know how old this thread is but I found it interesting to practice manipulation for strings,

      please keep in mind that I am but a few weeks into this perl code but did I meet the requirements? other than using length or split

      use strict; use warnings; my $string = 'abcdefghi'; #let's find the ways to count the elements in string; my $l = length($string); #finding number of elemnts my @ind=split //,$string; #finding the number of elements #assigning the start of our last element for our looping my $n = (scalar @ind )-1; #getting the last element to start count bac +kwards optinal for (my $i=(length ($string)-1) ; $i >= 0; $i-- ){ print $ind[$i]; } print "\nfor comparison :", scalar reverse($string),"\n";

        Good job, especially the use strict; use warnings;. Here's another way based on your code that you may find interesting. (EDIT: My bad... I totally glanced over the fact no built-ins were allowed).

        while (my $letter = pop @ind){ print $letter; }

        pop() removes the last element of an array. Also see shift(), unshift() and push()

        -stevieb

Re: reverse a string in place
by choroba (Cardinal) on Mar 24, 2013 at 08:57 UTC
    Using substr and length:
    my $s = "abcdefgh"; print "$s\n"; $s .= substr $s, length($s) - 2 * $_, 1 for 1 .. length($s) - 1;# Add +the reversed string. substr $s, 0, length($s) / 2, q(); # Remo +ve the original string. print "$s\n";
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: reverse a string in place
by ww (Archbishop) on Mar 24, 2013 at 17:07 UTC

    When you ask the Monks to do your homework, it's well to make note of that fact in your initial post.

    Otherwise, someone with a spark of evil might just post code to do the job with such sophistication that your instructor will immediately know you've been cheating.

    If you didn't program your executable by toggling in binary, it wasn't really programming!

      No built-in functions (abundant use of Perl's operators, though).

      Yes, there's a spark of evil. But "they" always say that the easiest way is to divide a problem into smaller sub-problems:

      sub rec_reverse { return $_[0] if $_[0] eq ''; my( $char, $smaller_problem ) = $_[0] =~ m/\A(.)(.*)\z/s; return rec_reverse( $smaller_problem ) . $char; } print rec_reverse( "Hello\nworld." ), "\n";

      I wouldn't call it sophisticated or elegant though, and if it were turned in as ones own work, it would probably merit some skepticism. Recursion is not an optimal approach here, since the number of recursive calls will match the length of the string, and each call added to the call-stack has a cost. Also, the regexp contortion as a means of eliminating any "built-in" functions (ie, substr) does nothing to dispel the rumor that Perl is difficult to read.

      I find with recursion that it always helps me to think through it by thinking in terms of "problem" and "smaller_problem". I'm always tempted to write recursion like this:

      sub rec_reverse { my $problem = shift; if( $problem eq '' or ! defined $problem ) { return $problem; # Can't be made smaller. End case. } else { my( $char, $smaller_problem ) = $problem =~ m/\A(.)(.*)\z/s; return rec_reverse( $smaller_problem ) . $char; } }

      Which is the same thing but more explicit, and possibly more readable (and possibly less, since we've lost variable names that look like strings).


      Dave

Re: reverse a string in place
by jwkrahn (Abbot) on Mar 24, 2013 at 22:12 UTC
    $ perl -le' my $string = "abcdefghi"; print $string; # get the address of every character my @addr = map \substr( $string, $_, 1 ), 0 .. length( $string ) - 1; # swap the characters in-place. ( ${$addr[ $_ ]}, ${$addr[ -( $_ + 1 ) ]} ) = ( ${$addr[ -( $_ + 1 ) ] +}, ${$addr[ $_ ]} ) for 0 .. $#addr / 2; print $string; ' abcdefghi ihgfedcba
Re: reverse a string in place
by toolic (Bishop) on Mar 24, 2013 at 12:46 UTC
Re: reverse a string in place
by mtve (Deacon) on Mar 27, 2013 at 12:07 UTC

    hmm, regular expression, without using any other array or (almost no) build-in functions:

    #! /usr/bin/perl use warnings; use strict; $_ = 'abcdefghi'; # s/./ substr $_, -$+[0], 1 /eg; # duh, substr and array # s#.# /(.).{$-[0]}$/; $1 #eg; # duh, array my $x = 0; s#.# /(.).{$x}$/; $x++; $1 #eg; print "$_\n";
Re: reverse a string in place
by Anonymous Monk on Feb 27, 2016 at 19:06 UTC
    my $string_reversed = join '', reverse(split //, $string_to_reverse);
Re: reverse a string in place
by Anonymous Monk on Feb 28, 2016 at 08:13 UTC

    Toady Tim. Is map() a function, technically?

    #! /usr/bin/perl -lw my @a = split //, shift; print "INPUT = <@a>"; # @a[0..$#a] = @a[map -1-$_, 0..$#a]; @a[$_,~$_] = @a[~$_,$_] for 0..$#a/2; print "OUTPUT = <@a>";