Skip to content

Commit 14c404a

Browse files
authored
Merge pull request #323 from turkunov/convert_range
New Problem: Convert Range
2 parents 5662e66 + f9e4c4a commit 14c404a

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

Problems/convert_range/learn.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Shifting one range to another could come in handy in the data preprocessing task, e.g. shift a GPA of $[0, 10]$ range to $[0, 4]$
2+
3+
Lets denote our first range (or interval) as $[a, b]$ and another as $[c, d]$. Let's recall that an **image interval** is some function $F$ applied to an interval $I$, i.e. $F(I)$. With that in mind, let's first apply the map $t\mapsto t - a$ and get an image interval for the first range: $[0, b-a]$. With that operation we've shifted the left point to $0$.
4+
5+
Then we apply a scaling mapping to bring the same interval to unit length: $t\mapsto\frac{1}{b-a}\cdot t$. Now we obtain an image interval $[0, 1]$ from the original first range.
6+
7+
Now we need a mapping from the unit interval to our sencond desired range $[c, d]$. Firstly, this involves $t\mapsto(d-c)\cdot t$, which results in the image $[0, d-c]$. Then we do $t\mapsto c+t$, which brings us to $[c, d]$.
8+
9+
Combining these operations we get the following mapping function, which shifts a set $x$ from its range of $[a, b]$ to $[c, d]$: $f(x) = c+(\frac{d-c}{b-a})(x-a)$

Problems/convert_range/solution.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import numpy as np
2+
3+
4+
def convert_range(values: np.ndarray, c: float, d: float) -> np.ndarray:
5+
"""
6+
Shifts an arbitrary range [values.min(), values.max()] to a desired [c, d]
7+
8+
Parameters
9+
----------
10+
values : np.ndarray
11+
An array of random values we want to shift
12+
c: float
13+
Supremum of the desired range
14+
d: float
15+
Infimum of the desired range
16+
17+
Returns
18+
-------
19+
values_shifted : np.ndarray
20+
Original values shifted to [c, d] range
21+
"""
22+
23+
a, b = values.min(), values.max()
24+
return c + (d-c) / (b-a) * (values-a)
25+
26+
27+
def test_convert_range():
28+
# Test 1
29+
seq = np.array([388, 242, 124, 384, 313, 277, 339, 302, 268, 392])
30+
c, d = 0, 1
31+
e_shifted = np.array([
32+
0.98507463, 0.44029851, 0., 0.97014925, 0.70522388, 0.57089552,
33+
0.80223881, 0.6641791, 0.53731343, 1.])
34+
assert np.allclose(e_shifted,convert_range(seq, c, d)), 'Test case 1 failed'
35+
36+
# Test 2
37+
seq = np.array([[2028, 4522], [1412, 2502], [3414, 3694], [1747, 1233], [1862, 4868]])
38+
c, d = 4, 8
39+
e_shifted = np.array(
40+
[[4.874828060522696, 7.619257221458047], [4.19697386519945, 5.396423658872077],
41+
[6.4, 6.7081155433287485], [4.565612104539202, 4.0], [4.692159559834938, 8.0]])
42+
assert np.allclose(e_shifted,convert_range(seq, c, d)), 'Test case 2 failed'
43+
44+
print('All tests passed')
45+
46+
47+
if __name__ == '__main__':
48+
test_convert_range()
49+

0 commit comments

Comments
 (0)