Hey there, there’s another task #066-1 offered by the Perl Weekly Challenge (why still not mentioning Raku in the name?).

*Integer-divide the two given integers, $m and $n, without using multiplication, or division, or modulo.*

So, for `5 / 2`

you get 2, -2 for `-5 / 2`

, and 2 for `-5 / -2`

. Actually, from the task definition, the floor of `-5 / 2`

would be -3, while the expected result is -2:

$ raku -e'say (-5/2).floor' -3

But let’s stick to the provided examples (which makes the solution simpler but not always correct :-). The goal is to demonstrate string-vs-integer transformations.

## 1

Obviously, division is subtraction repeated the required number of times, so one can subtract until the initial number vanishes and count the number of loops. So, here’s the straightforward solution:

my $m = 5; my $n = 2; my $r = 0; while $m >= $n { $m -= $n; $r++; } say $r;

It works but does not look elegant enough. The implicit operations with the counter should be done somehow indirectly.

## 2

What if using the sequence operator? Provide it with a pattern, and it should deduce the sequence itself. As we expect that the division gives some reminder (as in the `5 / 2`

example), you cannot rely on the sequence operator to stop by itself, so we need to explain what is the condition to continue rolling:

say ($m, $m - $n ... * < $n) - 1;

Here, the `...`

operator gets the two first elements of the sequence `$m`

and `$m - $n`

. Thus, it continues to subtract `$n`

while the current number (`*`

) is less than `$n`

(which means while it is big enough to be subtracted).

## 3

What about the sign? As we are not allowed to use proper math operations, let us use the power (here, *power* means *strength* and not `**`

) of Raku to easily convert between numbers and string representation of an object.

print '-' if +($m ~ $n ~~ m:g/'-'/) == 1;

Woohoo, what’s going on here? First, we concatenate the numbers as strings, so -5 and 2 are transformed to `-52`

, -5 and -2 to `-5-2`

, and 5 and 2 to `52`

. Ah, yes, 5 and -2 become `5-2`

. Half of these cases give negative result, the rest is positive. As we do not need to print a plus, we are only interested in the cases when the number of `'-'`

characters is odd, and that odd number can only be `1`

.

Match the concatenated string against the regex `m:g/'-'/`

, and you get either `｢-｣`

or `(｢-｣ ｢-｣)`

or `()`

. Print the minus sign when you have only one element after regex matching.

Of course, minuses should not be considered in our sequence, so the whole program looks like this:

my $m = 5; my $n = -2; print '-' if +($m ~ $n ~~ m:g/'-'/) == 1; say ($m.abs, $m.abs - $n.abs ... * < $n.abs) - 1;

Or even remove the signs in one go:

print '-' if +($m ~ $n ~~ m:g/'-'/) == 1; ($m, $n)>>.=abs; say ($m, $m - $n ... * < $n) - 1;

## 4

Not enough strings? Let us use them more intensively. Convert the numbers to the strings containing as many characters as the value of the number is.

$m = 'N' x $m; $n = 'N' x $n;

Again, a global regex match counts the number of sequences of new `$n`

that can be placed inside the new `$m`

.

say +($m ~~ m:g/$n/);

The reader should be trained enough to compete the solution to allow both positive and negative inputs:

my $m = -9; my $n = -2; $m = 'N' x $m.abs; $n = 'N' x $n.abs; print '-' if +($m ~ $n ~~ m:g/'-'/) == 1; say +($m ~~ m:g/$n/);

## One thought on “Raku string vs integer practices”