I have a list of values in an array (which is ordered low to high), I am planning to show these values distributed on a line, but as some of the values are close, the points end up overlapping. As the exact values are not important, small adjustments doesn't matter, I'm trying to make some code which spreads any clusters of values so that they are note closer than .5 from any other.
For instance, let's say we have this array:
my_values = { 0.2, 1.3, 2.0, 2.1, 2.5, 3.6, 5.2 }
The 2.0, 2.1 and 2.5 are too close together, so I need to move the so they're not closer than .5 but as close to the actual value as possible. So the optimal solution would be something like:
my_values = { 0.2, 1.1, 1.6, 2.1, 2.6, 3.6, 5.2 }
Here's my code so far, which only makes a lame attempt of a solution (the actual items in the list in my code are objects with get/set functions, but the principle is the same):
...
last_dot = -999 'Low enough
For Each dot In my_values
If dot.getPos <= last_dot + 0.5 Then
dot.setPos last_dot + 0.5
End If
last_dot = dot.getPos
Next dot
There's thing I'm not sure how to solve: I like to spread them both up and down, so the centre of any cluser is not really moved. So far every move I do just raises the value, and the last value of the cluster gets offset more than the others, prefarably any value moved upwards should have another value move downwards. Keeping the maxinum adjustment of any value as low as possible. So in the lists above when the 2.0 are move down to 1.6 it's then too close to the 1.3, so that has to be moved to 1.1, but in my code I dont know that when checking the 1.3 item. (Not sure if I explained that so anyone can understand =/)
Any help appriciated!
Iterative relaxation on whole array:
input:
{ 0.2, 1.3, 2.0, 2.1, 2.5, 3.6, 5.2 }
function:
for (int j = 0; j < 100; j++)// 100 is extreme, maybe 20 is enough for short anomalies
{
for (int i = 0; i < t.Length - 1; i++)
{
if (t[i] > t[i + 1] - 0.5)
{
t[i] -= (t[i] - (t[i + 1] - 0.5)) * 0.1;
}
}
for (int i = t.Length - 1; i >= 1; i--)
{
if (t[i] < t[i - 1] + 0.5)
{
t[i] -= (t[i] - (t[i - 1] + 0.5)) * 0.1;
}
}
}
Result:
0,2
1,00031552491128
1,61163875308098
2,1160023905259
2,66
3,6
5,2
Warning: O(n) is not efficient when only a few elements need to change.
Edit: corrected the codes as A.S.H. commented.
New output:
0,2
1,21857842635286
1,71823144559425
2,21771136663457
2,71733660405361
3,6
5,2
so it is looks more symmetric now being much closer to the point 2.05 which is mid point of points that are too close.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With