Test for scalar function inputs is failing - matlab

Despite using isscalar, isinteger... the result after running is still true, I still had this test which is incorrect and in relation with Scalar values.
My program:
function valid = valid_date(year, month, day)
[y1 y2] = size(year);
[m1 m2] = size(month);
[d1 d2] = size(day);
if (mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0
is_leap_year = 1;
else
is_leap_year = 0;
end
if ~(y1==y2==d1==d2==m1==m2==1)
valid = false;
elseif any(month == [1, 3, 5, 7, 8, 10, 12])
valid = (day >0 && day <= 31)
elseif any(month == [4, 6, 9, 11])
valid = day >0 && day <= 30;
elseif month == 2 && is_leap_year == 1
valid = (day >0 && day <=29);
elseif month == 2 && is_leap_year == 0
valid = (day >0 && day <=28);
else
valid = false;
end
end
The result after submitting my program, all tests are passed except the one related to scalar values:
Why did my program fail on the non-scalar test?

The way you're checking for scalars is really not well defined.
~(y1==y2==d1==d2==m1==m2==1)
This chained equivalence check is not the same as checking if all of your variables are equal to 1, consider the following counter-example:
1==0==0==1 % Output: 1
In this case none of your comparison variables should be 0, so you might skirt this issue, but it's still best to avoid it. You're also contending with floating point comparisons which are prone to issues.
You should use isscalar, you say you tried it but didn't show how. Something like this should work:
function valid = valid_date(year, month, day)
if ~( isscalar(year) && isscalar(month) && isscalar(day) )
valid = false;
return
end
% ... other code now we know inputs are scalar
end

Thank you so much #Wolfie. The problem is solved.
I used what you told me about and put it at the beginning of my function.
I show you guys the code, in case you had the same error:
function valid = valid_date(year, month, day)
if ~(isscalar(year) && isscalar(month) && isscalar(day))
valid = false;
return
end
if ((mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0)
is_leap_year = 1;
else
is_leap_year = 0;
end
if any(month == [1, 3, 5, 7, 8, 10, 12])
valid = (day >0 && day <= 31);
elseif any(month == [4, 6, 9, 11])
valid = day >0 && day <= 30;
elseif (month == 2 && is_leap_year == 1)
valid = (day >0 && day <=29);
elseif (month == 2 && is_leap_year == 0)
valid = (day >0 && day <=28);
else
valid = false;
end
end
Yaaay all the tests are passed lhamdullah!

Related

Function that take date and return the statement of the validation of the date

Write a function called valid_date that takes three positive integer scalar inputs year, month, day. If these three represent a valid date, return a logical true, otherwise false. The name of the output argument is valid. If any of the inputs is not a positive integer scalar, return false as well. Note that every year that is exactly divisible by 4 is a leap year, except for years that are exactly divisible by 100. However, years that are exactly divisible by 400 are also leap years. For example, the year 1900 was not leap year, but the year 2000 was. Note that your solution must not contain any of the date related built-in MATLAB functions.
samples:
valid = valid_date(2018,4,1)
valid = valid_date(2018,4,31)
The outputs are :
valid =
logical
1
valid =
logical
0
Here is a partial solution:
function valid= valid_date(year,month,date)
if nargin~=3
valid=false;
elseif ~isscalar(year) | ~isscalar(month) | ~isscalar(date)
valid=false;
elseif year<1 || month<1 || date<1
valid=false;
elseif year~=fix(year) || month~=fix(month) || date~=fix(date)
valid=false;
elseif month>12 || date>31
valid=false;
elseif month==2
if (rem(year,400)==0 || (rem(year,4)==0 && rem(year,100)~=0)) && date<30
valid=true;
elseif (rem(year,400)~=0 || (rem(year,4)~=0 && rem(year,100)==0)) && date<29
valid=true;
else
valid=false;
end
else
days = [31 29 31 30 31 30 31 31 30 31 30 31];
totaldays = days(month);
if date>totaldays
valid=false;
else
valid=true;
end
end
end
My solution is:
function out= valid_date(y,m,d)
if mod(y,4)==0
if mod (y,100)==0
if mod(y,400)==0
leap =true;
else
leap=false;
end
else
leap =true;
end
else
leap= false;
end
if y>0 &m>0&d>0 &y==fix(y)&m==fix(m)&d==fix(d)&m<=12 &isscalar(y)&isscalar(m)& isscalar(d)
if (m==1 | m==3|m==5|m==7 |m==8 |m==10 |m==12)&d <=31
out=true;
elseif d<=30
if m==2
if leap==true & d<=29
out =true;
elseif leap==false &d<=28
out=true;
else
out=false;
end
else
out=true;
end
else
out =false;
end
else
out= false;
end

Leap years not working in Date and Time program in Dlang

I haven't been programming very long, so I'm practicing some logic exercises in dlang. Any ideas on what I've done wrong here. When I get to a leap year, my program just keeps looping on the WHILE.
import std.stdio;
void main()
{
bool dead;
string thing;
int phew = 5; //days
int tahr = 1; //months
int tron; //monthsDate
string[7] days = ["Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"];
int date = 28;
string[12] months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
int year = 1996;
int hours = 11;
int mins = 28;
string ampm = "pm";
bool ly;
int leap = 1996;
int cen = 996;
//writeln("This program is incomplete. Obviously.");
write("Press Enter to Continue.");
readf("%s\n",&thing);
while(!dead)
{
while(hours <= 12)
{
while(mins <= 59)
{
if(mins < 10)
write(date," ",months[tahr],", ",year,". ",days[phew],". ",hours,":0",mins,ampm,": ");
else
write(date," ",months[tahr],", ",year,". ",days[phew],". ",hours,":",mins,ampm,": ");
readf("%s\n",&thing);
mins++;
}
hours++;
if(hours == 12 && ampm == "am")
{
ampm = "pm";
}
else if (hours == 12 && ampm == "pm")
{
ampm = "am";
phew++;
date++;
if(phew > 6)
phew = 0;
if((date == 29 || date == 30) && tahr == 1)
{
while(leap <= year) //this assuming time travel doesn't work
{ //reminder: add time travel
if (leap == year)
{
ly = true;
break;
}
leap+=4;
ly = false;
}
if(!ly || date == 30)
{
date = 31;
leap-=4;
}
}
if(!ly || date == 30)
{
date = 31;
leap-=4;
}
}
if(date == 31 && (tahr == 1 || tahr == 3 || tahr == 5 || tahr == 8 || tahr == 10))
{
date = 1;
tahr++;
}
else if (tahr == 11 && date == 32)
{
tahr = 0;
date = 1;
year++;
cen++;
if(cen == 1000)
{
writeln("Happy Millennium!");
cen = 0;
}
else
writeln("Happy New Year!");
}
else if(date == 32 && (tahr == 0 || tahr == 2 || tahr == 4 || tahr == 6 || tahr == 7 || tahr == 9))
{
date = 1;
tahr++;
}
}
if(hours == 13)
{
hours = 1;
}
mins = 0;
}
}
}
The important part is this:
if((date == 29 || date == 30) && tahr == 1)
{
while(leap <= year) //this assuming time travel doesn't work
{ //reminder: add time travel
if (leap == year)///
{
ly = true;
break;
}
leap+=4;
ly = false;
}
if(!ly || date == 30)
{
date = 31;
leap=-4;
}
}
So, I figured out the issue almost immediately after posting. Basically, I wrote =+ instead of +=. Very simple mistake. That's what I get for typing too fast. So, I've fixed up the code now, if you have any other suggestions, make sure to put them in the comments. Thanks.
Decided to print out leap into the terminal, and I figured out my issue. Leap was continuously equal to 4, because I wrote =+ instead of +=. It was just a case of clicking the wrong button first. That's what I get for typing fast. The program works now, as far as I know. Feel free to correct me on anything else you may notice.
I haven't read it in depth, but I recommend you add lots of debug writelns.
Particularly just inside the block you're THINKING should get run:
if((date == 29 || date == 30) && tahr == 1) {
writefln("Handling leap years...");
while(leap <= year) //this assuming time travel doesn't work
{ //reminder: add time travel
writefln("In loop, Leap <= year? %s", leap <= year);
This will allow you to debug more what is actually happening when your program is run.

Last elseif statement does not execute

My last elseif statement does not execute even if the conditions are met:
Currency_Exchanage != 'Select...' and all other variables (ETF_Exchanage, Index_Exchanage and Stock_Exchanage) = 'Select...'
Here is the section of code that I am concerned about:
if (strcmp(ETF_Exchanage,'Select...') == 1) && (strcmp(Stock_Exchanage,'Select...') == 1) && (strcmp(Index_Exchanage,'Select...') == 1)...
(strcmp(Currency_Exchanage,'Select...') == 1)
if db == 1 && uni == 1
tickers = gnr_bloomberg; % Analsise Bloomberg natural resources
nrm=1;
elseif db == 1 && uni == 2
tickers = all_bloomberg; % Analsise Bloomberg all
nrm=1;
elseif db == 2 && uni == 1
tickers = gnr_yahoo; % Analsise Yahoo natural resources
nrm=1;
elseif db == 2 && uni == 2
tickers = all_yahoo; % Analsise Yahoo all
nrm=1;
end
else
%Yahoo inputs
if (strcmp(ETF_Exchanage,'Select...') == 0) && (strcmp(Stock_Exchanage,'Select...') == 1) && (strcmp(Index_Exchanage,'Select...') == 1)...
(strcmp(Currency_Exchanage,'Select...') == 1); %Choose exhanges from ETF
tickers = ETF_Yahoo(:,1);
Exchanges = ETF_Yahoo(:,2);
Exchange = ETF_Exchanage;
db=2; %Yahoo Selection
elseif (strcmp(Index_Exchanage,'Select...') == 0) && (strcmp(Stock_Exchanage,'Select...') == 1) && (strcmp(ETF_Exchanage,'Select...') == 1)...
(strcmp(Currency_Exchanage,'Select...') == 1); %Choose exhanges from Index
tickers = Index_Yahoo(:,1);
Exchanges = Index_Yahoo(:,2);
Exchange = Index_Exchanage;
db=2;
elseif (strcmp(Stock_Exchanage,'Select...') == 0) && (strcmp(ETF_Exchanage,'Select...') == 1) && (strcmp(Index_Exchanage,'Select...') == 1)...
(strcmp(Currency_Exchanage,'Select...') == 1); %Choose exhanges from Stock
tickers = Stock_Yahoo(:,1);
Exchanges = Stock_Yahoo(:,2);
Exchange = Stock_Exchanage;
db=2;
elseif (strcmp(Currency_Exchanage,'Select...') == 0) && (strcmp(Stock_Exchanage,'Select...') == 1) && (strcmp(Index_Exchanage,'Select...') == 1)...
(strcmp(ETF_Exchanage,'Select...') == 1); %Choose exhanges from Currency
tickers = Currency_Yahoo(:,1);
Exchanges = Currency_Yahoo(:,2);
Exchange = Currency_Exchanage;
db=2;
else
msg = 'Error occurred.\Only one Yahoo input menue must be used!';
error(msg)
end
end
Any Help would be much appropriated, I can't see where I'm going wrong here. I am using Matlab 2013a.
Put a breakpoint at the elseif statement in question and then check in the command window what your condition evaluates to.
If it does not evaluate like expected, check what the individual terms evaluate to.
It is important to actually test what the conditions evaluate to in matlab, rather than only visually comparing the string values.
Usually by that point you should get a rough idea what is wrong.
However in your case we can't do these steps for you because something is off. Your code condensed to the more reasonable minimal example
if 1 && 1 && 1...
1;
disp('I was here')
end
does not even execute in R2014a since the interpreter complains about '...' being an unexpected matlab expression.

Checking if a Date is Valid in MATLAB

So as to not mislead anyone, this is a HW problem that I am attempting to complete and need a little help with. The problem itself is pretty self-explanatory. I have to write a function where I input a string 'Month Day, Year' and have it tell me whether or not it's valid (true or false statements). I have it working for almost everything, except now it doesn't seem to recognize my constraints for possible days.
function[valid] = isValidDate(str)
[date, year] = strtok(str, ','); %Should give me the date and year
[~, year2] = strtok(year, ' ');
[month, day] = strtok(date, ' '); %Should give me month and the day
day = round(day);
if length(date) < 6
valid = false;
elseif month(1) == upper(month(1))
valid = true;
elseif length(date) >= 12
valid = false;
end
if year2 >= 0
valid = true;
else
valid = false;
end
leapyear = mod(year, 400) == 0 | (mod(year, 4) == 0 ~= mod(year, 100) == 0);
switch month
case {'September','April','June','November'}
day <= 30;
valid = true;
case {'February'}
if leapyear
day <= 29;
valid = true;
else
day <= 28;
valid = true;
end
case {'January', 'March', 'May', 'July', 'August', 'October', 'December'}
days <= 31;
valid = true;
otherwise
valid = false;
end
end
So basically
valid4 = isValidDate('December 29.9, -1005.7')
valid = false
Note: There will be no suffix after the day. My only issue now is that my function doesn't realize my constraints on days. it likes to think 'February 30, 2014' is possible
Code
function[valid] = isValidDate(str)
[date1, year1] = strtok(str, ','); %Should give me the date and year
[month1, day1] = strtok(date1, ' '); %Should give me month and the day
%// 1. Take care of bad month strings
all_months = {'January', 'February','March', 'April', 'May','June',...
'July', 'August', 'September','October','November' 'December'} ;
if ~ismember(cellstr(month1),all_months)
valid = false;
return;
end
%// 2. Take care of negative or fraction days
day1 = day1(isstrprop(day1,'digit')); %// Take care of suffixes after day string
num_day = str2double(day1);
if round(num_day)~=num_day || num_day<1
valid = false;
return;
end
%// 3. Take care of fraction or negative years
num_year = str2double(strtok(year1,','));
if round(num_year)~=num_year || num_year<0
valid = false;
return;
end
lpyr =mod(num_year, 400) == 0 | (mod(num_year, 4) == 0 ~= mod(num_year, 100) == 0);
switch month1
case {'September','April','June','November'}
if num_day > 30
valid = false;
return;
end
case {'February'}
if (lpyr && num_day > 29) | (~lpyr && num_day > 28)
valid = false;
return;
end
case {'January', 'March', 'May', 'July', 'August', 'October', 'December'}
if num_day > 31;
valid = false;
return;
end
end
valid = true; %// We made it through!
return;
If you would prefer a compact code -
function valid = isValidDate(str)
[date1, year1] = strtok(str, ','); %Should give me the date and year
[month1, day1] = strtok(date1, ' '); %Should give me month and the day
%// 1. Take care of bad month strings
all_months = {'January', 'February','March', 'April', 'May','June',...
'July', 'August', 'September','October','November' 'December'} ;
valid_month = ismember(cellstr(month1),all_months);
%// 2. Take care of negative or fraction days
day1 = day1(isstrprop(day1,'digit')); %// Take care of suffixes after day string
num_day = str2double(day1);
valid_day = round(num_day)==num_day && num_day>=1;
%// 3. Take care of fraction or negative years
num_year = str2double(strtok(year1,','));
valid_year = round(num_year)==num_year && num_year>=0;
%// 4. Take care of valid days based on leap year and days in a month limits
lpyr = mod(num_year, 400) == 0 | (mod(num_year, 4) == 0 ~= mod(num_year, 100) == 0);
valid_leapyear = true;
switch month1
case {'September','April','June','November'}
valid_leapyear = num_day<=30;
case {'February'}
valid_leapyear = ~((lpyr && num_day>29) || (~lpyr && num_day>28));
case {'January', 'March', 'May', 'July', 'August', 'October', 'December'}
valid_leapyear = num_day<=31;
end
valid = valid_year & valid_month & valid_day & valid_leapyear;
return;
I made some simple function, using the java interface in matlab. Hope it will be useful.
function [valid] = isValidDate(dateStr)
valid = true;
dateFormat = java.text.SimpleDateFormat('MMM dd, yyyy');
dateFormat.setLenient(false);
try
dateFormat.parse(dateStr);
valid = true;
catch err
valid = false;
end
end
Example:
isValidDate('December 21, 1934'); % gives 1
isValidDate('December 29.9, -1005.7'); % gives 0

unexpected results of a function in matlab

Normally this function should give me the values ​​1, 2, 3 or 4. but when I use it, I get 0, 1 or 2. Could you help me to know where is the problem:
function Vecteur_retour = var_Test(Test)
AA = Test;
var_Test = zeros(1,2000);
for i=3:1:2000
if AA(i)<=AA(i-1) && AA(i-1)<=AA(i-2)
var_Test(i)=1;
else
if AA(i)<=AA(i-1) && AA(i-1)>AA(i-2)
var_Test(i)=2;
if AA(i)>AA(i-1) && AA(i-1)<=AA(i-2)
var_Test(i)=3;
else
if AA(i)>AA(i-1) && AA(i-1)>AA(i-2)
var_Test(i)=4;
end
end
end
end
end
Vecteur_retour = var_Test;
Vector comparisons will be much faster:
var_Test = ones(1,2000);
delta_Test = diff(Test);
var_Test([0 0 delta_Test(1:end-1)] > 0) = 2;
var_Test([0 delta_Test] > 0) = var_Test([0 delta_Test] > 0) + 2;
var_Test(1:2) = 0;
Probably because you never reach the cases var_Test(i) = 3 or var_Test(i) = 4.
You have a problem with your if and end blocks. The way you have it, case 3 is only reached if case 2 is hit first, but these are contradictory.
You want code more like.
function Vecteur_retour = var_Test(Test)
AA = Test;
var_Test = zeros(1,2000);
for i=3:1:2000
if AA(i)<=AA(i-1) && AA(i-1)<=AA(i-2)
var_Test(i)=1;
else
if AA(i)<=AA(i-1) && AA(i-1)>AA(i-2)
var_Test(i)=2;
else % you forgot this else
if AA(i)>AA(i-1) && AA(i-1)<=AA(i-2)
var_Test(i)=3;
else
if AA(i)>AA(i-1) && AA(i-1)>AA(i-2)
var_Test(i)=4;
end
end
end
end
end
Vecteur_retour = var_Test;
Careful indentation would have helped here.