Generating Inclusive Integer Ranges in APL#
In this article, we will explore how to generate inclusive integer ranges that can be either ascending or descending. There are many ways to approach this problem, and I won’t cover all of them here. However, in previous discussions, we explored various methods, and I encourage you to follow the link in the video description to review the chat log for different approaches.
For now, let’s focus on the shortest and fastest solutions that were developed during a recent coding competition.
Problem Specification#
The problem requires us to use a two-element vector that contains both the beginning and the end numbers. In a typical APL function, we might expect the beginning number on one side and the ending number on the other. However, this problem specifies that both ends are to be provided in the same argument.
Example#
Let’s illustrate with an example: generating a range from 3 to 10.
The method we will employ involves starting with the beginning number (3) and appending a sequence of ones to it until we reach the ending number (10). In this case, we need 7 ones. By performing a cumulative sum starting with 3, we obtain the sequence from 3 to 10:
+\3 1 1 1 1 1 1 1 ⍝ Result: 3 4 5 6 7 8 9 10
Conversely, if we want to create a range from 10 to 3, we would start with 10 and append negative ones (7 times). This will yield the sequence from 10 down to 3:
+\10 ¯1 ¯1 ¯1 ¯1 ¯1 ¯1 ¯1 ⍝ Result: 10 9 8 7 6 5 4 3
Steps to Generate the Range#
First, we need to determine the difference between the two values:
Calculate the Difference: We will use a minus reduction to subtract the two elements in the vector. However, when going from 3 to 10, we need to ensure the result is positive. Therefore, it is more appropriate to subtract the left element from the right element.
difference ← 10 - 3 ⍝ Result will be 7
Reshape the Ones: To generate the necessary sequence of ones or negative ones, we need to reshape our number of elements. The number of elements corresponds to the absolute value of our difference, while the sign corresponds to whether we are going ascending or descending.
Handle Edge Cases: If the beginning and ending points are the same, the result should simply return that point without generating a sequence.
Efficient Method#
While the approach described works, it is not the most efficient. Generating a sequence of ones creates additional data that need to be copied, potentially leading to memory inefficiencies.
Using Zero-Based Indexing#
To optimize, we’ll use zero-based indexing. Let’s create a function that utilizes this approach:
Index Generation: Create a sequence of indices based on the length of the input vector.
Account for Inclusive Ranges: When generating the range, remember to add an extra value to account for inclusivity.
Adjust for Positive and Negative Offsets: Instead of using conditionals, we can utilize mathematical operations. Specifically, we can use exponentiation to map a binary value (0 or 1) to either 1 or -1:
If the first number is greater than the second, we get -1.
If they are the same, we get 0.
If the first is less than the second, we get 1.
sign ← (-1) ^ (first > second) ⍝ Maps to -1 or 1
For example, when calculating the offset between 3 and 10:
(-/)3 10 ⍝ Result: ¯7 (-⍨/)3 10 ⍝ Result: 7
Final Computation: Finally, add the first value to the sequence generated from the adjusted offsets.
Here’s an efficient way to generate the inclusive ranges:
F←+\⊃,∘(|⍴×)-⍨/ ⍝ Function definition
Using the function for different inputs:
F 3 10 ⍝ Result: 3 4 5 6 7 8 9 10 F 10 3 ⍝ Result: 10 9 8 7 6 5 4 3 F 10 10 ⍝ Result: 10
This method executes efficiently without unnecessary memory overhead while producing the desired range.
Conclusion#
The problem of generating inclusive integer ranges in APL can be approached in various ways, from naive implementations to optimized solutions using mathematical properties. By leveraging proper indexing and efficient summation techniques, we can achieve an effective solution.
Thank you for reading, and I hope this guide helps you tackle similar problems in your coding journey!