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

I was trying to write the program of magic square. So I need a dynamic 2D array. But however when I tried to put some number in the array, it behaves abnormally. the output shows the first 2 rows as identical... my code was...

################################################### #!/usr/bin/perl use warnings; print " Enter dimension : "; my $n = <STDIN>; my $i=0; my $j=0; my $k=1; my @matrix = ( $n , $n ); for($i = 0; $i < $n; $i++) { print " see how the first row changes automatically...\n\n"; for($j = 0; $j < $n; $j++) { $matrix[$i][$j]= $k++; print "row = $i and col = $j input = $matrix[$i][$j] firstrow $j = $m +atrix[0][$j] //for error checking \n"; } } print " the matrix : \n\n"; for($i = 0; $i < $n; $i++) { for($j = 0; $j < $n; $j++) { print "$matrix[$i][$j] "; } print "\n"; } ############################################

just check it out

Replies are listed 'Best First'.
Re: Multidimentioal array
by Monk::Thomas (Friar) on Jul 09, 2015 at 12:08 UTC

    it magically works after converting the C-style loops to Perl
    Update: ... and strip the attempt at array initialization. I was wondering why the loops were having an effect but failed to notice I automatically fixed the array init. Ups.

    #!/usr/bin/perl use strict; use warnings; print " Enter dimension : "; my $n = <STDIN>; $n--; my $k = 1; my @matrix; for my $i (0..$n) { for my $j (0..$n) { $matrix[$i][$j]= $k++; } } print " the matrix : \n\n"; for my $i (0..$n) { for my $j (0..$n) { print "$matrix[$i][$j] "; } print "\n"; }
    Output:
    % perl matrix.pl  
     Enter dimension : 5
     the matrix : 
    
    1  2  3  4  5  
    6  7  8  9  10  
    11  12  13  14  15  
    16  17  18  19  20  
    21  22  23  24  25  
    

      Hi Monk::Thomas ... I was fooling with these and got a strange result when passing a non-integer to the scripts.

      [05:32][nick:~/dev/perl_dev/test/monks]$ cat 1133944.pl #!/usr/bin/env perl use strict; use warnings; print " Enter dimension : "; my $n = <STDIN>; my $k=1; my @matrix; for(my $i = 0; $i < $n; $i++) { for(my $j = 0; $j < $n; $j++) { $matrix[$i][$j]= $k++; } } print " the matrix : \n\n"; for(my $i = 0; $i < $n; $i++) { for(my $j = 0; $j < $n; $j++) { print "$matrix[$i][$j] "; } print "\n"; }
      [05:31][nick:~/dev/perl_dev/test/monks]$ perl 1133944.pl Enter dimension : 3.14159 the matrix : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
      [05:32][nick:~/dev/perl_dev/test/monks]$ cat 1133944-2.pl #!/usr/bin/env perl use strict; use warnings; print " Enter dimension : "; my $n = <STDIN>; $n--; my $k = 1; my @matrix; for my $i (0..$n) { for my $j (0..$n) { $matrix[$i][$j]= $k++; } } print " the matrix : \n\n"; for my $i (0..$n) { for my $j (0..$n) { print "$matrix[$i][$j] "; } print "\n"; }
      [05:33][nick:~/dev/perl_dev/test/monks]$ perl 1133944-2.pl Enter dimension : 3.14159 the matrix : 1 2 3 4 5 6 7 8 9

      Interesting that the number should be rounded differently in those two scripts!

      Remember: Ne dederis in spiritu molere illegitimi!

        Subhrangshu Das:

        1nickt:

        It's *not* rounding differently in the two scripts. First, neither is doing any rounding. Second, the second script explicitly decrements $n!

        Update: fixed greeting. Sorry Subhrangshu & 1nickt!

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

        Hi Monk::Thomas ... I was fooling with these and got a strange result when passing a non-integer to the scripts.

        And why do you want to do that?? You are using the user provided value as array indices. Array indices are supposed to be integer values.

        If you want to handle non-integer values then you should either implement some method to convert the provided input into a valid value or refuse invalid / strange input.

      Thanks thomas... learnt a new tric... but what is the problem in my code? did u understand anything?
Re: Multidimentioal array
by ambrus (Abbot) on Jul 09, 2015 at 12:57 UTC

    Have you tried to add use strict; to your program? I believe it would point out the mistake you've made.

Re: Multidimentioal array
by 1nickt (Canon) on Jul 09, 2015 at 12:13 UTC

    If you initialize @matrix as an empty list, it works fine.

    #!/usr/bin/perl use strict; use warnings; print " Enter dimension : "; my $n = <STDIN>; my $i=0; my $j=0; my $k=1; my @matrix;# = ( $n , $n ); for($i = 0; $i < $n; $i++) { for($j = 0; $j < $n; $j++) { $matrix[$i][$j]= $k++; } } print " the matrix : \n\n"; for($i = 0; $i < $n; $i++) { for($j = 0; $j < $n; $j++) { print "$matrix[$i][$j] "; } print "\n"; }
    05:11][nick:~/dev/perl_dev/test/monks]$ perl 1133944.pl Enter dimension : 4 the matrix : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
    Remember: Ne dederis in spiritu molere illegitimi!

      Thanks 1nickt ... learnt a new trics... but what is the problem in my code? did u understand anything?

        but what is the problem in my code?

        use strict;

        If you add 'use strict;' then it becomes very obvious there's something wrong with your code:

        use strict; use warnings;
        results in:
         Enter dimension : 5
         see how the first  row changes automatically...
        
        Can't use string ("5
        ") as an ARRAY ref while "strict refs" in use at matrix_orig.pl line 25, <STDIN> line 1.
        
        From there it's a small step to fix the attempt to define a multidimensional array on line 25:
        - my @matrix = ( $n , $n ); + my @matrix;

        Hmm. Actually the step is not that small. Let me try to explain. What you probably expect @array to contain is something like this:

        @array = ( 1, 2, 3, <-- $i = 0 4, 5, 6, <-- $i = 1 7, 8, 9, <-- $i = 2 ^ ^ ^ | | | $j = 0 $j = 1 $j = 2 );
        However what you're actually creating is:

        @array = ( [ 1, 2, 3 ], # <-- $i = 0 [ 4, 5, 6 ], # <-- $i = 1 [ 7, 8, 9 ], # <-- $i = 2 ^ ^ ^ | | | $j = 0 $j = 1 $j = 2 );

        Please note the square brackets.

        This is a typical 'array of array' data structure. Perl does not have any notion of a multidimensional array. Instead you create an array that has another array as one of it's members. To Perl the above data structure looks more like this:

        @array = ([ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ]); ^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^ $i = 0 $i = 1 $i = 2 # @array = <nested_array1>, <nested_array2>, <nested_array3>; # <nested_array1> = 1, 2, 3 # <nested_array2> = 4, 5, 6 # <nested_array3> = 7, 8, 9
        Because of my @matrix = ( $n, $n); the array already contains 2 values before you start to populate it:
        @array = ( 5, 5 );

        In line 28 you try to access the second dimension in the array, and perl complains that the already existing value '5' can not be used as a reference to another array.

        !! This is your problem. Perl is unable to use the already existing value '5' as a reference into another array. !!

        If you remove the attempt to define a multidimensional array, then @array looks like this instead:

        @array = ();
        $array[0] is an undefined value and perl will automagically create a nested array for you to store the first value
        # $i = 0, $j = 0, $k = 1 @array = ( [ 1 ] );
        next value ($i = 0, $j = 1, $k = 2)
        @array = ( [ 1, 2 ] );
        next value ($i = 0, $j = 2, $k = 3)
        @array = ( [ 1, 2, 3 ] );
        next value ($i = 1, $j = 0, $k = 4)
        @array = ( [ 1, 2, 3 ], [ 4 ] );
        ...and then everything starts to work as expected