# RabbitFarm

## Part 1

You are given a string \$S with 3 or more words. Write a script to find the length of the string except the first and last words ignoring whitespace.

### Solution

``````
use strict;
use warnings;
##
# You are given a string \$S with 3 or more words.
# Write a script to find the length of the string
# except the first and last words ignoring whitespace.
##
sub count_most_words{
my (\$s) = @_;
my \$count = 0;
my @a = split(/\s/, \$s);
map {\$count += tr/a-zA-Z//d} @a[1 .. (@a - 2)];
return \$count;
}

MAIN:{
my \$S;
\$S = "The Weekly Challenge";
print "\$S --> " . count_most_words(\$S) . "\n";
\$S = "The purpose of our lives is to be happy";
print "\$S --> " . count_most_words(\$S) . "\n";
}
``````

### Sample Run

``````
\$ perl perl/ch-1.pl
The Weekly Challenge --> 6
The purpose of our lives is to be happy --> 23
``````

### Notes

Anytime I need to count characters I immediately think of tr. `tr` will, of course, do character replacements but it’s return value is the number of characters which have been effected. Here with the `d` option the matching characters are just deleted. This code would work exactly just as well with the `d` but I figured it’d be actually less confusing to have it there and make it more clear what it was doing.

## Part 2

You are given an array @A of positive numbers. Write a script to flip the sign of some members of the given array so that the sum of the all members is minimum non-negative.

``````
use strict;
use warnings;
##
# You are given an array @A of positive numbers.
# Write a script to flip the sign of some members
# of the given array so that the sum of the all
# members is minimum non-negative.
##
sub try_all_flips{
my(@a) = @_;
my @minimum = (undef, undef, []);
for my \$i (0 .. (2**(@a) - 1)){
my \$b = sprintf("%0" . @a . "b", \$i);
my @b = split(//, \$b);
my \$flip_count = 0;
map {\$flip_count++ if \$_ == 1} @b;
my @f;
for my \$i (0 .. (@b - 1)){
if(\$b[\$i] == 1){
push @f, (-1) * \$a[\$i];
}
else{
push @f, \$a[\$i];
}
}
my \$sum = unpack("%32I*", pack("I*", @f));
if(!defined(\$minimum[0]) || (\$sum <= \$minimum[0] && \$sum >= 0)){
if(defined(\$minimum[0]) && \$sum == \$minimum[0] && \$flip_count < \$minimum[1]){
\$minimum[0] = \$sum;
\$minimum[1] = \$flip_count;
\$minimum[2] = \@f;
}
elsif(!defined(\$minimum[0])){
\$minimum[0] = \$sum;
\$minimum[1] = \$flip_count;
\$minimum[2] = \@f;
}
elsif(\$sum < \$minimum[0]){
\$minimum[0] = \$sum;
\$minimum[1] = \$flip_count;
\$minimum[2] = \@f;
}
}
}
return @minimum;
}

MAIN:{
my @A;
my @minimum;
@A = (3, 10, 8);
@minimum = try_all_flips(@A);
print "[". join(", ", @A) . "] --> ";
print  " [". join(", ", @{\$minimum[2]}) . "] = " . \$minimum[0] ."\n";
@A = (12, 2, 10);
@minimum = try_all_flips(@A);
print "[". join(", ", @A) . "] --> ";
print  " [". join(", ", @{\$minimum[2]}) . "] = " . \$minimum[0] ."\n";
}
``````

### Sample Run

``````
\$ perl perl/ch-2.pl
[3, 10, 8] -->  [3, -10, 8] = 1
[12, 2, 10] -->  [-12, 2, 10] = 0
``````

### Notes

This is a brute force approach. I use the same method for generating all combinations that I used in Challenge 077 with the variation that here I use the generated combination to determine which elements of the list are to be flipped. After calculating the sum of each new list (with flipped elements) I check to see if this is a new minimum positive value and, if so, if it has been done with fewer flips.

posted at: 01:01 by: Adam Russell | path: /perl | permanent link to this entry