A challenge many developers face when drawing a graph from scratch to plot some data is generating its ticks. In below graph, there are 6 horizontal ticks (1750, 1800, 1830, 1860, 1880 and 1900) and 11 vertical ticks (0, 10, 20, 30, 40, 50, 60, 70, 80, 90 and 100).
The horizontal bounds of the above graph goes from 1750 to 1900, which we'll call \$x_{min}\$ and \$x_{max}\$, respectively. For any \$x_{min}\$ and \$x_{max}\$ values, using \$n\$ ticks, there is a minimum multiple \$m\$ of a value \$s\$ that satisfies the following:
\$m \geq x_{min}\$
\$(m + s \times (n - 1)) \leq x_{max}\$; and
\$(m + s \times n) \gt x_{max}\$.
Let's suppose \$x_{min} = 0\$, \$x_{max} = 19\$ and \$n=4\$.
Consider \$s=4\$. The minimum multiple of \$s\$ that is greater or equal than \$x_{min}\$ is 0, therefore \$m=0\$. While the second condition is satisfied (\$0 + 4 \times 3 = 12 \leq x_{max}\$), the third condition is not (\$0 + 4 \times 4 = 16 \not \gt x_{max}\$).
Consider \$s=5\$. The minimum multiple of \$s\$ that is greater or equal than \$x_{min}\$ is 0, therefore \$m=0\$. Both the second (\$0 + 5 \times 3 = 15 \leq x_{max}\$) and the third (\$0 + 5 \times 4 = 20 \gt x_{max}\$) conditions are satisfied, therefore \$s=5\$.
Note that we need to minimize \$s\$: \$s=6\$ also satisfies all of the conditions, but we'll use \$s=5\$. In addition, since there could be more than one multiple of \$s\$ that satisfies all three conditions, we want also to minimize \$m\$ of the minimum found \$s\$.
Finding \$s\$ allows us to create \$n\$ equally-spaced ticks that can be used for our graph. The sequence goes from \$m\$ to \$m + s \times (n - 1)\$ with step \$s\$, so using \$s=5\$ as in the previous example, the generated ticks are \$\{0, 5, 10, 15\}\$. These ticks also gives the impression that our graph is sliding if we scale those properly, since they will only change if \$x_{min}\$ is a multiple of \$s\$. Below a gif that illustrates the generated ticks for \$(x_{min}, x_{max})\$ going from (0, 19) to (10, 29), with \$n=4\$.
Another way of thinking about this problem is generating the ticks beforehand. Let's suppose \$x_{min} = 4\$, \$x_{max} = 21\$ and \$n=3\$.
Consider \$s=5\$. This would generate the ticks \$\{5, 10, 15\}\$ and the next tick would be 20, which is not greater than \$x_{max}\$ (breaking the third condition). Note that here, \$m=5\$ since it's the first multiple \$m\$ of \$s\$ such that \$m \geq x_{min}\$.
Consider \$s=6\$. This would generate the ticks \$\{6, 12, 18\}\$ and the next tick would be 24, which is greater than \$x_{max}\$ (satisfying all conditions). We could also use \$s = 7\$, but we want to minimize this value.
Input
- Two real numbers
min
andmax
representing the minimum and the maximum values of a range, wheremax
is greater thanmin
; and one positive integer (num
) representing the number of ticks.
The input is guaranteed to generate an integer s
, so you should not handle min = 0
, max = 4
, and num = 3
for example.
Output
- A sequence of equally-spaced numbers with length
num
representing the ticks of a graph based on the previous explanation.
Test cases
# from gif
0, 19, 4 -> [0, 5, 10, 15]
1, 20, 4 -> [5, 10, 15, 20]
2, 21, 4 -> [5, 10, 15, 20]
3, 22, 4 -> [5, 10, 15, 20]
4, 23, 4 -> [5, 10, 15, 20]
5, 24, 4 -> [5, 10, 15, 20]
6, 25, 4 -> [10, 15, 20, 25]
7, 26, 4 -> [10, 15, 20, 25]
8, 27, 4 -> [10, 15, 20, 25]
9, 28, 4 -> [10, 15, 20, 25]
10, 29, 4 -> [10, 15, 20, 25]
11, 30, 4 -> [15, 20, 25, 30]
# m can be negative
-10, 1, 3 -> [-8, -4, 0]
-9, 2, 3 -> [-8, -4, 0]
-8, 3, 3 -> [-8, -4, 0]
-7, 4, 3 -> [-4, 0, 4]
-6, 5, 3 -> [-4, 0, 4]
-5, 6, 3 -> [-4, 0, 4]
-4, 7, 3 -> [-4, 0, 4]
-3, 8, 3 -> [0, 4, 8]
-2, 9, 3 -> [0, 4, 8]
-1, 10, 3 -> [0, 4, 8]
# num can be 1
0, 3, 1 -> [0]
1, 4, 1 -> [3]
2, 5, 1 -> [3]
3, 6, 1 -> [4]
4, 7, 1 -> [6]
5, 8, 1 -> [6]
6, 9, 1 -> [8]
7, 10, 1 -> [9]
8, 11, 1 -> [9]
9, 12, 1 -> [12]
This is code-golf, so shortest code in bytes wins. Default I/O methods apply.
0,4,3
, why iss=5/3
chosen, when, says=3/2
is smaller and would also satisfy all conditions? (In fact, there is no minimum value of s which satisfies that test case since any s in the half-open interval(4/3,2]
would work). I'd recommend requiring s to be an integer to make this challenge well-defined. \$\endgroup\$8, 11, 1 -> [9]
-- would 8 be a valid result us well, with assumed step size4
. 1.8 <= 8
, check. 2.8 + 4*(1-1) = 8
, which is less than11
. Check. 3.8 + 4 = 12
, which is greater than11
. Check. \$\endgroup\$