The Weekly Challenge - 267


TASK #1: Product Sign
You are given an array of @ints. Write a script to find the sign of product of all integers in the given array.

The sign is 1 if the product is positive, -1 if the product is negative and 0 if product is zero.

# Default: return 1 (product positive)
# - return 0, if the value 0 is found (product is always 0)
# - return -1 (negative product), if the number of negative values is odd
#!/usr/bin/perl
use strict;
use warnings;
#-------------------------------------------
sub product_sign {
	
    foreach (@_) {

        return 0 if ( grep {$_ == 0} @_ );
        return -1 if ( (my $n = grep {$_ < 0} @_) % 2 != 0 );

    }	
    return 1;    
}

# TESTS

my @ints = ();

# Example 1
@ints = (-1, -2, -3, -4, 3, 2, 1);
print(product_sign(@ints), "\n"); # Output: 1

# Example 2
@ints = (1, 2, 0, -2, -1);
print(product_sign(@ints), "\n"); # Output: 0

# Example 3
@ints = (-1, -1, 1, -1, 2);
print(product_sign(@ints), "\n"); # Output: -1

TASK #2: Line Counts
You are given a string, $str, and a 26-items array @widths containing the width of each character from a to z.

Write a script to find out the number of lines and the width of the last line needed to display the given string, assuming you can only fit 100 width units on a line.
# Method:
# - $widths[0] gives the width value of 'a' ... $widths[25] gives the width value of 'z'
# - The ASCII value of the character 'a' is 97 (= ord('a')). Subtracting 97 from ord('a') results in 0.
# - Therefore, $widths[(ord('a') - 97)] equals $width[0].
# - The ASCII value of the character 'z' is 122 (= ord('z'). Subtracting 97 from ord('z') results in 25.
# - Therefore, $widths[(ord('z') - 97)] equals $width[25].
# etc.
#!/usr/bin/perl
use strict;
use warnings;
#-------------------------------------------
sub line_counts {
	
    my ($str, @widths) = @_;
    my ($max_width_line, $width_line, $no_lines) = (100, 0, 1);

    # process each character in the given string $str
    foreach ( split(//, $str) ) {

        # increment $width_line with the width value of the current character $char: see above
        if ( ($width_line + $widths[(ord($_) - 97)]) <= $max_width_line) {  
        
            $width_line += $widths[(ord($_) - 97)];
        
        }    
        else {
            # a new line
            $no_lines++;
            # starting with the width value of the current character
            $width_line = $widths[(ord($_) - 97)];      
        }
    }
    print("($no_lines, $width_line)\n");    
}    

# TESTS

my $str;
my @widths = ();

# Example 1
$str = "abcdefghijklmnopqrstuvwxyz";
@widths = (10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10);
line_counts($str, @widths); # Output: (3, 60)

# Example 2
$str = "bbbcccdddaaa";
@widths = (4,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10);
line_counts($str, @widths); # Output: (2, 4)