Determining the direction of a turn? - c

I want to turn an object clockwise or counter-clockwise. A couple of integers (from 0 -> 7) represent the direction that object is looking to (eg. left, leftup, up, upright, right, ...). Adding +1 to the current direction of the object turns it clockwise, substracting -1 turns it counter-clockwise.
If I want the object to turn to a certain direction (= integer), how do I determine the minimum amount of turns necessary?
Currently I'm using this way of thinking :
int minimumRequiredTurns = min(abs(currentDirection.intvalue - goalDirection.intvalue),
8 - abs(currentDirection.intvalue - goalDirection.intvalue));
Is it possible to do it without a min statement?

I think
(1-(abs(abs(currentDirection.intvalue - goalDirection.intvalue)/(n/2)-1)))*(n/2)
should do the trick, where n is the number of possible directions.
In order to have integer only calculations transform this to
(n/2)-abs(abs(currentDirection.intvalue - goalDirection.intvalue)-(n/2))
Explanation: Using the hat function to generate the map:
0 -> 0
1 -> 1
2 -> 2
3 -> 3
4 -> 4
5 -> 3
6 -> 2
7 -> 1

If you really don't like the "min", you could use a lookup table.
int minRequiredTurns[8][8] = {
0, 1, 2, 3, 4, 3, 2, 1,
1, 0, 1, 2, 3, 4, 3, 2,
2, 1, 0, 1, 2, 3, 4, 3,
/* and so on... */
};

Almost certainly, a much better design would be to use vectors to represent directions; treat the "direction" as a pair of numbers (x,y) so that x represents the horizontal direction, y represents the vertical.
So (1,0) would represent facing right; (0,1) would represent facing up; (-1, 0) would be facing left; (1,1) would be facing up-right; etc.
Then you can just use the normal vector-based solution to your problem: Take the direction you're facing, and the direction you want to face, and take the cross-product of the two.
result = x1y2 - x2y1
If the result is positive, rotate counter-clockwise; if the result is negative, rotate clockwise (this works because of the right-hand rule that defines cross-products).
Note that this approach generalizes trivially to allow arbitrary directions, not just horizontal/vertical/diagonal.

First, force a positive difference, then force to be between 0 and N/2 (0 and 4):
N=8
diff = (new-old+N)%N;
turns = diff - (diff>N/2 ? N/2 : 0)

int N = 8, turns = abs(current-goal);
if (turns > N/2) turns = N-turns;
But I don't understand why you don't want the min-statement...

No min, no abs, one expression, no division:
turns = ((((goalDirection + 8 - currentDirection) % 8) + 4) % 8) - 4
How it works: the innermost expression (goalDirection + 8 - currentDirection) is the same as given by AShelley; number of required turns in the clockwise direction. The outermost expression shifts this to its equivalent in [-4..+3]

Related

Fast Way to Find Border Cells in a 2D array

Suppose that I have a n x n 2D array where the entries are either 0 or 1. For example:
[[0, 1, 1]
[1, 0, 0]
[0, 0, 0]]
Now I want to find the neighbor cells of the 1s in the array, which are the cells to the sides and directly diagonal of the 1s in the array that equal to 0. So in the example above, the neighbor cells would be {(0, 0), (1, 1), (1, 2), (2, 0), (2, 1)}. There is the brute-force method of doing this, where I iterate through every entry and if it is a 1, I look at its neighbors and check if it equal to 0. For large n with a high density of 1s, the number of checks made is around 8n^2. However, I feel like I can make use of the redundancy of this problem to come up with a faster solution. For example, after look at the first entry in the cell (0, 0), I see that that it has two neighboring ones and a neighboring 0. So I know that I don't have to check the cell (1, 1) and its neighbors. I also know that at (0, 1) and (1, 0) the entry is 1, so I can add (0, 0) as a neighbor cell.
What's the fastest implementation of a solution to this problem that someone can come up with for this problem? Personally, I've thinking of using some sort of BFS or DFS implementation, but I'm not sure how I would implement it. I was thinking instead of taking around 8n^2 checks, it would only take around n^2 checks.
(Also, I don't know if this is a leetcode problem. It seem suitable to be one, so if anyone knows the name or number of this problem on leetcode, please let me know!)
Well, I can think of an idea that will lower the 8.
First you sum all the numbers int the matrix, that will gives you how many 1s there are in the matrix. This step can be made in O(n^2).
Then if there are less 1s than (n * n) / 2 you do the check by the 1s. I mean you go for every item and if it is a 1 you look for all the 0 positions in the eight neighbor (and add them to your answer).
In the other side, if there are more 1s than (n * n) / 2 you do the same but this time you do the check by the 0s. You go for every item and if it is a 0 you look for at least one 1 in the eight neighbor. If there is a 1 neighbor you add to your answer the current 0 position.
Why doing this? Well you are checking the 8 neighbor at most (n^2)/2 so the final time in the worst case will be: n^2 + n^2 + 8(n^2)/2 = 2n^2 + 4(n^2) = 6n^2
Ps: Thanks to #unlut that pointed some error this answer had
I was thinking instead of taking around 8n^2 checks, it would only take around n^2 checks.
I think this is impossible. It all depends on input. For every 1, you must check/overwrite neighbors. So, minimum of number of 1s in input matrix * 8 checks are required.
Try out some examples
0 0 0 1 1 1 0 1 0 1 0 1
0 1 0 1 1 1 1 1 1 0 0 0
0 0 0 1 1 1 0 1 0 1 0 1

How can I remove rows of a matrix in Matlab when the difference between two consecutive rows is more than a threshold?

Suppose a data like:
X y
1 5
2 6
3 1
4 7
5 3
6 8
I want to remove 3 1 and 5 3 because their difference with the previous row is more than 3. In fact, I want to draw a plot with them and want it to be smooth.
I tried
for qq = 1:size(data,1)
if data(qq,2) - data(qq-1,2) > 3
data(qq,:)=[];
end
end
However, it gives:
Subscript indices must either be real positive integers or logicals.
Moreover, I guess the size of array changes as I remove some elements.
In the end, the difference between no consecutive elements must be greater than threshold.
In practice I want to smooth the following picture where there is high fluctuate
One very simple filter from Mathematical morphology that you could try is the closing with a structuring element of size 2. It changes the value of any sample that is lower than both neighbors to the lowest of its two neighbors. Other values are not changed. Thus, it doesn't use a threshold to determine what samples are wrong, it only looks that the sample is lower than both neighbors:
y = [5, 6, 1, 7, 3, 8]; % OP's second column
y1 = y;
y1(end+1) = -inf; % enforce boundary condition
y1 = max(y1,circshift(y1,1)); % dilation
y1 = min(y1,circshift(y1,-1)); % erosion
y1 = y1(1:end-1); % undo boundary condition change
This returns y1 = [5 6 6 7 7 8].
If you want to prevent changing your signal for small deviations, you can apply your threshold as a second step:
I = y1 - y < 3;
y1(I) = y(I);
This finds the places where we changed the signal, but the change was less than the threshold of 3. At those places we write back the original value.
You have a few errors:
Your index needs to start from 2, so that you aren't trying to index 0 for a previous index.
You need to check that the absolute value of the difference is greater than 3.
Since your data matrix is changing sizes, you can't use a for loop with a fixed number of iterations. Use a while loop instead.
This should give you the results you want:
qq = 2;
while qq <= size(data, 1)
if abs(data(qq, 2) - data(qq-1, 2)) > 3,
data(qq, :) = [];
else
qq = qq+1;
end
end

How to multiply matrices with only one iterable

I have a matrix in the form below where the position is only given via one iterable (x).
A B
1 0 3 2
0 2 4 5
where for matrixA[x] and matrixB[x]
matrixA[0] = 1, matrixA[1] = 0, matrixA[2] = 0, matrixA[3] = 2
matrixB[0] = 3, matrixB[1] = 2 etc.
What would be the best way to implement a multiplication of matrices A and B (preferably in C) when the only way to receive the position within a matrix is through variable x (also have the length of width and height)?
(the examples I have gotten from google all use two variables - height and width to solve this however I'm only working with one)
I think matrix's width had been given as input.
If so, You can convert matrix[x][y] to matrix[x*width+y] and apply any ordinary multiplication algorithm.

Finding an number in montonically increasing and then decreasing sequencecera

Finding the maximum or minimum value in a sequence that increases montonically and then decreases monotonically can be done in O(log n).
However, if i want to check if a number exists in such a sequence, can this also be done in O(log n)?
I do not think that is possible. Consider this example: 1 4 5 6 7 10 8 3 2 0.
In this example, if I need to find whether the sequence contains '2', I do not have any conditions to divide the search space into half of the original search space. In the worst, case it will be O(n), as you need to check for both halves, when we are trying to search for 2.
I would like to know, if this search be done in O(log n) time?
As you noted, you can find the maximum (and its position) in O(logn). Then you can just do a binary search in each part which is also O(logn).
In the above example, you find the maximum 10 at position 5.
Then you do a binary search in the subsequence [0..5] (1, 4, 5, 6, 7, 10).
As 2 is not found, you proceed to do a binary search in the other part (10, 8, 3, 2, 0).
To find the maximum in O(logn): look at the two elements at the center: 7 < 10. So we are still in the increasing part and have to look for the maximum in the right half of the sequence: (10, 8, 3, 2, 0). Look at 8 and 3 an proceed with the left part (10, 8).
As I remember the best search for the arrays which elements are ordered increasing and then decreasing is the Fibonacci search algorithm.
Here is a sketch in python. In short we are aiming to find an element which borders the increasing and decreasing regions (this we check we two conditions checking the neighbor elements). And we keep hopping like in standard binary search until we find this element. Hope that helps.
def get_max(arr):
if len(arr) == 1:
return arr[0]
if len(arr) in [0,2]:
return None
left, right = 0, len(arr) - 1
while left <= right:
mid = (left+right) // 2
#increasing region
if arr[mid+1] > arr[mid] and arr[mid] > arr[mid-1]:
left = mid + 1
#decreasing region
elif arr[mid+1] < arr[mid] and arr[mid] < arr[mid-1]:
right = mid - 1
elif arr[mid+1] < arr[mid] and arr[mid-1] > arr[mid]:
return arr[mid-1]
else:
return arr[mid]
return -1

FIND-S Algorithm - simple question

The FIND-S algorithm is probably one of the most simple machine learning algorithms. However, I can't find many examples out there.. Just the standard 'sunny, rainy, play-ball' examples that's always used in machine learning. Please could someone help me with this application (its a past exam question in machine learning).
Hypotheses are of the form a <= x <= b, c <= y <= d where x and y are points in an x,y plane and c and d are any integer. Basically, these hypotheses define rectangles in the x,y space.
These are the training examples where - is a negative example and + is a positive example and the pairs are the x,y co-ordinates:
+ 4, 4
+ 5, 3
+ 6, 5
- 1, 3
- 2, 6
- 5, 1
- 5, 8
- 9, 4
All I want to do is apply FIND-S to this example! It must be simple! Either some tips or a solution would be awesome.
Thank you.
Find-S seeks the most restrictive (ie most 'specific') hypothesis that fits all the positive examples (negatives are ignored).
In your case, there's an obvious graphical interpretation: "find the smallest rectangle that contains all the '+' coordinates"...
... which would be a=4, b=6, c=3, d=5.
The algorithm for doing it would be something like this:
Define a hypothesis rectangle h[a,b,c,d], and initialise it to [-,-,-,-]
for each + example e {
if e is not within h {
enlarge h to be just big enough to hold e (and all previous e's)
} else { do nothing: h already contains e }
}
If we step through this with your training set, we get:
0. h = [-,-,-,-] // initial value
1. h = [4,4,4,4] // (4,4) is not in h: change h so it just contains (4,4)
2. h = [4,5,3,4] // (5,3) is not in h, so enlarge h to fit (4,4) and (5,3)
3. h = [4,6,3,5] // (6,5) is not in h, so enlarge again
4. // no more positive examples left, so we're done.

Resources