Perl Weekly Challenge: Week 67
Challenge 1:
Number Combinations
You are given two integers
$m
and$n
. Write a script print all possible combinations of$n
numbers from the list 1 2 3 … $m.Every combination should be sorted i.e. [2,3] is valid combination but [3,2] is not.
Example:
Input: $m = 5, $n = 2 Output: [ [1,2], [1,3], [1,4], [1,5], [2,3], [2,4], [2,5], [3,4], [3,5], [4,5] ]
In Raku we can do this as a one-liner:
say q{[ }, (1 .. $m).combinations($n).map({ q{[} ~ @_.join(q{,}) ~ q{]} }).join(q{, }), q{ ]};
If we just wanted the answer it would be even simpler but formatting it exactly as the spec has it requires a little extra code.
Perl is a little trickier because it doesn't have a .combinations()
method like Raku does. Luckily I could
reuse my clone from challenge 38.
With that, the Perl version also becomes quite simple.
my @result = combinations([1 .. $m], $n);
say q{[ }, (join q{, }, map { q{[} . (join q{,}, @{$_}) . q{]} } @result), q{ ]};
Challenge 2:
Letter Phone
You are given a digit string
$S
. Write a script to print all possible letter combinations that the given digit string could represent.
1_,@ | 2ABC | 3DEF |
4GHI | 5JKL | 6MNO |
7PQRS | 8TUV | 9WXYZ |
∗ ␣ | 0 | # |
(I had way too much fun making that dialpad.)
Example:
Input: $S = '35' Output: ["dj", "dk", "dl", "ej", "ek", "el", "fj", "fk", "fl"].
Once again let's start with Raku.
I made a hash mapping digits to arrays of possible values.
my %digits =
1 => < _ , @ >,
2 => < a b c >,
3 => < d e f >,
4 => < g h i >,
5 => < j k l >,
6 => < m n o >,
7 => < p q r s >,
8 => < t u v >,
9 => < w x y z >,
0 => [ q{} ],
'*' => [ q{ } ],
'#' => [ q{} ],
;
As in the previous task, formatting the result just right makes the code a bit more complex
but the core is simple. The input string is split into individual digits. Each digit is mapped to an
array of values using %digits
and then the cross-product hyper operator [X]
is applied to the arrays
to give all the combinations.
say q{[}, ([X] $S.comb.map({ %digits{$_} })).map({ q{"} ~ @_.join({}) ~ q{"} }).join(q{, }), q{]};
For the Perl version, I also begin by building a digit to values map.
my %digits = (
1 => [ q{_}, q{,}, q{@} ],
2 => [qw/ a b c /],
3 => [qw/ d e f /],
4 => [qw/ g h i /],
5 => [qw/ j k l /],
6 => [qw/ m n o /],
7 => [qw/ p q r s /],
8 => [qw/ t u v /],
9 => [qw/ w x y z /],
0 => [ q{} ],
'*' => [ q{ } ],
'#' => [ q{} ],
);
Perl doesn't have [X]
like Raku but once again my replacement, most recently
seen in challenge 65 comes
to the rescue. It's use is a bit more convoluted than in Raku but it gets the job done.
my @letters = map { $digits{$_} } split //, $S;
my @result = @{ $letters[0] };
for my $i (1 .. (scalar @letters) - 1 ) {
@result = X(\@result, $letters[$i]);
}
All that remains by this point is to print out the result in the format used in the spec.
say q{[}, (join q{, }, map { q{"} . (join q{}, @{$_}) . q{"} } @result), q{]};