by Arne Sommer

# Reverse Floor with Raku

[263] Published 16. November 2023.

This is my response to The Weekly Challenge #243.

## Challenge #243.1: Reverse Pairs

You are given an array of integers.

Write a script to return the number of reverse pairs in the given array.

A reverse pair is a pair (i, j) where: a) 0 <= i < j < nums.length and b) nums[i] > 2 * nums[j].

Example 1: ```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 ```
File: reverse-pairs ```#! /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 ```

## Challenge #243.2: Floor Sum

You are given an array of positive integers (>=1).

Write a script to return the sum of floor(nums[i] / nums[j]) where 0 <= i,j < nums.length. The floor() function returns the integer part of the division.

Example 1: ```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 ```
File: floor-sum ```#! /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.