Perl Weekly Challenge 053: Rotate Matrix and Vowel Strings

Rotate Matrix

Write a script to rotate the following matrix by given 90/180/270 degrees clockwise.
[ 1, 2, 3 ]
[ 4, 5, 6 ]
[ 7, 8, 9 ]

For example, if you rotate by 90 degrees then expected result should be like below

[ 7, 4, 1 ]
[ 8, 5, 2 ]
[ 9, 6, 3 ]

The easiest way to work with multidimensional data in Perl is PDL. Interestingly, I haven’t found a direct method to rotate a matrix in this way.

What I have found, though, was a method to transpose a matrix, which means to switch the columns and rows. The result for the sample input is

Perl Weekly Challenge 052: Stepping Numbers & Lucky Winner

Stepping Numbers

Write a script to accept two numbers between 100 and 999. It should then print all Stepping Numbers between them.

A number is called a stepping number if the adjacent digits have a difference of 1. For example, 456 is a stepping number but 129 is not.

The naive approach would be to iterate over all the numbers from 100 to 999 and check the difference between each adjacent digits.

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

NUMBER: for my $n (100 .. 999) {
    my @digits = split //, $n;
    for my $i (1 .. $#digits) {
        next NUMBER
            unless 1 == abs($digits[$i - 1] - $digits[$i]);
    }
    say $n;
}

In fact, for the given range this is enough. But if we try to print all the stepping numbers of length 7 (1_000_000 .. 9_999_999), it takes more than 10 seconds.

Perl Weekly Challenge 051: 3 Sum and Colourful Numbers

3 Sum

Given an array @L of integers. Write a script to find all unique triplets such that a + b + c is same as the given target T. Also make sure a <= b <= c.

Here is wiki page for more information.

Example:

@L = (-25, -10, -7, -3, 2, 4, 8, 10);

One such triplet for target 0 i.e. -10 + 2 + 8 = 0.

I hadn’t checked the wiki page before writing my solution; and I hadn’t changed the solution after I read it. Therefore, it presents the naive and inefficient solution that iterates over all the possible triplets (but not starting from 0 in the inner loops to avoid checking the same triplet several times).

Perl Weekly Challenge 050: Merge Intervals and Noble Integer

Merge Intervals

Write a script to merge the given intervals where ever possible.
[2,7], [3,9], [10,12], [15,19], [18,22]

The script should merge [2, 7] and [3, 9] together to return [2, 9].

Similarly it should also merge [15, 19] and [18, 22] together to return [15, 22].

The final result should be something like below:

[2, 9], [10, 12], [15, 22]

This sounds so similar to PWC 039 I first thought I could solve it in the same way. Unfortunately, Set::IntSpan gives a different result:

#!/usr/bin/perl
use warnings;
use strict;

use Set::IntSpan;

my @intervals = ([2, 7], [3, 9], [10, 12], [15, 19], [18, 22]);

my $set = 'Set::IntSpan'->new([@intervals]);

print $set; # 2-12,15-22

The reason is that the module only considers integers. There’s no integer between 9 and 10, so the spans 2-9 and 10-12 can be merged into one span 2-12.

Perl Weekly Challenge 049: Smallest Multiple and LRU Cache

Smallest Multiple

Write a script to accept a positive number as command line argument and print the smallest multiple of the given number consists of digits 0 and 1.

For example: For given number 55, the smallest multiple is 110 consisting of digits 0 and 1.

The simplest naive solution is to start from the input number, keep adding it to itself until the result consists of 0's and 1's exclusively.

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my $x = shift;
say "$x ", smallest_multiple($x);

sub smallest_multiple {
    my ($n) = @_;
    my $r = $n;
    $r += $n until $r =~ /^[01]+$/;
    $r
}

The problem of this solution is that it’s very slow for multiples of 9, as the result of the function is a very large number (111_111_111 for 9, 111_111_111_111_111_111 for 99).