Perl Weekly Challenge #61, with answers reversed because I want to.

### TASK #2 › IPv4 Partition

Reviewed by: Ryan Thompson

You are given a string containing only digits (0..9). The string should have between 4 and 12 digits.

Write a script to print every possible valid IPv4 address that can be made by partitioning the input string.

For the purpose of this challenge, a valid IPv4 address consists of four “octets” i.e. A, B, C and D, separated by dots (.).

Each octet must be between 0 and 255, and must not have any leading zeroes. (e.g., 0 is OK, but 01 is not.)

Example Input: `25525511135`

Output:

`255.255.11.135`

`255.255.111.35`

Should we still deal with IPv4 addresses anymore? Vint Cerf argues no.

Source

But, since it’s the challenge, let’s go.

``````#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use feature qw{ postderef say signatures state switch };
no warnings qw{ experimental };

my \$input = '25525511135';
(\$input) = \$ARGV[0] =~ /(\d+)/ if defined \$ARGV[0];
my @input  = split //, \$input;
my \$output = '';

say join "\n\t", "\$input =>", ipv4_partitions( \$output, @input );

sub ipv4_partitions ( \$output, @input ) {

# this block ensures we only have "good" addresses go through
# * no .1.1.1.1
# * only four numbers
# * only three periods
# * no number greater than 255
#   ( because only digits, no need to block negatives)
# * no zero-pads - 0 is fine, 04 is not
return if \$output =~ /^\./;
return if 4 < scalar split /\./, \$output;
return if grep { int \$_ > 255 } split /\./, \$output;
return if grep { length \$_ > 3 } split /\./, \$output;
return if grep { \$_ =~ /0\d/ } split /\./, \$output;
my @zed;

# if there's still digits to fit
if ( scalar @input ) {
my \$next = shift @input;
push @zed, ipv4_partitions( qq{\$output\.\$next}, @input );
push @zed, ipv4_partitions( qq{\$output\$next},   @input );
}
else {
# handles non-\d+.\d+.\d+.\d+ cases
return if 4 != scalar split /\./, \$output;
push @zed, \$output;
}
return @zed;
}
``````

There’s one IP address that I doubt I ever will forget, which is for the main DNS server for my former school and workplace. This is a good example because it shows what is and isn’t allowed with zeroes.

``````./ch-2.pl 128210115
128210115 =>
1.28.210.115
12.8.210.115
12.82.10.115
128.2.10.115
128.21.0.115
128.210.1.15
128.210.11.5
``````

### TASK #1 › Product SubArray

Reviewed by: Ryan Thompson

Given a list of 4 or more numbers, write a script to find the contiguous sublist that has the maximum product. The length of the sublist is irrelevant; your job is to maximize the product.

Example

Input: `[ 2, 5, -1, 3 ]`

Output: `[ 2, 5 ]` which gives maximum product `10`.

I’m usng JSON to format the output.

``````\$ ./ch-1.pl 2 5 1 5  2
["2","5"]
``````

Both `[2,5]` and `[5,2]` are valid as max, but we return `[2,5]` because it comes first.

``````#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use feature qw{ postderef say signatures state switch };
no warnings qw{ experimental };

use JSON;
my \$json = JSON->new;

my @numbers = @ARGV;
@numbers = ( 2, 5, -1, 3 ) if scalar @ARGV < 4;

my @array = product_subarray(@numbers);
say \$json->encode(@array);
exit;

sub product_subarray ( @numbers ) {
my @output;
for my \$i ( 1 .. \$#numbers ) {
my \$j       = \$i - 1;
my \$product = \$numbers[\$j] * \$numbers[\$i];
push @output, { p => \$product, n => [ \$numbers[\$j], \$numbers[\$i] ], };
}
my (\$output) = sort { \$b->{p} <=> \$a->{p} } @output;
return \$output->{n};
}
``````