I've got a c homework problem that is doing my head in and will be greatful if anyone can help point me in the right direction.
If I have two minutes points on an analog watch such as t1 (55 minutes) and t2 (7 minutes), I need to calculate the shortest amount of steps between the two points.
What I've come up with so far is these two equations:
-t1 + t2 + 60 =
-55 + 7 + 60
= 12
t1 - t2 + 60 =
55 - 7 + 60
= 108
12 is lower then 108, therefore 12 steps is the shortest distance.
This appears to work fine if I compare the two results and use the lowest. However, if I pick out another two points for example let t1 = 39 and t2 = 34 and plug them into the equation:
-t1 + t2 + 60 = -39 + 34 + 60 = 55
t1 - t2 + 60 = 39 - 34 + 60 = 35
35 is lower then 55, therefore 35 steps is the shortest distance.
However, 35 isn't the correct answer. 5 steps is the shorest distance (39 - 34 = 5).
My brain is a little fried, and I know I am missing something simple. Can anyone help?
What you want is addition and subtraction modulo 60. Check out the % operator. Make sure you handle negatives correctly.
If you don't want to use % operator, try to think this way:
for each couple of points (t1; t2), you'll have two way to connect them: one path will cross 0 (12 o'clock), and the other won't.
Provided that t2 >= t1, the second distance is easy to calculate: it's t2 - t1.
the other distance is t1 + 60 - t2
I think your mistake was adding 60 in the first expression.
Related
I am trying to run an Explanatory Factor Analysis on my questionnaire data.
I have data for 201 participants and 30 questions. The head of my data looks somehow like this (I am showing only the first 5 questions to give an idea of the dataset structure):
Q1 Q2 Q3 Q3 Q4 Q5
1 14 0 20 0 0 0
2 14 14 20 20 20 1
3 20 18 20 20 20 9
4 14 14 20 20 20 0
5 20 18 20 20 20 5
6 20 18 20 20 8 7
I want to find multivariate outliers ,so I am trying to calculate the Mahalanobis distance (cases with Mahalanobis Distance p values bigger than 0.001 are considered outliers).
I am using this code in R-studio (all_data_EFA is my dataset name):
distance <- as.matrix(mahalanobis(all_data_EFA, colMeans(all_data_EFA), cov = cov(all_data_EFA)))
Mah_significant <- all_data_EFA %>%
transmute(row_number = 1:nrow(all_data_EFA),
Mahalanobis_distance = distance,
Mah_p_value = pchisq(distance, df = ncol(all_data_EFA), lower.tail = F)) %>%
filter(Mah_p_value <= 0.001)
However, when I run "distance" I get the following Error:
Error in solve.default(cov, ...) :
Lapack routine dgesv: system is exactly singular: U[26,26] = 0
As far as I understood, this means that the covariance matrix of my data is singular, hence the matrix is not invertible and I cannot calculate Mahalanobis distance.
Is there an alternative way to calculate multivariate outliers or how can I solve this problem?
Many thanks.
Let's say we have a 24 hour clock where all time is represented in minutes. That gives us 24 * 60 possible time points from 0 hours to 24 hours. The clockwise distance between two time points T1, T2 is simply |T1 - T2| since the time is represented in minutes.
Now, how do I obtain the counter clockwise distance between T1 and T2 ? Would I do something like
(-|T1 - T2|) % 1440?
have you considered:
24 * 60 - |T1 - T2|
So I have a rectilinear grid that can be described with 2 vectors. 1 for the x-coordinates of the cell centres and one for the y-coordinates. These are just points with spacing like x spacing is 50 scaled to 10 scaled to 20 (55..45..30..10,10,10..10,12..20,20,20) and y spacing is 60 scaled to 40 scaled to 60 (60,60,60,55..42,40,40,40..40,42..60,60) and the grid is made like this
e.g. x = 1 2 3, gridx = 1 2 3, y = 10 11 12, gridy = 10 10 10
1 2 3 11 11 11
1 2 3 12 12 12
so then cell centre 1 is 1,10 cc2 is 2,10 etc.
Now Im trying to formulate an algorithm to calculate the positions of the cell edges in the x and y direction. So like my first idea was to first get the first edge using x(1)-[x(2)-x(1)]/2, in the real case x(2)-x(1) is equal to 60 and x(1) = 16348.95 so celledge1 = x(1)-30 = 16318.95. Then after calculating the first one I go through a loop and calculate the rest like this:
for aa = 2:length(x)+1
celledge1(aa) = x(aa-1) + [x(aa-1)-celledge(aa-1)]
end
And I did the same for y. This however does not work and my y vector in the area where the edge spacing should be should be 40 is 35,45,35,45... approx.
Anyone have any idea why this doesnt work and can point me in the right direction. Cheers
Edit: Tried to find a solution using geometric alebra:
We are trying to find the points A,B,C,....H. From basic geometry we know:
c1 (centre 1) = [A+B]/2 and c2 = [B+C]/2 etc. etc.
So we have 7 equations and 8 variables. We also know the the first few distances between centres are equal (60,60,60,60) therefore the first segment is 60 too.
B - A = 60
So now we have 8 equations and 8 variables so I made this algorithm in Matlab:
edgex = zeros(length(DATA2.x)+1,1);
edgey = zeros(length(DATA2.y)+1,1);
edgex(1) = (DATA2.x(1)*2-diffx(1))/2;
edgey(1) = (DATA2.y(1)*2-diffy(1))/2;
for aa = 2:length(DATA2.x)+1
edgex(aa) = DATA2.x(aa-1)*2-edgex(aa-1);
end
for aa = 2:length(DATA2.y)+1
edgey(aa) = DATA2.y(aa-1)*2-edgey(aa-1);
end
And I still got the same answer as before with the y spacing going 35,45,35,45 where it should be 40,40,40... Could it be an accuracy error??
Edit: here are the numbers if ur interested and I did the same computation as above only in excel: http://www.filedropper.com/workoutedges
It seems you're just trying to interpolate your data. You can do this with the built-in interp1
x = [30 24 19 16 8 7 16 22 29 31];
xi = interp1(2:2:numel(x)*2, x, 1:(numel(x)*2+1), 'linear', 'extrap');
This just sets up the original data as the even-indexed elements and interpolates the odd indices, including extrapolation for the two end points.
Results:
xi =
Columns 1 through 11:
33.0000 30.0000 27.0000 24.0000 21.5000 19.0000 17.5000 16.0000 12.0000 8.0000 7.5000
Columns 12 through 21:
7.0000 11.5000 16.0000 19.0000 22.0000 25.5000 29.0000 30.0000 31.0000 32.0000
I was giving a test for a company called Code Nation and came across this question which asked me to calculate how many times a number k appears in the submatrix M[n][n]. Now there was a example which said Input like this.
5
1 2 3 2 5
36
M[i][j] is to calculated by a[i]*a[j]
which on calculation turn I could calculate.
1,2,3,2,5
2,4,6,4,10
3,6,9,6,15
2,4,6,4,10
5,10,15,10,25
Now I had to calculate how many times 36 appears in sub matrix of M.
The answer was 5.
I am unable to comprehend how to calculate this submatrix. How to represent it?
I had a naïve approach which resulted in many matrices of which I think none are correct.
One of them is Submatrix[i][j]
1 2 3 2 5
3 9 18 24 39
6 18 36 60 99
15 33 69 129 228
33 66 129 258 486
This was formed by adding all the numbers before it 0,0 to i,j
In this 36 did not appear 5 times so i know this is incorrect. If you can back it up with some pseudo code it will be icing on the cake.
Appreciate the help
[Edit] : Referred Following link 1 link 2
My guess is that you have to compute how many submatrices of M have sum equal to 36.
Here is Matlab code:
a=[1,2,3,2,5];
n=length(a);
M=a'*a;
count = 0;
for a0 = 1:n
for b0 = 1:n
for a1 = a0:n
for b1 = b0:n
A = M(a0:a1,b0:b1);
if (sum(A(:))==36)
count = count + 1;
end
end
end
end
end
count
This prints out 5.
So you are correctly computing M, but then you have to consider every submatrix of M, for example, M is
1,2,3,2,5
2,4,6,4,10
3,6,9,6,15
2,4,6,4,10
5,10,15,10,25
so one possible submatrix is
1,2,3
2,4,6
3,6,9
and if you add up all of these, then the sum is equal to 36.
There is an answer on cstheory which gives an O(n^3) algorithm for this.
Say I have 7 items in A and 4 items in B
A=[10;40;90;130;200;260;320]
B=[100;300;500;1000]
I want to have the list of possible combinations where :
All sub-components of A MUST be included
sub-components of B can be added until the the SUM of all sub-componenets added is greater than 2000
Anyone has an idea how to do this in Matlab ?
My try :
X=sum(A);
y=1;
for Y=1:((length(A))-1);
X=X+B(y);
if(X>2000)
disp('Following is unacceptable')
end
y=y+1
end
However this code is not correct. It just adding the first element of B then adding it with the second element and so on. It isn't providing me with possible combinations.
Example :
sum(A) + B(1) = OK
sum(A) + B(4) = NOT OK
sum(A) + B(1) + B(2) = OK
sum(A) + B(2) + B(3) = OK
etc...
I want this to be automated if values of A or B change in the future. I am not sure if this is a case of probability as well.
Just use nchoosek and a double for-loop to go through all possible combinations of elements in B:
SA = sum(A);
for k = 1:numel(B)
for idx = nchoosek(1:numel(B), k)'
B_subset = B(idx);
if (SA + sum(B_subset) <= 2000)
disp([A(:)', B_subset(:)'])
end
end
end
This prints all combinations with a sum less than (or equal to) 2000. For your example we get:
10 40 90 130 200 260 320 100
10 40 90 130 200 260 320 300
10 40 90 130 200 260 320 500
10 40 90 130 200 260 320 100 300
10 40 90 130 200 260 320 100 500
10 40 90 130 200 260 320 300 500
10 40 90 130 200 260 320 100 300 500
Explanation:
The inner for-loop:
The inner for-loop uses nchoosek(1:numel(B), k), which generates all k-length combinations out of 1...length(B) (I'm using numel instead of length out of habit; in this case it has the same effect). For example, in our case B has 4 elements, so for k = 3 we get nchoosek(1:4, 3):
1 2 3
1 2 4
1 3 4
2 3 4
What we get from this is all the possible k-length combinations of indices of elements in B. In each iteration, this for-loop assigns a different combination of indices to idx. How do we convert the indices of B to real elements? We simply write B(idx).
Inside loop the combination is tested: if the total sum(A) + sum(B(idx)) is less than (or equal to) 2000, that combination is displayed.
The outer for-loop:
The outer for-loop simply iterates over all possible lengths of combinations (that is, over all possible values of k).
Hope that helps!
P.S:
Some MATLAB programming tips for the future:
1. Variable names are case-sensitive.
2. You don't need to increment the loop variable. The for loop does that automatically for you.
The best approach would involve some recursion, like this:
sumA=sum(A);
find_CombinationsOfB(B,sumA,[])
function ret=findCombinationsOfB(in_vals,total_sum,already_contained)
if total_sum>2000
ret=false;
else
for y=1:length(in_vals);
if (~findCombinationsOfB(in_vals([1:(y-1);(y+1):length(in_vals)],total_sum+in_vals(y),[already_contained in_vals(y))
display([already_contained in_vals])
end
end
ret=true;
end
Essentially what this does is tries each combination of B. It will print any that don't add up to 2000, including the sum from A.
Step by step, here's what it does:
Initially, the full array of B is passed, along with the sum of A. An empty array is passed to store which elements of B have been used so far.
Each element added in turn to the function, and called again with a new sum, and with a value missing from the array.
If at any point the array sum is over 2000, it stops that chain of reasoning.
If you want to know more about how this works, print in_vals, total_sum, and already_contained in the start of the function, like this:
fprintf("in_vals=%s total_sum=%i already_contained=%s",mat2str(in_vals),total_sum,mat2str(already_contained));
It should show you at each iteration what is happening.
Assuming B is not very long (around 10 elements), an exhaustive search through all combinations will work just fine. You can carry out this exhaustive search with a recursive function, but the code below uses a trick that's particularly concise in MATLAB: it sweeps through all combinations of the elements of B by representing each combination as a binary bit string.
% examine each of 2^length(B) combinations
for i=0:2^length(B)-1
% converts the binary string into an array of 0 and 1 used to select elements in B
combo = dec2bin(i, length(B))-'0';
% print the combination of elements if their sum is large
if combo * B + sum(A) > 2000
disp(find(combo));
end
end
There are 2^length(B) possible combinations. This examines them in turn, representing the combination as a binary string of length length(B), and evaluating the sum of these elements (with a dot product between the bit string and B).