This is my response to the Perl Weekly Challenge #066.

You are given two integers

Write a script to divide the given two integers i.e.

**Example 1**

**Example 2**

**Example 3**

`$M`

and `$N`

.
Write a script to divide the given two integers i.e.

`$M / $N`

without
using multiplication, division and mod operator and return the floor of the result
of the division.
Input: $M = 5, $N = 2
Output: 2

Input: $M = -5, $N = 2
Output: -3

Input: $M = -5, $N = -2
Output: 2

Division is just subtraction in a loop. Off we go. Off we go. Off we go...:

File: divint#! /usr/bin/env raku
unit sub MAIN (Int $M, Int $N where $N != 0, :$verbose); # [1]
my $count = 0; # [2]
my $negate = $M.sign != $N.sign; # [3]
my $M-abs = $M.abs; # [4]
my $N-abs = $N.abs; # [4]
while $M-abs >= $N-abs # [5]
{
$M-abs -= $N-abs; # [6]
$count++; # [7]
say "M: $M-abs N: $N-abs = $count (negate $negate)" if $verbose;
}
if $negate # [8]
{
$count = -$count; # [9]
$count-- if $M-abs; # [10]
}
say $count; # [2]

We have to take care of two things; the sign
and any remainder (but only if the sign is negative).
[1] Divison by zero is a bad thing, so we prevent that possibility for `$N`

.

[2] The result.

[3] The result is a negative integer if one and only one of `$M`

and `$M`

is neagtive, else it is positive. We use `sign`

to get the
sign (`-1`

, `0`

or `1`

).

[4] Are we counting *down to* - or *up to* - zero? That
depends on the sign. But we can count down if we ensure that both values are positive.
That is done with `abs`

, that removes any negative sign. The sign of the
result has been taken care of in [3].

[5] As long as the remainder is larger or equal to the divisor,

[6] • subtract the divisor.

[7] • increase the count, which is the end result.

[8] Should the answer be negative?

[9] • negate it.

[10] • subtract 1 (the «floor» part of the challenge description) if we have a remainder.

See
docs.raku.org/routine/sign for more
information about the `sign`

method.

See
docs.raku.org/routine/abs for more
information about the `abs`

method.

Running it:

$ raku divint 5 2
2
$ raku divint -5 2
-3
$ raku divint -5 -2
2
$ raku divint 5 -2
-3

With *verbose mode* (which would benefit from a rethink, me think...):

$ raku divint --verbose 5 2
: Negate the result: No
: M: 3 N: 2 = 1
: M: 1 N: 2 = 2
2
$ raku divint --verbose 25 2
: Negate the result: No
:M: 23 N: 2 = 1
:M: 21 N: 2 = 2
:M: 19 N: 2 = 3
:M: 17 N: 2 = 4
:M: 15 N: 2 = 5
:M: 13 N: 2 = 6
:M: 11 N: 2 = 7
:M: 9 N: 2 = 8
:M: 7 N: 2 = 9
:M: 5 N: 2 = 10
:M: 3 N: 2 = 11
:M: 1 N: 2 = 12
12

Perl does not have a «sign» function, so I wrote one. I chose to do command line handling manually. Other than that, the code is pretty much the same as the raku version. Except longer...

File: divint-perl#! /usr/bin/env perl
use feature 'say';
use feature 'signatures';
no warnings qw(experimental::signatures);
my $verbose = 0;
if (@ARGV && $ARGV[0] eq "--verbose")
{
$verbose++;
shift @ARGV;
}
my $M = shift(@ARGV) || die 'Specify $M and $N';
my $N = shift(@ARGV) || die 'Specify $N';
die '$M is not an integer' unless int($M) == $M;
die '$N is not an integer' unless int($N) == $N;
die "Unable to divide by zero" if $N == 0;
sub sign ($value)
{
return 1 if $value > 0;
return 0 if $value == 0;
return -1 if $value < 0;
}
my $count = 0;
my $negate = sign($M) != sign($N);
my $M_abs = abs($M);
my $N_abs = abs($N);
say ": Negate the result: ", $negate ? 'Yes' : 'No' if $verbose;
while ($M_abs >= $N_abs)
{
$M_abs -= $N_abs;
$count++;
say "M: $M_abs N: $N_abs = $count" if $verbose;
}
if ($negate)
{
$count = -$count;
$count-- if $M_abs;
}
say $count;

You are given an integer **m**^{n} where
**m** and **n** are positive integers. Otherwise print 0.

Please make sure

**BONUS: If there are more than one way to express the given number then print all possible
solutions.**

**Example 1**

For given^{2} or

**Example 2**

For given

**Example 3**

For given

`$N`

.
Write a script to check if the given number can be expressed as Please make sure

`m > 1`

and `n > 1`

.
For given

`$N = 9`

, it should print 3`3^2`

.
For given

`$N = 45`

, it should print `0`

.
For given

` $N = 64`

, it should print all or one of `8^2`

or `2^6`

or `4^3`

.
File: powint

#! /usr/bin/env raku
multi sub MAIN (Int $N where $N.is-prime, :$one) # [1] [2]
{
say 0;
}
multi sub MAIN (Int $N where $N > 1, :$one) # [3] [2]
{
my $match = 0; # [4]
for 2 .. $N.sqrt -> $base # [5]
{
for 2 .. Inf -> $exp # [6]
{
my $candidate = $base ** $exp; # [7]
last if $candidate > $N; # [8]
(say "$base^$exp"; $match++; exit if $one) if $candidate == $N; # [9]
}
}
say 0 unless $match; # [10]
}

[1] Prime numbers cannot be factoralized, so we can check for that (with
`is-prime`

) up front. This speeds up the program in case of prime numbers,
but isn' strictly necessary

[2] Use the «--one» command line option if you only want one result.

[3] The `where`

clause ensures that the value is as requested by the
challenge.

[4] Do we have a match (or more), so that we can give the «0» *error message*
in [10].

[5] Iterate over the base number, from 2 to the square root of the original number.
This will stop our loop when we have reached the largest number (for `$base`

)
that we can fit (in `$N`

) by squaring it.

[6] The exponent, as an infinite loop.

[7] A possible answer?

[8] If the possible answer is higher than the initial value, we can abort the inner (infinite) loop.

[9] We have a match, print it, count it, and exit if we only wanted one result. Note
the funny use of parens (the grouping operator) to stack more than one expressions into
a postfix `if`

. Brackets are also allowed, instead of the parens.

[10] No match?, say so.

See
docs.raku.org/routine/is-prime for more information about `is-prime`

.

See
docs.raku.org/routine/** for more
information about the *exponentiation operator* `**`

.

Running it:

$ raku powint 9
3^2
$ raku powint 45
0
$ raku powint 64
2^6
4^3
8^2
$ raku powint --one 64
2^6

#! /usr/bin/env perl
use feature 'say';
my $one = 0;
if (@ARGV && $ARGV[0] eq "--one")
{
$one++;
shift @ARGV;
}
my $N = shift(@ARGV) || die 'Specify $N';
die '$N is not an integer' unless int($N) == $N;
die '$N must be an integer larger than 1' unless $N > 1;
my $match = 0;
for my $base (2 .. sqrt($N))
{
my $exp = 1;
while ($exp++)
{
my $candidate = $base ** $exp;
last if $candidate > $N;
if ($candidate == $N)
{
say "$base^$exp";
$match++;
exit if $one;
}
}
}
say 0 unless $match;

And that's it.