in reply to John Guttag's book - 2nd exercise. My attempt in Perl.

Maybe this subroutine:
use strict; use warnings; my @array = (-11,-13,4, 22, 17); print find_max_odd(@array), "\n"; sub find_max_odd { my $max; while ($max = shift) { last if $max % 2; } return "Not found" unless @array; while (my $current = shift) { next unless $current % 2; if ($current > $max) { $max = $current; } } return $max; }
Update: As pointed out by AnoMonk below, these while loops have a bug when one of the array item is 0.I suggest a better for loop in another post below.

Replies are listed 'Best First'.
Re^2: John Guttag's book - 2nd exercise. My attempt in Perl.
by KurtZ (Friar) on May 20, 2017 at 22:12 UTC
    you can avoid the first loop if you change

    if ($current > $max) {

    to

    if ( not defined $max or $current > $max) {

    $max would simply stay undef if all values were even.


    no it's more complicated ... wait
    This should do:
    use strict; use warnings; my @array = ( -11, -13, 4, 22, 17); print "Result: ",find_max_odd(@array) // "undefined", "\n"; sub find_max_odd { my $max; for (@_) { next unless $_ % 2; unless ( defined $max ) { $max = $_; next; } $max = $_ if $_ > $max; } return $max; }

    I was confused, but becaus eof short-circuiting of the or the first idea should do too:
    use strict; use warnings; my @array = (-11,-13,4, 22, 17); print find_max_odd(@array), "\n"; sub find_max_odd { my $max; while (my $current = shift) { next unless $current % 2; if (not defined $max or $current > $max) { $max = $current; } } return $max // "undefined"; }
      Yeah, KurtZ, I definitely agree with you that it can be made simpler (++), and I most likely wouldn't code this the way I have shown.

      I only suggested a solution that used only very basic Perl knowledge since it was what the OP was asking for. Also, having two loops did not bother me too much, since they're browsing the array items only once anyway.

Re^2: John Guttag's book - 2nd exercise. My attempt in Perl.
by Anonymous Monk on May 22, 2017 at 18:03 UTC
    Should while (my $current = shift) be  while ( defined( my $current = shift ) ) ? Otherwise it seems to fail if @array contains 0.
      Yes, Anonymous Monk, you're correct, this while loop has a bug when one of the values in the array is 0.

      IMHO, this array traversal should really be made with a for loop, as it is usually better to use a for loop to iterate over an array, but the OP did not specify very clearly what was authorized and what not.

      This is what it might look like with a for loop.

      use strict; use warnings; my @array = (-11,-13,4, 22, 17); print find_max_odd(@array), "\n"; sub find_max_odd { my $max; for my $num (@_) { next unless $num % 2; $max = $num unless defined $max; $max = $num if $num > $max; } return defined $max ? $max : "No odd number found\n"; # this co +uld be replaced with if conditional statements if needed }