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

Hello Perlmonks!
I have a problem and I need advice, because I can't think of how exactly to proceed.
In a script of mine, I create an array of arrays, of the following type:
@my_arr=( [1, 11, 0, 0], [12, 109, 0, 0] [16, 1, 16, 0], [14, 14, 2, 0], [45, 16, 5, 4] );

What I want to do is:
1) Start from the last element (let's name it k), which in my case is $my_arr[5][4] -> 4 (this is elemnt l).
2) Find the element $my_arr[l][3], which is $my_arr[4][3], which is 2 (this is element m).
3) Then, find the element $my_arr[m][2], which is $my_arr[2][2], which is 1 (element n).
4) Finally, find the element $my_arr[n][1], which is $my_arr[1][1], which is 12.
The total string of numbers will be: 4-2-1-12.
I can't think of the kind of loop i must use...

Replies are listed 'Best First'.
Re: Read array of arrays in reverse order
by GrandFather (Saint) on Apr 18, 2010 at 23:15 UTC

    It looks to me like what you want to do is find the elements along a diagonal from the 'last' element. Perl allows you to index from the end of an array using negative values so this becomes fairly trivial with the only major trick being knowing when to stop. Consider:

    use strict; use warnings; my @my_arr = ( [1, 11, 0, 0], [12, 109, 0, 0], [16, 1, 16, 0], [14, 14, 2, 0], [45, 16, 5, 4], ); my $index = -1; my @diagonal; while (exists $my_arr[$index] && exists $my_arr[$index][$index]) { push @diagonal, $my_arr[$index][$index]; --$index; } print join '-', @diagonal;

    Prints:

    4-2-1-12
    True laziness is hard work
Re: Read array of arrays in reverse order
by LanX (Saint) on Apr 18, 2010 at 22:08 UTC
    First of all indexing in perl starts with 0 not 1.

    Then the solution is much easier than your description.

    It's most likely a artificial exercise for homework, since an index like 12 is out of boundary and would make it break.

    Sorry we don't run a homework service here!!!

    But we give advice... looping over a reversed @a gives you the rows in the order you need....

    So plz try to show us some code now! :)

    Cheers Rolf

    UPDATE: And your example is not consistent, first you start indexing from 1 and then from 0... it's 4-2-109-

Re: Read array of arrays in reverse order
by b4swine (Pilgrim) on Apr 18, 2010 at 22:09 UTC

    First a typo in your example:

    (Step 2) Find the element <tt>$my_arr[k][3]...

    Now, in order to make it programmable, it is better to not have variable names that are changing like k, l, m, n, ... Since you want to have the entire list, in any case, we can call them k[0], k1, ..., so your algorithm now becomes:

    Step 0) k[0] = $arr[4][3] Step 1) k[1] = $arr[3][k[0]] Step 2) k[2] = $arr[2][k[1]] Step 3) k[3] = $arr[1][k[2]]

    Now k is the answer. Since step 0, is different, it could be done out of the loop, while the rest can be easily made into a loop. Perhaps this is enough help?

Re: Read array of arrays in reverse order
by nvivek (Vicar) on Apr 19, 2010 at 03:14 UTC
    Following script also does the job.Normally in Perl,array indexes starts from 0.
    use strict; use warnings; my @my_arr = ( [1, 11, 0, 0], [12, 109, 0, 0], [16, 1, 16, 0], [14, 14, 2, 0], [45, 16, 5, 4], ); my $index=$#my_arr; while($index) { push @diagonal,$my_arr[$index][$index-1]; --$index; }
    print join '-', @diagonal;
Re: Read array of arrays in reverse order
by PeterPeiGuo (Hermit) on Apr 18, 2010 at 22:09 UTC

    Have two indexes - on is initialized to largest index of your outer array, and the second one is initialized to the largest index of your inner array.

    State to iteration, each time decrement both indexes by 1, until at least one of those indexes hits zero. With each iteration, take the element identifies by those two indexes - that's what you want.

    Peter (Guo) Pei

      You were probably looking for something more complicated, but your step 3 is wrong. Your (2,2) is not 1, it is 109 (this is 1-based index, just like you did, simply to avoid more confusion).

      Maybe what you are looking for is more like this:

      use warnings; use strict; my @my_arr=( [1, 11, 0, 0], [12, 109, 0, 0], [16, 1, 16, 0], [14, 14, 2, 0], [45, 16, 5, 4] ); my ($index1, $index2) = (5, 4); #used 1-based index for easy communica +tion while (1) { last if $index1 > 5 || $index1 < 1 || $index2 > 4 || $index2 < 1; print $my_arr[$index1 - 1][$index2 - 1], "\n"; $index1 = $my_arr[$index1 - 1][$index2 - 1]; $index2 --; }

      Peter (Guo) Pei