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

Hello, I want to draw this triangle by perl:
1 11 121 1331 14641 .......
and now have some problem with my sub partition, pls see codes below:
#!/usr/bin/perl use strict; use warnings; my $i; my $j; my $k; my @a; my @b; $a[0] = 1; $a[1] = 1; for($i=0;$i<=10;$i++){ @a = &yh(@a); print @a,"\n"; } sub yh{ my(@a)=@_; my @b; my $j; my $k; $k = $#a + 1; $b[0] = 1; for($i=1;$i<=$k;$i++){ $j = $i - 1; $b[$i] = $a[$i] + $a[$j]; } $b[$k] = 1; return @b; }
and when run it at command line,
phillip@Athen:~/script$ perl yanghui.pl Use of uninitialized value in addition (+) at yanghui.pl line 34. 121 Use of uninitialized value in addition (+) at yanghui.pl line 34. 1331 Use of uninitialized value in addition (+) at yanghui.pl line 34. 14641 Use of uninitialized value in addition (+) at yanghui.pl line 34. 15101051 Use of uninitialized value in addition (+) at yanghui.pl line 34. 1615201561 Use of uninitialized value in addition (+) at yanghui.pl line 34. 172135352171 Use of uninitialized value in addition (+) at yanghui.pl line 34. 18285670562881 Use of uninitialized value in addition (+) at yanghui.pl line 34. 193684126126843691
I know i can ignore the warning by remove "use strict and use warnings". while my question is ,if i want to remain "use strict" "use warnings" in codes, what can i do to not display this warning message? Thanks, Phillip

Replies are listed 'Best First'.
Re: problem in my sub partition
by Ratazong (Monsignor) on Nov 08, 2010 at 16:12 UTC

    Hi!

    Line 34 is

    $b[$i] = $a[$i] + $a[$j];
    And the error is Use of uninitialized value in addition (+) at yanghui.pl line 34..

    So obviously either $a[$i] or $a[$j] are undefined.

    Now lets have a look at $i and $j:

    for($i=1;$i<=$k;$i++){ # $k = $#a + 1; $j = $i - 1;
    So $j goes from 0 to the number of the last element of $a. And $i goes from 1 to the last element + 1!

    The element $a["last element + 1"] is undefined, and that's the reason for your error.

    The solution is simple: just let your loop process one element less:

    for($i=1;$i<$k;$i++)

    HTH, Rata
Re: problem in my sub partition
by kcott (Archbishop) on Nov 08, 2010 at 16:19 UTC

    You're doing the right thing by checking errors - you've made a classic error which is easy to fix. You are off by one in:

    for($i=1;$i<=$k;$i++)

    which should be:

    for($i=1;$i<$k;$i++){

    You're not quite done though. As you can see from your current output, you're missing the top of Pascal's triangle:

    1 11

    Tongue-in-cheek comment: you could try handing this in for your homework and see if you get away with it:

    $ perl -wE 'for (0 .. 4) { say 11**$_ }' 1 11 121 1331 14641

    -- Ken

Re: problem in my sub partition
by moritz (Cardinal) on Nov 08, 2010 at 16:16 UTC
    You are accessing one value beyond the end of array @a. That returns undef, and thus you get the warnings.

    Since addition treats undef as 0, and that is what you, just switch off the warning:

    for($i=1;$i<=$k;$i++){ $j = $i - 1; no warnings 'uninitialized'; $b[$i] = $a[$i] + $a[$j]; }
    Perl 6 - links to (nearly) everything that is Perl 6.
Re: problem in my sub partition
by VinsWorldcom (Prior) on Nov 08, 2010 at 16:09 UTC

    Are you sure the values in your for loop in the sub are what you expect?

    ... for($i=1;$i<=$k;$i++){ print "i = $i, j= $j\n"; # Added to debug ...

    I think you'll find the following does the trick:

    for($i=1;$i<$k;$i++){

    (Less than versus less than/equal to)

      or if you happen to be writing Perl rather than C you could:

      for my $i (1 .. $k - 1) {
      True laziness is hard work
Re: problem in my sub partition
by jethro (Monsignor) on Nov 08, 2010 at 16:20 UTC

    Usually a warning tells you that there is a good chance that you have a bug or at least a problem that might bite you later in your program.

    As is the case here: Your loop control should be $i<$k, not $i<=$k, because $a[$k] is not defined. This bug luckily doesn't change the result and only leads to a warning

Re: problem in my sub partition
by Anonymous Monk on Nov 08, 2010 at 17:13 UTC
    Without changing your logic, here is how I would write your program, filtered through
    perltidy -csc -otr -opr -ce -nibc -i=4
    #!/usr/bin/perl -- use strict; use warnings; Main(); exit(0); sub Main { my @a; for ( 0 .. 10 ) { print Dumpyh( @a = yh(@a) ); } } ## end sub Main sub yh { my (@a) = @_; my @b = (1); #~ for ( my $i = 1 ; $i < @a ; $i++ ) { for my $i ( 1 .. $#a ) { $b[$i] = $a[$i] + $a[ $i - 1 ]; } $b[@a] = 1; return @b; } ## end sub yh sub Dumpyh { #~ return @_, "\n"; #~ return "@_\n"; my $s = "@_"; join '', ' ' x ( abs( 40 - length $s ) / 2 ), "$s\n"; } ## end sub Dumpyh __END__ 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1 1 8 28 56 70 56 28 8 1 1 9 36 84 126 126 84 36 9 1 1 10 45 120 210 252 210 120 45 10 1
    Notice how I'm using the narrowest possible scope for my variables.

    Tutorials: Arrays: A Tutorial/Reference, Variables and Scoping, Context tutorial

Re: problem in my sub partition
by Fletch (Bishop) on Nov 08, 2010 at 20:09 UTC

    Converting to a HOP-style iterator left as an exercise.

    (defn lazy-triangle ([] (cons [1] (lazy-triangle [1]))) ([row] (let [pairs (partition 2 1 row) next-row (concat [1] (map #(apply + %) pairs) [1])] (lazy-seq (cons (vec next-row) (lazy-triangle next-row)))))) ;; ;; user=> (pprint (take 10 (lazy-triangle))) ;; ([1] ;; [1 1] ;; [1 2 1] ;; [1 3 3 1] ;; [1 4 6 4 1] ;; [1 5 10 10 5 1] ;; [1 6 15 20 15 6 1] ;; [1 7 21 35 35 21 7 1] ;; [1 8 28 56 70 56 28 8 1] ;; [1 9 36 84 126 126 84 36 9 1]) ;;

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: problem in my sub partition
by poolpi (Hermit) on Nov 09, 2010 at 08:54 UTC
Re: problem in my sub partition
by GrandFather (Saint) on Nov 10, 2010 at 00:50 UTC

    That is better written using Perl than C. Consider:

    #!/usr/bin/perl use strict; use warnings; my @row; print "1\n"; for (0 .. 10) { @row = yh(@row); print "@row\n"; } sub yh { my @prevRow = @_; my @nextRow = 1; if (@prevRow) { for my $i (1 .. $#prevRow) { $nextRow[$i] = $prevRow[$i - 1] + $prevRow[$i]; } } push @nextRow, 1; return @nextRow; }

    Prints:

    1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1 1 8 28 56 70 56 28 8 1 1 9 36 84 126 126 84 36 9 1 1 10 45 120 210 252 210 120 45 10 1 1 11 55 165 330 462 462 330 165 55 11 1
    True laziness is hard work