## Andrew Shitov Weekly Review: Challenge - 082

Sunday, Oct 25, 2020| Tags: Raku

# Raku Solutions Weekly Review

## Getting in Touch

GitHub › Submit a pull request for any issues you may find with this page.

We’d greatly appreciate any feedback you’d like to give.

Welcome to the Raku Review for Week 082 of The Weekly Challenge!. For a quick overview, go through the original tasks and recap of the weekly challenge.

In the first task, we had to find common factors of two integer numbers. The solutions submitted can be roughly classified into a few categories:

• With two greps
• By intersection of factors
• Employing the GCD
• With junctions

### Using a row of `grep`s

In this kind of solutions, the range of numbers is first filtered to take the numbers by which `\$A` is divisible, and then the second filter is applied to do the same for `\$B`. The remaining numbers are the numbers in question.

For example, in my solution, we see:

``````    say ((1 .. (\$a max \$b)).grep: \$a %% *).grep: \$b %% *;
``````

### Intersection of lists of factors

Here, the first step is to find all the factors for each input number independently and then compute their intersection. Of course, using Raku’s operator `(&)` for set intersection.

In the program by Arne Sommer:

``````    my @M-factors = \$include-self ?? (1..\$M).grep({ \$M %% \$_ }) !! (1..\$M/2).grep({ \$M %% \$_ });
my @N-factors = \$include-self ?? (1..\$N).grep({ \$N %% \$_ }) !! (1..\$N/2).grep({ \$N %% \$_ });

my %common = @M-factors (&) @N-factors;
``````

Or the same operator but spellt out as a Unicode symbol `∩` as Jaldhar H. Vyas did it:

``````    sub MAIN(Int \$M, Int \$N) {
(factors(\$M) ∩ factors(\$N)).keys.sort.join(', ').say;
}
``````

Simon Proctor demonstrates another example of this approach:

``````    sub MAIN ( UInt \$M, UInt \$N ) {
say "({(fac(\$M) (&) fac(\$N)).keys.sort.join(', ')})"
}

sub fac( UInt \$v ) {
(1..^\$v).grep( \$v %% * )
}
``````

Notice how the whole line of Raku code is interpolated in curly braces inside a double-quoted string.

By the way, in a couple of solutions, finding the factors is optimised to take two factors at once if possible. Examine the `take` parts of Colin Crain’s solution:

``````    sub factor (Int \$num) {
gather {
for (1..\$num.sqrt.Int).grep({\$num %% \$_}) {
take \$_;
take \$num div \$_;
}
}
}
``````

### With the help of GCD

GCD, or greatest common divisor, is available as a built-in routine in Raku.

Instead of finding the divisors for `\$A` or `\$B`, you can find them for their GCD only, as you can see in the solution submitted by Jan Krňávek:

``````    sub common-factors( +@a ) {
my \$gcd = [gcd] @a;
1, 2 ... \$gcd
andthen .grep:  \$gcd %% *
}
``````

Or in Kang-min Liu’s program:

``````    sub common-factors (Int \$a, Int \$b) {
my \$x = \$a gcd \$b;
return (1..\$x).grep(-> \$n { \$x %% \$n });
}
``````

Mark Andreson expressed the same idea using a `WhateverCode` block instead of a pointy block with an explicit signature:

``````    my \$gcd = \$M gcd \$N;
say (1..\$gcd).grep(\$gcd %% *).join(", ").List;
``````

Philip Hood showed an unexpected way of making some computations directly in the signature of the `MAIN` function:

``````    sub MAIN( Int \$m = 18, Int \$n = 12, \$gc = \$m gcd \$n ) {
die( "too many args!" ) if @*ARGS.end > 1;
( 1 .. \$gc ).grep(-> \$k { \$gc %% \$k } ).say;
}
``````

This trick can probably be used in a Raku Golf contest.

Laurent Rosenfeld added another improvement to check if the found value of GCD is a prime number:

``````    sub common_factors (Int \$a, Int \$b) {
my \$gcd = \$a gcd \$b;
return (1,) if \$gcd == 1;
return (\$gcd,) if \$gcd.is-prime;
return (1..\$gcd).grep(\$gcd %% *).unique;
}
``````

### Using junctions

The next group includes solutions that use junctions.

For example, look at Feng Chang’s code and the use of `&`:

``````    (1..min(\$M,\$N)).grep({ (\$M & \$N) %% \$_ }).say;
``````

Markus Holzer reminds us that there’s an alternative form of creating junctions by using the built-in routine `all`:

``````    say "({ join ', ', grep all( \$N, \$M ) %% *, 1 ..^ max \$N, \$M })"
``````

### Bonus slide

The solution that was submitted by Julio de Castro requires special mentioning. A lot of `-o fun` things happen here:

``````    sub prefix:<∕>(\num) {
(1 ... num/2, +num).grep: num %% *
}

# intersects and returns result as sorted list
sub infix:<@∩>(\a, \b) {
(a ∩ b).keys.sort.list
}

sub MAIN(Int \a where * > 0, Int \b where * > 0) {
say ∕a @∩ ∕b
}
``````

### Video review

This task was understood a bit differently by the participants. The main questions are, first, whether it is possible to only insert `\$B` into `\$A`, or the opposite is also allowed. The second idea is if we can split one or both of the input strings into smaller parts before searching for the result.

Let me not run through the solutions and their types here, but I still want to show you the output of the program by Athanasius. In the ‘Explanation’ section, you clearly see how the result was achieved:

``````\$ raku challenge-082/athanasius/raku/ch-2.raku XXY XXZ XXXXYZ

Challenge 082, Task #2: Interleave String (Raku)

Input:
\$A = "XXY"
\$B = "XXZ"
\$C = "XXXXYZ"

Output: 1

EXPLANATION
\$A =  XX  Y
\$B =    XX Z
\$C =  XXXXYZ
``````

You will find more details about the solutions and other interesting findings there in the video review below.