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 commentaires

himanshu tripathi
himanshu tripathi le 9 Déc 2018
Modifié(e) : himanshu tripathi le 9 Déc 2018
code not working for day1 argument as array
Walter Roberson
Walter Roberson le 9 Déc 2018
... And?
A number of errors have been pointed out in the original code.
Jan
Jan le 10 Déc 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.

Connectez-vous pour commenter.

 Réponse acceptée

Jan
Jan le 13 Mar 2017
Modifié(e) : Jan le 13 Mar 2017

1 vote

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 commentaires

Radoslav Gagov
Radoslav Gagov le 13 Mar 2017
I forgot what a scalar is now i understand it and I understand your answer. Thank you
Jan
Jan le 13 Mar 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 le 13 Mar 2017
Modifié(e) : Jan le 13 Mar 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 le 20 Nov 2017
I can't understand the changes that you made in the code above
Jan
Jan le 20 Nov 2017
@Marios: This is a very general statement. Do you mean a specific point and do you have a question?
Jerry Lee
Jerry Lee le 1 Juin 2018
Modifié(e) : Jan le 8 Juin 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 le 8 Juin 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.

Connectez-vous pour commenter.

Plus de réponses (3)

Govind Mishra
Govind Mishra le 14 Mar 2018
Modifié(e) : Walter Roberson le 14 Mar 2018

0 votes

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 le 7 Juin 2018

0 votes

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 commentaires

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.
>> 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 le 7 Juin 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 le 7 Juin 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.
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.

Connectez-vous pour commenter.

Duddela Sai Prashanth
Duddela Sai Prashanth le 23 Sep 2018
Modifié(e) : Duddela Sai Prashanth le 23 Sep 2018

0 votes

%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 commentaire

Jan
Jan le 24 Sep 2018
Modifié(e) : Jan le 24 Sep 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.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Phased Array Design and Analysis dans Centre d'aide et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by