Perl Weekly Challenge 088

Another week, another challenge and chance to practice Perl and Python programming skills.

Challenge 1 - Array of Product:

You are given an array of positive integers @N.

Write a script to return an array @M where $M[i] is the product of all elements of @N except the index $N[i].

This one was quite straightforward. My first idea was to loop through the array and calculate the products using slicing of the array.

Then I realized it is easier to calculate the product once and then just divide it by each number.

  1. Calculate the Product:

Perl - using product function from List::Util:

my $product = product(@$in_arr);

Python:

product = 1
for i in in_arr:
    product *= i
  1. Push the result to the return array.

Perl:

push @out_arr, int($product / $_) for (@$in_arr);

Python:

for item in in_arr:
        out_arr.append( product // item )

Challenge 2: Spiral Matrix

You are given m x n matrix of positive integers.

Write a script to print spiral matrix as list.

If you want to think like a robot traversing enemy area, you have to become a robot.

I liked this exercise as there will be certainly similar in the coming Advent Of Code!

I decided to be in the position of a robot crawling the array, going in a direction as far as I can and then change the direction at the end. At the same time keep track of the fields I have seen.

From the code:

  1. Initialize the max dimensions, current position, seen cells and the return array.

Perl:

my $x_max = scalar @$in_arr;
my $y_max = scalar @{$in_arr->[0]};

my @pos = (0, 0);
my $direction = ">";

my %seen_cells;
my @out_arr;

Python:

x_max = len(in_arr)
y_max = len(in_arr[0])

pos = [0,0]
direction = ">"

seen_cells = {}
out_arr = []
  1. Look indefinitely when there are still some fields we have not seen - if so, push the field to the return array and remember we have seen it. If everything has been seen, return the array.

Perl:

while (1) {

    return \@out_arr if scalar @out_arr == $x_max * $y_max;

    push @out_arr, $in_arr->[$pos[0]][$pos[1]] unless $seen_cells{$pos[0]}{$pos[1]};
    $seen_cells{$pos[0]}{$pos[1]} = 1;

Python:

while 1:

        if len(out_arr) == x_max * y_max:
            return out_arr

        if seen_cells.get((pos[0], pos[1]), 0 ) == 0:
            out_arr.append(in_arr[pos[0]][pos[1]])

        seen_cells[(pos[0], pos[1])] = 1
  1. Check if we can continue in the same direction, otherwise change the direction.

Perl - example for going to the right “>”:

# can move in the direction we are walking?
if ($direction eq ">") {
    if (($pos[1] + 1 < $x_max) and not ($seen_cells{$pos[0]}{$pos[1]+1})) {
        $pos[1]++;
    } else {
        $direction = "v";
    }
}

Python:

if direction == ">":
    if (pos[1] + 1 < x_max) and not (seen_cells.get( (pos[0], pos[1]+1), 0) ):
        pos[1] += 1
    else:
        direction = "v"

Test cases were added to both exercises to make sure it passes the requirements.

Complete code in Github!

Many thanks for the challenges this week, looking forward to the next ones!