This is my response to The Weekly Challenge #243.
Input: @nums = (1, 3, 2, 3, 1)
Output: 2
(1, 4) => nums[1] = 3, nums[4] = 1, 3 > 2 * 1
(3, 4) => nums[3] = 3, nums[4] = 1, 3 > 2 * 1
Example 2:
Input: @nums = (2, 4, 3, 5, 1)
Output: 3
(1, 4) => nums[1] = 4, nums[4] = 1, 4 > 2 * 1
(2, 4) => nums[2] = 3, nums[4] = 1, 3 > 2 * 1
(3, 4) => nums[3] = 5, nums[4] = 1, 5 > 2 * 1
#! /usr/bin/env raku
unit sub MAIN (*@nums where @nums.elems > 1 && all(@nums) ~~ Int, # [1]
:v(:$verbose));
my $count = 0; # [2]
for 0 .. @nums.end -1 -> $i # [3]
{
for $i + 1 .. @nums.end -> $j # [4]
{
if @nums[$i] > 2 *@nums[$j] # [5]
{
say ": ($i, $j) => nums[$i] = @nums[$i], nums[$j] = @nums[$j], \
@nums[$i] > 2 * @nums[$j]" if $verbose;
$count++; # [5a]
}
}
}
say $count; # [6]
[1] At least 2 elements (because of the «a» rule), all of which must be integers.
[2] The number of reverse pairs will end up here.
[3] Iterate over the i
indices, respecting the
«a» rule. Note the use of end
to get the index of the last
item.
See
docs.raku.org/routine/end
for more information about end
.
[4] Iterate over the j
indices, respecting the «a» rule.
[5] Does the «b» rule hold? If so, add it the count [5b].
[6] Print the result.
Running it:
$ ./reverse-pairs 1 3 2 3 1
2
$ ./reverse-pairs 1 3 2 3 1
2
$ ./reverse-pairs 2 4 3 5 1
3
Looking good.
With verbose mode:
$ ./reverse-pairs -v 1 3 2 3 1
: (0, 1) => nums[0] = 1, nums[1] = 3, 1 > 2 * 3
: (0, 2) => nums[0] = 1, nums[2] = 2, 1 > 2 * 2
: (0, 3) => nums[0] = 1, nums[3] = 3, 1 > 2 * 3
: (0, 4) => nums[0] = 1, nums[4] = 1, 1 > 2 * 1
: (1, 2) => nums[1] = 3, nums[2] = 2, 3 > 2 * 2
: (1, 3) => nums[1] = 3, nums[3] = 3, 3 > 2 * 3
: (1, 4) => nums[1] = 3, nums[4] = 1, 3 > 2 * 1
: (1, 4) => nums[1] = 3, nums[4] = 1, 3 > 2 * 1
: (2, 3) => nums[2] = 2, nums[3] = 3, 2 > 2 * 3
: (2, 4) => nums[2] = 2, nums[4] = 1, 2 > 2 * 1
: (3, 4) => nums[3] = 3, nums[4] = 1, 3 > 2 * 1
: (3, 4) => nums[3] = 3, nums[4] = 1, 3 > 2 * 1
2
$ ./reverse-pairs -v 1 3 2 3 1
: (1, 4) => nums[1] = 3, nums[4] = 1, 3 > 2 * 1
: (3, 4) => nums[3] = 3, nums[4] = 1, 3 > 2 * 1
2
$ ./reverse-pairs -v 2 4 3 5 1
: (1, 4) => nums[1] = 4, nums[4] = 1, 4 > 2 * 1
: (2, 4) => nums[2] = 3, nums[4] = 1, 3 > 2 * 1
: (3, 4) => nums[3] = 5, nums[4] = 1, 5 > 2 * 1
3
Input: @nums = (2, 5, 9)
Output: 10
floor(2 / 5) = 0
floor(2 / 9) = 0
floor(5 / 9) = 0
floor(2 / 2) = 1
floor(5 / 5) = 1
floor(9 / 9) = 1
floor(5 / 2) = 2
floor(9 / 2) = 4
floor(9 / 5) = 1
Example 2:
Input: @nums = (7, 7, 7, 7, 7, 7, 7)
Output: 49
#! /usr/bin/env raku
subset PosInt of Int where * > 0; # [1]
unit sub MAIN (*@nums where @nums.elems > 0 && all(@nums) ~~ PosInt, # [2]
:v(:$verbose));
my $sum = 0; # [3]
for ^@nums.elems -> $i # [4]
{
for ^@nums.elems -> $j # [4]
{
my $floor = @nums[$i] div @nums[$j]; # [5]
say ": floor(@nums[$i]/@nums[$j]) = $floor" if $verbose;
$sum += $floor; # [6]
}
}
say $sum; # [7]
[1] Set up a custom type (with subset
) that
allows for positive integers only.
See
docs.raku.org/language/typesystem#index-entry-subset-subset
for more information about subset
.
[2] At least one element, and they must all be positive integers.
[3] The result will end up here.
[4] Iterate over the indices, for both variables.
Note the use of ^
(the upto operator), giving the values from 0 to
one less than the value given to it (i.e. «up to« but not including).
See
docs.raku.org/routine/^
for more information about the Upto Operator ^
.
[5]
Rauku has a floor
function, but it is more
efficient to use integer division (with div
instead of
/
).
See
docs.raku.org/routine/floor for
more information about floor
.
See
docs.raku.org/routine/div for
more information about div
.
[6] Add the current floor value to the sum.
[7] Print the result.
Running it:
$ ./floor-sum 2 5 9
10
$ ./floor-sum 7 7 7 7 7 7 7
49
Looking good.
With verbose mode:
$ ./floor-sum -v 2 5 9
: floor(2/2) = 1
: floor(2/5) = 0
: floor(2/9) = 0
: floor(5/2) = 2
: floor(5/5) = 1
: floor(5/9) = 0
: floor(9/2) = 4
: floor(9/5) = 1
: floor(9/9) = 1
10
$ ./floor-sum -v 7 7 7 7 7 7 7
: floor(7/7) = 1
<47 identical rows removed>
: floor(7/7) = 1
49
And that's it.