Hey guys, i am trying to solve this assignemnt. :
Write a function called day_diff that takes four scalar positive integer inputs, month1, day1, month2, day2. These represents the birthdays of two children who were born in 2015. The function returns a positive integer scalar that is equal to the difference between the ages of the two children in days. Make sure to check that the input values are of the correct types and they represent valid dates. If they are erroneous, return -1. An example call to the function would be >> dd = day_diff(1,30,2,1); which would make dd equal 2. You are not allowed to use the built-in function datenum or datetime. Hint: store the number of days in the months of 2015 in a 12-element vector (e.g., 31, 28, 31, 30 …) and use it in a simple formula.
I have figured the Hard part but i have problems how to make it accpent only whole possitve numbers and no matrixes as an input. Here is my code :
function [d] = day_diff( month1,day1,month2,day2 )
M=[31,28,31,30,31,30,31,31,30,31,30,31];
if month1==fix(month1)&&month1==fix(month1) && day1==fix(day1) && day2==fix(day2) && isscalar(month1)&&isscalar(day1)&&isscalar(month2)&&isscalar(day2) && day1>0 && day2 > 0 && month1 <=12 && month1 >= 1 && month2 <=12 && month2 >= 1 && M(month1) >= day1 && M(month2) >= day2
d1 = day1 + sum(M(1:1:month1-1));
d2 = day2 + sum(M(1:1:month2-1));
dd = d2-d1;
if dd <0
d = dd*(-1);
else
d = dd;
end
else d = -1;
end
end

3 comentarios

himanshu tripathi
himanshu tripathi el 9 de Dic. de 2018
Editada: himanshu tripathi el 9 de Dic. de 2018
code not working for day1 argument as array
Walter Roberson
Walter Roberson el 9 de Dic. de 2018
... And?
A number of errors have been pointed out in the original code.
Jan
Jan el 10 de Dic. de 2018
@himanshu tripathi: I have mentioned 18 month ago, that if month1==fix(month1) && ... will fail, if the inputs are not scalars. Please take the time to read the already posted solutions.
You cannot call this function without inputs.

Iniciar sesión para comentar.

 Respuesta aceptada

Jan
Jan el 13 de Mzo. de 2017
Editada: Jan el 13 de Mzo. de 2017
if month1 == fix(month1) && month1==fix(month1) ...
This fails, if month1 is not scalar, because than the == comparison replies a logical array and this collides with using the && operator. The solution is easy: Check at first if teh inputs are scalars:
% Short-circuting!
if isscalar(m1) && isscalar(d1) && isscalar(m2) && isscalar(m1) && ...
m1 == fix(m1) && m1==fix(m1) && d1==fix(d1) && d2==fix(d2) && ...
d1 > 0 && d2 > 0 && m1 <= 12 && m1 >= 1 && m2 <=12 && m2 >= 1 && ...
M(m1) >= d1 && M(m2) >= d2
The && operator is "lazy": It does not evaluate the 2nd argument, when the first is false already. This is called "short-circuting".
In this order the terms "M(m1)" and "M(m2)" are secure also: m1 and m2 has been tested before to be legal indices: integer values and in the allowed range.
I've used "m1" instead of "month1" here, because this is easier to read an matches into the interface of the forum. It is questionable if "month1" or "m1" is better.
Hint: With dd = abs(d2 - d1); you do not have to care about the sign.
Note: You've shown your code and your own effort and asked almost a specific question. Therefore I post an answer although I assume this is a homework question. By the way: This problem appeared already in the forum.

7 comentarios

Radoslav Gagov
Radoslav Gagov el 13 de Mzo. de 2017
I forgot what a scalar is now i understand it and I understand your answer. Thank you
Jan
Jan el 13 de Mzo. de 2017
Taken form the answer section:
[Radoslav Gagov wrote:]
Thank for the quick answer.Your code is working buti cant really tell where the difference is. Is it in the order if checks the requarements. Why does it matter if it checks isscalar first.
Jan
Jan el 13 de Mzo. de 2017
Editada: Jan el 13 de Mzo. de 2017
@Radoslav Gagov: Exactly: It is the different order of tests. An example:
x = 1:2; y = 3
if x==fix(x) && y==fix(y) && isscalar(x) && isscalar(y)
Now evaluate this manually:
if [true, true] && true && false && true
The first combination by && is not allowed, because && accepts scalar inputs only. Now change the order:
if isscalar(x) && isscalar(y) && x==fix(x) && y==fix(y)
if false && true && [true, true] && true
Here the problem would occur also, but at the 3rd argument. Matlab parses the complete line and as said already applies a "short-circuting": if the leftmost argument is false already, the rest is not evaluated anymore and therefore the problem with the non-scalar argument does not matter.
This occurres another time for M(m1)<d1: If m1 is not a valid index, e.g. -1 or 3.14, the former tests will break the IF condition before. Moving M(m1) < d1 before the tests would let Matlab stop with an error about the illegal indexing on demand instead of proceeding the code and replying d=-1.
This might be confusing and therefore whenever short-circuting is intented, it is important to add a corresponding comment. Otherwise there is the danger, that the code is edited later and this detail is overseen.
If you are in doubt, avoid the short-circuting and split the condition:
if ~isscalar(m1) || ~isscalar(d1) || ~isscalar(m2) || ~isscalar(m1)
d = -1;
return;
end
% Short-circuting: M(m1) and M(m2) is save.
if m1 == fix(m1) && m1==fix(m1) && d1==fix(d1) && d2==fix(d2) && ...
d1 > 0 && d2 > 0 && m1 <= 12 && m1 >= 1 && m2 <=12 && m2 >= 1 && ...
M(m1) >= d1 && M(m2) >= d2
d = ...
else
d = -1;
end
This is less elegant. But beyond a certain level elegance can start to look confusing and an important law for efficient program is: Keep it simple stupid.
Marios Pappous
Marios Pappous el 20 de Nov. de 2017
I can't understand the changes that you made in the code above
Jan
Jan el 20 de Nov. de 2017
@Marios: This is a very general statement. Do you mean a specific point and do you have a question?
Jerry Lee
Jerry Lee el 1 de Jun. de 2018
Editada: Jan el 8 de Jun. de 2018
function age_difference_days = day_diff(m1, d1, m2, d2)
Month=[31 28 31 30 31 30 31 31 30 31 30 31];
day1=d1+sum(Month(1:(m1-1)));
day2=d2+sum(Month(1:(m2-1)));
if ~isscalar(m1) || ~isscalar(d1) || ~isscalar(m2) || ~isscalar(d2)
age_difference_days=-1;
elseif m1<1 || d1<1 || m2<1 || d2<1 || m1>12 || d1>31 || m2>12 || d2>31
age_difference_days=-1;
elseif Month(m1) < d1 || Month(m2) < d2
age_difference_days=-1;
elseif m1~=fix(m1) || d1~=fix(d1) || m2~=fix(m2) || d2~=fix(d2)
age_difference_days=-1;
else
age_difference_days=abs(day1-day2);
end
This code works well on the most of the cases.Except for the input which is fraction. For instance, day_diff(2.3,4,5,6). I am wondering about if there is something wrong about
elseif m1~=fix(m1) || d1~=fix(d1) || m2~=fix(m2) || d2~=fix(d2)
age_difference_days=-1;
Thanks for your support.
Jan
Jan el 8 de Jun. de 2018
The line to check that the inputs have integer values ( m1~=fix(m1) ) looks okay. Perhaps m1 ~= abs(fix(m1)) is better. But move it before the Month(m1) < d1 test, because here m1 is used as index already, which fails, if it does not have an integer value.
There is a problem in Month(m1) < d1, because Month(m1) == d1 is valid also, isn't it? Exclude 0 also.

Iniciar sesión para comentar.

Más respuestas (3)

Govind Mishra
Govind Mishra el 14 de Mzo. de 2018
Editada: Walter Roberson el 14 de Mzo. de 2018

0 votos

You can use round function to get an integer out of float and check if a float present or not.
function dd=day_diff(m1,d1,m2,d2)
num_of_days=[31,28,31,30,31,30,31,31,30,31,30,31];
dd=-1;
mmm1=round(m1);mmm2=round(m2);ddd1=round(d1);ddd2=round(d2);
if(isscalar(d1)&&isscalar(d2)&&isscalar(m1)&&isscalar(m2))
if(d1-ddd1 || d2-ddd2 || m1-mmm1 || m2-mmm2)
dd=-1;
else
if (m1<1||m1>12||m2<1||m2>12)
dd=-1;
else
if(d1>num_of_days(m1) || d2>num_of_days(m2) || d1<1 || d2<1)
dd=-1;
else
dd1=sum(num_of_days(1:m1));
dd1=dd1+d1-num_of_days(m1);
dd2=sum(num_of_days(1:m2));
dd2=dd2+d2-num_of_days(m2);
if(dd1>=dd2)
dd=dd1-dd2;
else
dd=dd2-dd1;
end
end
end
end
end
Lars Wolff
Lars Wolff el 7 de Jun. de 2018

0 votos

Hi!
I am already again asking why my function will not graded.
My solution:
function [dd] = day_diff(month1, day1, month2, day2)
if (month1 == 2 && day1 >28) || (month2 == 2 && day2 >28)
fprintf('Sorry this data is not correct for the year 2015!\n')
return
end
months = [31 28 31 30 31 30 31 31 30 31 30 31]
if month1 == 1
c1=day1
else
c1 = day1 + sum(months((1:(month1-1))))
end
if month2 == 1
c2 = day2
else
c2 = day2 + sum(months((1:(month2-1))))
end
if c1>=c2
dd=c1-c2
else dd=c2-c1
end
end
Response:
NOTE: the grader will only determine if your
solution for Problem 4 is correct or not.
No score will be given.
Problem 4 (day_diff):
Feedback: Your function performed correctly for argument(s) 1, 30, 2, 1
Feedback: Your function performed correctly for argument(s) 1, 1, 1, 1
Feedback: Your function performed correctly for argument(s) 1, 1, 1, 2
Feedback: Your function performed correctly for argument(s) 1, 2, 1, 1
Feedback: Your function performed correctly for argument(s) 1, 1, 2, 1
Feedback: Your function performed correctly for argument(s) 2, 1, 1, 1
Feedback: Your function performed correctly for argument(s) 1, 31, 2, 1
Feedback: Your function performed correctly for argument(s) 2, 1, 1, 31
Feedback: Your function performed correctly for argument(s) 1, 1, 12, 31
Feedback: Your function performed correctly for argument(s) 2, 1, 3, 1
Feedback: Your function performed correctly for argument(s) 7, 1, 9, 30
Feedback: Your program made an error for argument(s) 2, 29, 1, 22
Your solution is _not_ correct.
Thanks for your help in advance!

6 comentarios

Steven Lord
Steven Lord el 7 de Jun. de 2018
What happens if you call your function with the inputs about which the grader complained?
dd = day_diff(2, 29, 1, 22)
[Note: the "dd = " part is important! It's how the grader is calling your function, most likely.] Does the error you receive make sense? What should it return?
You probably also want to add semicolons at the end of the lines where you define the variables months, c1, c2, and dd. I'm guessing you removed them to debug your code by displaying the intermediate values. Instead, I recommend using the tools provided by MathWorks to step through your code, line by line, examining the values that your code creates / modifies.
Lars Wolff
Lars Wolff el 7 de Jun. de 2018
>> day_diff(2,29,1,22)
months =
31 28 31 30 31 30 31 31 30 31 30 31
c1 =
60
c2 =
22
dd =
38
ans =
38
This is the output, when I skip:
if (month1 == 2 && day1 >28) || (month2 == 2 && day2 >28)
fprintf('Sorry this data is not correct for the year 2015!\n')
return
end
So in my opinion, this is a correct result.
Moreover, the days in dependence of the months are not considered, e.g. what happens with the input (4,31,6,31)??
Walter Roberson
Walter Roberson el 7 de Jun. de 2018
The problem requirements are that the function must return -1 when the dates are not valid. 2, 29 is not a valid date in 2015 so the function must return -1; instead it is failing to return anything.
Steven Lord
Steven Lord el 7 de Jun. de 2018
Perhaps I should have emphasized this important part of my question:
[Note: the "dd = " part is important! It's how the grader is calling your function, most likely.]
Your function throws an error. That is not a correct result for the assignment.
Lars Wolff
Lars Wolff el 8 de Jun. de 2018
Hi Walter! Thank you for the hint and I apologize for I haven't seen it in the question. Currently I am learning matlab with coursera on my own....
Here is my (long) solution - but now it works!!
:-)
function [dd] = day_diff(month1, day1, month2, day2)
months = [31 28 31 30 31 30 31 31 30 31 30 31]
if month1 == 1
c1=day1
else
c1 = day1 + sum(months((1:(month1-1))))
end
if month2 == 1
c2 = day2
else
c2 = day2 + sum(months((1:(month2-1))))
end
if c1>=c2
dd=c1-c2
else dd=c2-c1
end
if ~isscalar(month1) || ~isscalar(day1) || ~isscalar(month2) || ~isscalar(day2)
dd=-1
elseif((month1 == 2 && day1 >28) || (month2 == 2 && day2 >28))
dd=-1
elseif (((month1 == 1 || month1 == 3 || month1 == 5 || month1 == 7 || month1 == 8 || month1 == 10 || month1 == 12) ) && (day1 > 31))
dd=-1
elseif (((month2 == 1 || month2 == 3 || month2 == 5 || month2 == 7 || month2 == 8 || month2 == 10 || month2 == 12) ) && (day2 > 31))
dd=-1
elseif (((month1 == 4 || month1 == 6 || month1 == 9 || month1 == 11) ) && (day1 > 30))
dd=-1
elseif (((month2 == 4 || month2 == 6 || month2 == 9 || month2 == 11) ) && (day2 > 30))
dd=-1
elseif (month1 < 1 || month1 > 12 || month2 < 1 || month2 > 12 || day1 < 1 || day1 > 31 || day2 < 1 || day2 > 31)
dd=-1
end
if round(month1) ~= month1
dd=-1
elseif round(month2) ~= month2
dd=-1
elseif round(day1) ~= day1
dd=-1
elseif round(day2) ~= day2
dd=-1
end
end
Hint:
days_in_month = [31 28 31 30 31 30 31 31 30 31 30 31]
day1 > days_in_month(month1)
Also hint: watch out for negative numbers.

Iniciar sesión para comentar.

Duddela Sai Prashanth
Duddela Sai Prashanth el 23 de Sept. de 2018
Editada: Duddela Sai Prashanth el 23 de Sept. de 2018

0 votos

%This will work for sure.. Tested on different test cases
function age = day_diff(m1,d1,m2,d2)
m = [31 28 31 30 31 30 31 31 30 31 30 31];
if isscalar(m1) && isscalar(m2) && isscalar(d1) && isscalar(d2)
if m1 == 0 || m2 == 0 || d1 == 0 || d2 == 0
age = -1;
elseif m1 > 0 && d1 > 0 && m2 > 0 && d2 > 0 && m1 <= 31 && d1 <=31 && m2 <=31 && d2 <=31
M2=fix(m2); D2 = fix(d2);
M1=fix(m1); D1 = fix(d1);
if M2 == m2 && M1 == m1 && D2 == d2 && D1==d1
Month2 = m(1:m2-1);
Month1 = m(1:m1-1);
Month2 = sum(Month2);
Month1 = sum(Month1);
days2 = Month2 + d2;
days1 = Month1 + d1;
test2 = m(m2) - d2;
test1 = m(m1) - d1;
if test2<0 || test1<0
age = -1;
else
age = (days2-days1)^2;
age = sqrt(age);
end
else
age = -1;
end
else
age = -1;
end
else
age = -1;
end

1 comentario

Jan
Jan el 24 de Sept. de 2018
Editada: Jan el 24 de Sept. de 2018
You can simplify the code by removing repeated code: Set age=-1 once at the beginning and redefine it only if all checks are satisfied.
"m1 <= 31" and "m2 <=31" is not correct: The maximum value of the month is 12, not 31.
function age = day_diff(m1,d1,m2,d2)
age = -1;
m = [31 28 31 30 31 30 31 31 30 31 30 31];
if isscalar(m1) && isscalar(m2) && isscalar(d1) && isscalar(d2)
if m1 > 0 && d1 > 0 && m2 > 0 && d2 > 0 && ...
m1 <= 12 && d1 <= 31 && m2 <= 12 && d2 <= 31
if fix(m2) == m2 && fix(m1) == m1 && ...
fix(d1) == d2 && fix(d1) == d1
if m(m1) >= d1 && m(m2) >= d2
days1 = sum(m(1:m1-1)) + d1;
days2 = sum(m(1:m2-1)) + d2;
age = abs(days2 - days1);
end
end
end
For scalars abs(a-b) is easier than sqrt((a-b)^2). If a temporary variable occurs once only, it might be simpler to use the formula directly.

Iniciar sesión para comentar.

Categorías

Más información sobre Phased Array Design and Analysis en Centro de ayuda y File Exchange.

Etiquetas

Preguntada:

el 13 de Mzo. de 2017

Comentada:

Jan
el 10 de Dic. de 2018

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by