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

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

Hello,

Today I have an array, and I want to reverse and push it, to make a final array become palindromic. Upd.If initial array has even length, I want to double the length, otherwise I want doubled and -1 length. I've tried this expression:
push @array, reverse @array[ 0 .. $n / 2 - 1 ];
Where $n - is a length of final array (wanted length). For some test cases: @arr =
qw(A B C D E) qw(A B C D) qw(A B C) qw(A B) qw(A)
It outputs:
A B C D E D C B A A B C D D C B A A B C B A A B B A A A
I would like to get only one 'A' (n = 1) in the last output line. Intuitively it looked like '0 .. 1/2 - 1' is an empty list, however '0 .. -0.5' is being converted to '0 .. 0', so it is a non-empty range, because '..' asks its operands to become integers, i.e. 'int(-0.5)' becomes '0' (opposing to POSIX:floor).
So even ranges '0 .. -0.5' and '0 .. 0.5' are equal.

What expression would you suggest to put into brackets to achieve my goal:
push @array, reverse @array[ EXPR ];

Replies are listed 'Best First'.
Re: Need help with range expression ('0 .. -0.5' === '0 .. 0.5')
by poj (Abbot) on Feb 23, 2019 at 18:49 UTC
    push @array,reverse (@array==1 ? () : @array[ 0..$#array - @array % 2 +]);
    poj
Re: Need help with range expression ('0 .. -0.5' === '0 .. 0.5')
by vr (Curate) on Feb 23, 2019 at 19:09 UTC
    push @a, reverse @a[0..$#a-@a%2];
      I am surprised that this works for the special case qw(A). Documentation for the range operator specifies that it returns an empty list when the first element is greater than the second (in this case 0..-1). I cannot find any documentation of what should happen when the list of elements in an array slice is an empty list (in this case @a() ). It seems to return an empty string, which is exactly what is needed!

      UPdate: Corrected terminology - Changed 'string' to 'list'.

      Bill

        No, why (from Range Operators):

        In list context, it returns a list of values counting (up by ones) from the left value to the right value. If the left value is greater than the right value then it returns the empty list.

        I'm embarrassed to see now, I posted almost the same answer as poj 10 minutes after him. I guess I just glanced across available answers without actually reading, thought his was long enough so mine is different, and clicked "create". Sorry about that.

Re: Need help with range expression ('0 .. -0.5' === '0 .. 0.5')
by 1nickt (Canon) on Feb 23, 2019 at 18:48 UTC

    Try this?:

    push @array, reverse @array[ $n > 2 ? 0 .. $n / 2 - 1 : 0 ];

    Edit: no, try this:

    push @arr, $#arr < 1 ? () : reverse @arr[ 0 .. ($#arr % 2 ? $#arr : $# +arr - 1)];


    The way forward always starts with a minimal test.
Re: [SOLVED]: Need help with range expression ('0 .. -0.5' === '0 .. 0.5')
by rsFalse (Chaplain) on Feb 24, 2019 at 21:26 UTC
    Thanks for answers ;)

    And later I've found a trivial "upgrade" to the initial range, for which I was blind yesterday... Just to add "int" in one place:
    push @array, reverse @array[ 0 .. int( $n / 2 ) - 1 ];
      If initial array has even length, I want to double the length, otherwise I want doubled and -1 length.
      ...
      Where $n - is a length of final array ...
      ...
      push @array, reverse @array[ 0 .. int( $n / 2 ) - 1 ];

      Why bother figuring out the length  $n of the final, palindromatized array when this length is inherent in the initial array?
          push @array, reverse @array[ 0 .. $#array - (@array & 1) ];
      (This is essentially vr's solution. (Update: To be quite fair, 1nickt here and poj here also had essentially the same solution, and with earlier precedence.))


      Give a man a fish:  <%-{-{-{-<