# Raku Solutions Weekly Review

## Getting in Touch

Email › Email me (Andrew) with any feedback about this review.

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

Twitter › Join the discussion on Twitter!

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

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

## Task 1. Words Length

The first task this week is quite simple. And as always in such cases, more people submitted their solutions :-) The task is to find the total number of characters in the phrase excluding its first and the last words. Not quite clear if we should also ignore punctuation, but that’s a separate question.

In Raku, we can use the `words`

method that splits the phrase into words, after which take a slice to extract the elements with indices from `1`

to `*-2`

. After that point, different approaches are possible: either get the lengths of all the words and add them up or join the words and then take the total length in one go.

The first branch gives solutions similar to this one:

```
$s.words[1 .. *-2]>>.chars.sum.say;
```

The second approach leads to the following code:

```
$S.words[1..*-2].join.chars;
```

Alternatively, you can remove those non-wanted words and spaces using a regex, and then take the lengths of what’s left:

```
$_ = $str;
s:g/^ \s* \S+ | \S+ \s* $ | \s+//;
say $_.chars;
```

Or you can `map`

the words and exploit side effects of executing a code block. This example is a good start to study the facilities for parallel computing that Raku offers. Think about how to add `race`

and atomic operations to this program:

```
my $stringlen = 0 ;
@words[1..$arraylen - 2].map( {$stringlen += $_.chars } ) ;
say $stringlen ;
```

An alternative approach is to find the positions of all spaces and use a simple formula to find the length of the words we need:

```
sub words-length (Str $s) {
my @w = $s.trim.indices(' ');
return @w.elems == 0 ?? 0 !! @w.tail - @w.head - @w.elems + 1;
}
```

### Video review

The full review of Task 1 is available on YouTube:

The timestamps for quick access to the review of each solution.

- 00:59 - Andrew Shitov
- 02:16 - Arne Sommer
- 03:12 - Jan Krnavek
- 04:38 - Kang-min Liu
- 07:25 - Mark Anderson
- 07:59 - Markus Holzer
- 08:26 - PJ Durai
- 09:22 - Simon Proctor
- 10:44 - Stuart Little
- 11:25 - Athanasius
- 12:51 - Colin Crain
- 14:04 - Daniel Mita
- 17:09 - Jaldhar H. Vyas
- 19:13 - Julio de Castro
- 20:13 - Laurent Rosenfeld
- 20:44 - Myoungjin Jeon
- 22:54 - Roger Bell_West
- 23:51 - Ulrich Rieke

## Task 2. Flip Array

In the second task, you had to take an array of positive integers. For some of them, you can alter the sign. In the end, add the numbers up to get the minimum possible but non-negative sum. The solution with the minimum sum and the minimum number of sign flips wins.

On a bigger scale, we can split the solutions into three groups. In the first, we simply try to find all possible combinations of `+`

and `-`

. In the second, we split the numbers into two groups, one of which comes with `+`

, while another with `-`

.

The first type of solution is easily implemented with the help of binary representation of the numbers from 0 to *2 ^{n} - 1*, where

*n*is the size of input data. Zero bits can represent a

`+`

, and set bits would stand for `-`

. Having the bits in an array, you can use Raku’s `Z`

operator to multiply data items:```
my $sum = [+] @bits>>.subst(0, -1) Z* @a;
```

Splitting the items into two groups can be done with testing all `combinations`

:

```
for @arr.combinations($k) -> $c {
my $new_sum = $base_sum - 2 * $c.sum;
if 0 <= $new_sum < $min {
$min = $new_sum;
$pick = $c;
}
}
```

Note that in this fragment, the minus sign is indirectly applied by subtracting the values twice.

There’s also a completely different approach with recursion. Here is the idea:

```
sub do_it (@left, @right is copy) {
my $current = @right.shift;
# . . .
do_it((@left, $current).flat, @right);
do_it((@left, -$current).flat, @right);
}
```

As you see, on each step, two branches are tested: in one, the next item is added with a `+`

, while in the other with `-`

.

From the other interesting solutions, let me highlight the usage of Raku’s built-ins. [Using `classify`

routine:

```
my &less-than-zero = *.grep: * < 0;
say +less-than-zero # find and count all negative numbers of
( [X] map { +$_, -$_ }, @A ) # all possible candidates
.classify( *.sum ) # grouped by sum
.grep( *.key > -1 ) # filtered where sum is positive
.sort( *.key ) # sorted by sum
.head.value # closest to zero
.min( &less-than-zero ) # the one with the least flips
```

```
sub cmpair($cap) {
return -> @a, @b {
(@b.sum <= $cap) ?? max(@a,(@b.sum,-@b.elems)) !! @a;
}
}
say -reduce(cmpair(@*ARGS.sum/2), (0,0), |@*ARGS.combinations).[1];
```

Explore the rest of the code in the below video review!

### Video review

The full review of Task 2 is available on YouTube:

The timestamps to the reviews of the individual solutions:

- 01:09 - Andrew Shitov
- 04:19 - Arne Sommer
- 09:55 - Jan Krnavek
- 12:00 - Kang-min Liu
- 15:02 - Mark Anderson
- 17:18 - Markus Holzer
- 19:58 - PJ Durai
- 21:55 - Simon Proctor
- 26:36 - Stuart Little
- 29:12 - Athanasius
- 32:26 - Colin Crain
- 34:32 - Daniel Mita
- 35:58 - Jaldhar H. Vyas
- 39:21 - Julio de Castro
- 43:22 - Laurent Rosenfeld
- 47:25 - Myoungjin Jeon
- 50:44 - Roger Bell_West
- 51:45 - Ulrich Rieke

If you want to participate in **The Weekly Challenge**, please contact us at perlweeklychallenge@yahoo.com.