All points crossed by a line - c#

I need to find all points that are on a line. I tried Bresenham's algorithm but it doesn't work on the following case:
(0, 0)
.-----------+-----------+-----------.
|...........| | |
|...........| | |
|.....XXXX..| | |
|........XXXX | |
|...........XXXXX | |
+-----------+---XXXX----+-----------+
| |......XXXXX|...........|
| |..........XXXX.........|
| |...........|.XXXXX.....|
| |...........|...........|
| |...........|...........|
`-----------+-----------+-----------ยด
(2, 1)
X is the actual line, . is what Bresenham's algorithm returns, notice the line crosses (1, 0) but it is not marked.
How can I find all the pixels a line goes through efficiently? I don't need this anti-aliased so I think Wu's algorithm is an overkill. The line endpoints are in middle of the pixels.
To reference the algorithm I have is:
int dx = System.Math.Abs(x0 - x1);
int dy = System.Math.Abs(y0 - y1);
int sx = x0 < x1 ? 1 : -1;
int sy = y0 < y1 ? 1 : -1;
int err = dx - dy;
int lx = x0;
int ly = y0;
for(int i = 0; true; i++)
{
Mark(x0, y0);
if(x0 == x1 && y0 == y1)
break;
int e2 = err * 2;
if(e2 > -dy)
{
err -= dy;
x0 += sx;
}
if(e2 < dx)
{
err += dx;
y0 += sy;
}
}

Well, just implement the obvious straightforward algorithm: start from one end of the line, find which side of the starting square it crosses, jump to the corresponding adjacent square... and so on. Walk until you reach the finish square.
The simplest way to implement it in integers would be to switch to superpixel precision: just multiply everything by a constant factor. The difficult part begins when you discover that you don't have enough integer range to multiply it sufficiently... I don't know whether this is the case in your case.

Related

Storing data efficiently to save ram usage, without lookup overhead in C#

Depending on which position my agent is, along with its rotation, I need to determine the distances to a wall. As this function takes a little bit and needs to be called a lot, my idea was to store the distances by discretizing the position x and y as well as the angle.
My function is therefore called as follows:
float GetWallDistance(int x, int y, int angle)
{
return CalcWallDistance(x, y, angle);
}
where the x and y range from 0 to 500, and the angle ranges from 0 to 360. My first idea was to store it in a multidimensional array as follows:
Initialize the array somewhere by using float[,,] saveArray = new float[500, 500, 360];
float GetWallDistance(int x, int y, int angle)
{
float distance = 0;
if(saveArray[x, y, angle] == 0)
{
distance = CalcWallDistance(x, y, angle);
saveArray[x, y, angle] = distance;
}
else
{
distance = saveArray[x, y, angle];
}
return distance;
}
This tremendously sped up the calculation time but the problem here is that the saveArray takes up quite a big chuck of memory, and the agent will most likely not go through the entire 500 x 500 x 360 search space. A lot of memory is therefore taken up for nothing.
I therefore used a dictionary to store the data much more ram efficiently as follows:
Initialize the dictionary somewhere by using Dictionary<double, float> saveDictionairy = new Dictionary<double, float>();
float GetWallDistance(int x, int y, int angle)
{
double key = (double)x * 1000 + (double)y + (double)angle/1000
float distance = 0;
if(!saveDictionairy.TryGetValue(key, out distance))
{
distance = CalcWallDistance(x, y, angle);
saveDictionairy.Add(key, distance);
}
return distance;
}
(I tried using a string as key for the dictionary but it seemed that concatenating the x, y and angle takes up quite some time apparently)
This method is indeed a lot more memory efficient but the lookup time for the dictionary using the keys items increases by a large amount with respect to indexing the multi dimensional array.
Does anyone know a way how to store this data efficiently in a way that is also easy to lookup?
The .NET Dictionary uses a fast algorithm but has a fairly high overhead still. I experimented with making it faster a while ago. I found that I could make it 6x faster by deleting things that I did not need and by making other design changes.
For example, Dictionary uses the modulo operator to map from hash codes to buckets. % is surprisingly slow. It takes, I think, 31 CPU cycles. When I replaced that with hashCode & bucketCountMask where the bucket count is a power of two and bucketCountMask is buckets.Length - 1 I immediately realized a big performance gain.
I also deleted support for removing items and the iterator version feature. I directly exposed the slots array so that callers could directly mutate data in it.
This custom type was a lot faster because it was more specialized to my needs and it's API was a lot more difficult to use.
.NET Code on GitHub contains a DictionarySlim type for their internal use. Maybe you can use that.
From your current listed options, it seems the matrix approach is your best bet both in terms of performance and memory allocation.
I have run the following benchmarks:
[Benchmark(Baseline = true)]
public void MatrixTest()
{
// float[,,] saveArray = new float[501, 501, 361];
for (int x = 0; x <= 500; x++)
for (int y = 0; y <= 500; y++)
for (int angle = 0; angle <= 360; angle++)
if (saveArray[x, y, angle] == 0) saveArray[x, y, angle] = 42;
}
[Benchmark]
void IntKeyDictionaryTest()
{
// Dictionary<int, float> saveDictionary = new Dictionary<int, float>();
for (int x = 0; x <= 500; x++)
for (int y = 0; y <= 500; y++)
for (int angle = 0; angle <= 360; angle++)
{
int key = (x << 18) | (y << 9) | (angle);
if (!saveDictionary.TryGetValue(key, out float d)) saveDictionary[key] = 42;
}
}
[Benchmark]
void DoubleKeyDictionaryTest()
{
// Dictionary<double, float> saveDictionary = new Dictionary<double, float>();
for (int x = 0; x <= 500; x++)
for (int y = 0; y <= 500; y++)
for (int angle = 0; angle <= 360; angle++)
{
double key = (double)x * 1000 + (double)y + (double)angle / 1000l;
if (!saveDictionary.TryGetValue(key, out float d)) saveDictionary[key] = 42;
}
}
with following results:
Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op |
------------------------ |------------:|----------:|----------:|------:|--------:|------------:|------------:|------------:|--------------------:|
MatrixTest | 727.9 ms | 5.733 ms | 5.363 ms | 1.00 | 0.00 | - | - | - | - |
IntKeyDictionaryTest | 4,682.1 ms | 12.017 ms | 11.241 ms | 6.43 | 0.05 | - | - | - | - |
DoubleKeyDictionaryTest | 12,804.1 ms | 66.425 ms | 62.134 ms | 17.59 | 0.17 | - | - | - | - |
So I managed to make a more efficient key for your dictionary knowing the fact that x, y and angle can each be represented on 9 bits => 27bits total which fits in an int.
Anyway from the looks of it, the matrix approach seems to be the winner.

Shift Middle Point of Number Range

I have a function that Normalizes any number range to a new range.
Such as
[123,456] to [0,10]
or
[-50,50] to [-1,1]
I need help shifting the middle point of the new range.
I'm using this for a GUI Slider that has a range of [-100,100] but controls a value of [-2,2].
The GUI Slider default is 0 but the value default is 1 (none).
My program is a GUI for a CLI and I'm not able to change that program's value default to 0.
Slider
-100 --------------||-------------- 100
0
Value
-2 | | | -1 | | 0| | | 1 | | 2
Shifted Value
-2 | | -1 | | 0 | 1| | | | | | 2
Normalize
https://dotnetfiddle.net/42jHvM
// Normalize Function
public static double Normalize(double val, double valmin, double valmax, double min, double max, double midpoint)
{
return (((val - valmin) / (valmax - valmin)) * (max - min)) + min;
}
double output = Normalize( 0, // slider input
-100, // input min
100, // input max
-2, // normalize min
2, // normalize max
1 // middle point
);
Shift Middle Point
In my example I use [-100,100] converted to [-2,2].
The middle point of the input [-100,100] is 0.
But I need the output [-2,2] to have a middle point of 1 instead of 0.
So it will be skewed, slower towards -2, faster towards 2.
Example I made in photoshop to visualize the middle point shift using a gradient.
Easing
I tried using an Ease Out Tween to shift the middle point, but I don't know what values to use.
The example output needs to be Min: -2, Mid: 1, Max: 2.
https://dotnetfiddle.net/nfNlBC
It uses:
//t: current time
//b: start value
//c: change in value
//d: duration
After the middle point has been shifted:
Input of -100 should output -2.
Input of -50 should output -0.50?
Input of 0 should output 1.
Input of 50 should output 1.75?
Input of 100 should output 2.
Before
-100 | -50 | -25 | 0 | 25 | 50 | 100
-2 | -1 | -0.5 | 0 | 0.5 | 1 | 2
After approximated
-100 | -50 | -25 | 0 | 25 | 50 | 100
-2 |-0.50 | 0.25 | 1 | 1.25 | 1.75 | 2
Question
How can I modify the Normalize function, or run it's output through a new Shift/Easing function to set the new middle point of the range and readjust the numbers?
I don't understand why do you need such a mapping but the way to do it is:
public static double Normalize( double val, double valmin, double valmax, double min, double max, double midpoint )
{
double mid = ( valmin + valmax ) / 2.0;
if ( val < mid )
{
return ( val - valmin ) / ( mid - valmin ) * ( midpoint - min ) + min;
}
else
{
return ( val - mid ) / ( valmax - mid ) * ( max - midpoint ) + midpoint;
}
}
There's multiple ways this can be done, but if linear interpolation is sufficient, then you can just use some simple stretching and compression of the input parameter with a piecewise function.
public static double Interpolate(double val, double valmin, double valmax, double min, double max)
{
return (max - min) * (val - 0.5 * (valmax + valmin)) / (valmax - valmin) + 0.5 * (max + min);
}
public static double Normalize(double val, double valmin, double valmax, double min, double max, double midpoint)
{
double m = Interpolate(midpoint, valmin, valmax, min, max);
if (val < m) {
return Interpolate(val, valmin, m, min, midpoint);
} else if (val > m) {
return Interpolate(val, m, valmax, midpoint, max);
} else {
return m;
}
}
You should be able to replace Interpolate with something fancier, like one of the easing forms you linked, with the following mappings from your parameter names to theirs:
t = val - 0.5 * (valmax + valmin)
b = 0.5 * (max + min)
c = max - min
d = valmax - valmin

Dealing with large integers without BigInteger Library in Algorithm contests

Problem: Topcoder SRM 170 500
Consider a sequence {x0, x1, x2, ...}. A relation that defines some term xn in terms of previous terms is called a recurrence relation. A linear recurrence relation is one where the recurrence is of the form xn = c(k-1) * x(n-1) + c(k-2) * x(n-2) + ... + c(0) * x(n-k)
where all the c(i) are real-valued constants, k is the length of the recurrence relation, and n is an arbitrary positive integer which is greater than or equal to k.
You will be given a int[] coefficients, indicating, in order, c(0), c(1), ..., c(k-1). You will also be given a int[] initial, giving the values of x(0), x(1), ..., x(k-1), and an int N. Your method should return xN modulo 10.
More specifically, if coefficients is of size k, then the recurrence relation will be
xn = coefficients[k - 1] * xn-1 + coefficients[k - 2] * xn-2 + ... + coefficients[0] * xn-k.
For example, if coefficients = {2,1}, initial = {9,7}, and N = 6, then our recurrence relation is xn = xn-1 + 2 * xn-2 and we have x0 = 9 and x1 = 7. Then x2 = x1 + 2 * x0 = 7 + 2 * 9 = 25, and similarly, x3 = 39, x4 = 89, x5 = 167, and x6 = 345, so your method would return (345 modulo 10) = 5.
Constraints:
- Code must run in less than or equal to 2 seconds
- Memory utilization must not exceed 64 MB
My attempted Solution:
class RecurrenceRelation
{
public int moduloTen(int[] coefficients, int[] initial, int N)
{
double xn = 0; int j = 0;
int K = coefficients.Length;
List<double> xs = new List<double>(Array.ConvertAll<int, double>(initial,
delegate(int i)
{
return (double)i;
}));
if (N < K)
return negativePositiveMod(xs[N]);
while (xs.Count <= N)
{
for (int i = xs.Count - 1; i >= j; i--)
{
xn += xs[i] * coefficients[K--];
}
K = coefficients.Length;
xs.Add(xn);
xn = 0;
j++;
}
return negativePositiveMod(xs[N]);
}
public int negativePositiveMod(double b)
{
while (b < 0)
{
b += 10;
}
return (int)(b % 10);
}
}
My problem with this solution is the precision of the double representation, and since I can't use a third party library or the BigInteger library in .NET for this SRM, i need to find a way of solving it without them. I suspect I could use recursion but I'm a little clueless on how to go about that.
Here is a test case that shows when my code works and when it doesn't
{2,1}, {9,7}, 6 - Successfully returns 5
{9,8,7,6,5,4,3,2,1,0}, {1,2,3,4,5,6,7,8,9,10}, 654 - Unsuccessfully returns 8 instead of 5 due to precision of double type
Can anyone help me figure this out? I was going to consider using arrays to store the values but it is a little bit beyond me especially on how to cater for multiplication and still be within the time and space complexity set out in the problem. Perhaps my entire approach is wrong? I'd appreciate some pointers and direction (not fully fleshed out answers) answers please.
Thanks
Notice that we only need to return the modulo 10 of xn.
We also need to know that if a = b + c, we have a % 10 = (b % 10 + c % 10) %10.
And a = b*c, so we also have a % 10 = (b %10 * c % 10) % 10;
So, for
xn = c(k-1) * x(n-1) + c(k-2) * x(n-2) + ... + c(0) * x(n-k)
= a0 + a1 + .... + an
(with a0 = c(k - 1)*x(n-1), a1 = ...)
we have xn % 10 = (a0 % 10 + a1 % 10 + ...)%10
And for each ai = ci*xi, so ai % 10 = (ci % 10 * xi % 10)% 10.
So by doing all of these math calculations, we can avoid to use double and keep the result in manageable size.
As Pham has answered, the trick is to realize that you only need to return a modulo, thereby bypassing the problem of overflow. Here is my quick attempt. I use a queue to put in the last result xN, and evict the oldest one.
static int solve(int[] coefficients, int[] seed, int n)
{
int k = coefficients.Count();
var queue = new Queue<int>(seed.Reverse().Take(k).Reverse());
for (int i = k; i <= n; i++)
{
var xn = coefficients.Zip(queue, (x, y) => x * y % 10).Sum() % 10;
queue.Enqueue(xn);
queue.Dequeue();
}
return (int) (queue.Last() );
}
Edit:
Getting the same results as you expect, however I don't guarantee that there is no bug in this example.

Recursive Multiplication Method

I'm following along with this http://www.cs.berkeley.edu/~vazirani/algorithms/chap1.pdf (bottom of page 24). In the book the author describes Al Khwarizmi multiplication algorithm. Here is my implementation
static int RecMultiply(int x, int y)
{
if (y == 0)
return 0;
int z = RecMultiply(x, y / 2);
if (y % 2 == 0)
return 2 * z;
else
return x + 2 * z;
}
I've stepped through the code a couple times and I'm just not grokking it. Why does the bottom else add x to 2 * z? It seems to me that z is used both as a running total and as the "right column" number in the algorithm in the book. Can someone break this code down and explain it please?
Since Multiplication is simple repetitive addition, if y is pair, you can divide it by two, and multiply x by two. (so, 2*2 = 2+2. 2*3 = 2+2+2, 2*4 = 2+2+2+2 ....)
If y is odd, you can subtract 1, to get a y that is pair, and you need to add an x, (basically, 1*y).
Here's a breakdown:
RecMultiply(5,5) :
+- z = RecMultiply(5,2)
| return 5 + 2 * z (=20 +5 =25)
|
|
+-- RecMultiply(5,2) :
+- z = RecMultiply(5,1)
| return 2 * z (=10)
|
+-- RecMultiply(5,1) :
+- z = RecMultiply(5,0)
| return 5 + 0
|
+---RecMultiply(5,0) :
return 0
RecMultiply(5,4) :
+- z = RecMultiply(5,2)
| return 2 * z (=)
|
+-- RecMultiply(5,2) :
+- z = RecMultiply(5,1)
| return 2 * z (=10)
|
+-- RecMultiply(5,1) :
+- z = RecMultiply(5,0)
| return 5 + 0
|
+---RecMultiply(5,0) :
return 0
So, basically, after the recursive bit (that takes care of all the pair multiplications), you might need to add another y, which in the first case above, is 5 for the first call).
Note the special case of y=1, which means x*1 which obviously is 5 in our case. Same logic applies.
You might want to look at it like this, if it helps:
static int RecMultiply(int x, int y)
{
switch (y)
{
case 0:
return 0;
break;
case 1:
return x;
break;
default:
return (y%2 ==0) ? RecMultiply(x, y/2)
: x + RecMultiply(x, y/2);
break;
}
}
I think it denotes the +1 (or odd cases) in a more understandable manner.
It is quite simple.
Z is calculated by multiplying x and half of y.
If y was of even parity (if section) return 2*z = 2 * x * y/2 = x * y (which is original request)
If y was of odd parity (else section) return 2*z + x. Why do we add x??? That is because y/2 will be the same for even and following odd number. So Z would be the same. But, with this if section we are detecting if it's odd or even and in case of odd we add x once more to the result.

How to create pulsating value from 0..1..0..1..0 etc for a given duration?

I'm working on some code where I have a Time object with a member time. Time.time gives
me the time since my application started in seconds (float value). Now I want to create a pulsating value between 0 and 1 and then from 1 to 0 again, which continues doing thins untill the application stops.
I was thinking to use sin() but don't know what to pass to it as paramters to create this pulsing value.
How would I create this pulsating value?
Kind regards,
Pollux
You mention using sin(), so I guess you want it to pulse continuously between 0 and 1.
Something like this will do:
float pulse(float time) {
const float pi = 3.14;
const float frequency = 10; // Frequency in Hz
return 0.5*(1+sin(2 * pi * frequency * time));
}
1/frequency = 0.1 second is the period, which is the time between 1's.
How about x = 1 - x?
Or if you want it to be time based use Timer % 2
Oh, you wanted the values between 0 and 1 as well.
how about Math.Abs(100 - (Timer % 200)) / 100
Where timer is something like DateTime.Now.TimeOfDay.TotalMilliseconds
Edit:
My tests indicate that this is more than twice as fast as the Sin method. For 1 million iterations, the sin method takes .048 seconds while the Abs method takes about .023 seconds. Also, you get different waveforms out of the two, of course. Sin produces a Sine wave, while Abs produces a triangular wave.
static void Main(string[] args)
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
const int count = 1000000;
float[] results = new float[count];
for (int i = 0; i < count; i++)
{
results[i] = AbsPulse(i/1000000F);
//results[i] = SinPulse(i / 1000000F);
}
sw.Stop();
Console.WriteLine("Time Elapsed: {0} seconds", sw.Elapsed.TotalSeconds);
char[,] graph = new char[80, 20];
for (int y = 0; y <= graph.GetUpperBound(1); y++)
for (int x = 0; x <= graph.GetUpperBound(0); x++)
graph[x, y] = ' ';
for (int x = 0; x < count; x++)
{
int col = x * 80 / count;
graph[col, (int)(results[x] * graph.GetUpperBound(1))] = 'o';
}
for (int y = 0; y <= graph.GetUpperBound(1); y++)
{
for (int x = 0; x < graph.GetUpperBound(0); x++)
Console.Write(graph[x, y]);
Console.WriteLine();
}
}
static float AbsPulse(float time)
{
const int frequency = 10; // Frequency in Hz
const int resolution = 1000; // How many steps are there between 0 and 1
return Math.Abs(resolution - ((int)(time * frequency * 2 * resolution) % (resolution * 2))) / (float)resolution;
}
static float SinPulse(float time)
{
const float pi = 3.14F;
const float frequency = 10; // Frequency in Hz
return 0.5F * (1 + (float)Math.Sin(2 * pi * frequency * time));
}
A sine function would be ideal I think, but you need to adjust the period and the scale.
The sine function produces results between -1 and 1, but you want to go between 0 and 1. To scale it properly you want (sin(x)+1)/2.
The sine function starts at zero, goes to 1 at pi/2, zero again at pi, -1 at 3*pi/2, and back to zero at 2*pi. Scaled, the first zero will happen at 3*pi/2 and the first maximum after that will be at 5/2*pi. So x in the previous formula is (2*time + 3) * pi/2.
Putting it all together: (sin((2*time.time + 3) * pi/2) + 1) / 2
How often do you want it to pulse?
Let's say you want to go from 0 to 1 over 10 seconds.
float pulseValueForTime(int sec) {
int pulsePoint = sec % 10;
float pulsePercent = (float)pulsePoint / (float)10;
float pulseInTermsOfPI = (pulsePercent * 2 * PI) - PI;
float sinVal = MagicalSinFunction(pulseInTermsOfPI); // what framework you use to compute sin is up to you... I'm sure you can google that!
return (sinVal + 1) / 2; // sin is between 1 and -1, translate to between 0 and 1
}
Look into Ease functions. They do this sort of thing in all sorts of manners - linear, poly, exp, sin, etc.

Categories