### 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{ ]};
``````

(Full code on Github.)

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{ ]};
``````

(Full code on Github.)

#### 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 #

##### Example:
``````Input: \$S = '35'

Output: ["dj", "dk", "dl", "ej", "ek", "el", "fj", "fk", "fl"].
``````

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{]};
``````

(Full code on Github.)

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{]};
``````

(Full code on Github.)