I have been able to retrieve the first day of any given month, and I also know how many days are in that month. How do i calculate the amount of mondays, tuesdays, etc.. left in the month? Below is my code is far.
//Set Days in Month
if(Time.Month == 2)
{
if((Time.Year % 400 == 0) || ((Time.Year % 4 == 0) && (Time.Year % 100 != 0)))
Weekend_Status.Month_Days[Time.Month] = 29;
else
Weekend_Status.Month_Days[Time.Month] = 28;
}
else if(Time.Month == 1 || Time.Month == 3 || Time.Month == 5 || Time.Month == 7 || Time.Month == 8 || Time.Month == 10 || Time.Month == 12)
{
Weekend_Status.Month_Days[Time.Month] = 31;
}
else
{
Weekend_Status.Month_Days[Time.Month] = 30;
}
//Set New Month Start Day
if(Time.Day == 1 && Time.Hour == 0 && Time.Minute == 0 && Time.Second == 1)
{
switch(Time.Day_of_Week)
{
case 0: //Sunday
Weekend_Status.Month_Start_Day = 0;
break;
case 1: //Monday
Weekend_Status.Month_Start_Day = 1;
break;
case 2: //Tuesday
Weekend_Status.Month_Start_Day = 2;
break;
case 3: //Wednesday
Weekend_Status.Month_Start_Day = 3;
break;
case 4: //Thursday
Weekend_Status.Month_Start_Day = 4;
break;
case 5: //Friday
Weekend_Status.Month_Start_Day = 5;
break;
case 6: //Saturday
Weekend_Status.Month_Start_Day = 6;
break;
}
}
You could do something like this, where you take advantage of the modulo operator, using it to count all days in the month where the day occurs. Note: Untested.
// example: count how many Wednesdays
int search_day = 3;
int search_day_count = 0;
int start_day = Weekend_Status.Month_Start_Day;
int end_day = Weekend_Status.Month_Days[Time.Month];
// loop through all days for the given month
for (int day = start_day; day <= start_day + end_day; day++)
{
// count all days that are 7 days apart starting from search_day = 3
if (day == search_day || (day - search_day) % 7 == 0)
{
search_day_count++;
}
}
Related
I'm making a program which calculates the date by giving the program a date and number of days to add to that date in input. In order to do this, I need to make a switch and make it repeat with a loop, but for some reasons, the program gets frozen and doesn't do anything after the user inserts the number of days to add. I've tried removing loop and the program works.
Looking forward to someone who might help me fix this.
Here's the part of the code from getting number of days to add to the end of loop:
cin>>addDays;
while (addDays > 0) {
switch (month) {
//months with 31 days
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
{
finalDay = day + addDays;
if (finalDay > 31) {
addDays = finalDay - 31;
month++;
day = 1;
}
break;
}
//months with 30 days
case 4:
case 6:
case 9:
case 11:
{
finalDay = day + addDays;
if (finalDay > 30) {
addDays = finalDay - 30;
month++;
day = 1;
}
break;
}
//december
case 12:
{
finalDay = day + addDays; //oggi è 10. Voglio aggiungere 30
if (finalDay > 31) { //40 è maggiore di 31
addDays = finalDay - 31; //l'aggiunta 30 diventa 40 - 31 che fa 9
year++;
day = 1;
month = 1;
}
break;
}
//february
case 2:
{
finalDay = day + addDays;
if (year % 4 == 0) {
if (finalDay > 29) {
addDays = finalDay - 29;
month++;
day = 1;
}
}
else {
if (finalDay > 28) {
addDays = finalDay - 28;
month++;
day = 1;
}
}
break;
}
}
}
Your loop runs until addDays falls to <= 0. The problem is, when you add addDays to day, if the resulting finalDay IS within the current month's number of days, you ARE NOT breaking the loop, and you ARE NOT adjusting the values of day or addDays either, so the loop iterates again with the same day and addDays values, calculating the same finalDay value, over and over, endlessly. That is why your program appears frozen.
After fixing that, you are also not taking into account the possibility that addDays might span more than a full month's worth of days. The user could ask to add more than 1 month at a time. So you need to adjust addDays more granularly per month.
Also, when the current month is 2 (February), your leap year calculation is incomplete. Being evenly divisible by 4 is not the only rule you need to check to know if the year is a leap year. A year that is evenly divisible by 4 and 100 but not evenly divisible by 400 is not a leap year.
With that said, try something more like this instead:
bool isLeapYear(int year)
{
return ((year % 4) == 0) &&
(((year % 100) != 0) || ((year % 400) == 0));
}
int lastDayInMonth(int year, int month)
{
switch (month) {
//months with 31 days
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
//months with 30 days
case 4:
case 6:
case 9:
case 11:
return 30;
//month with 28 or 29 days
case 2:
return isLeapYear(year) ? 29 : 28;
}
return 0;
}
int year, month, day, addDays, lastDay;
...
cin >> addDays;
while (addDays > 0) {
lastDay = lastDayInMonth(year, month);
day += addDays;
if (day <= lastDay) break;
addDays -= (lastDay - day);
if (++month == 13) {
++year;
month = 1;
}
day = 1;
}
That being said, have a look at this answer, which wraps up this kind of logic in a reusable struct named Date that has an overloaded operator+= for adding days.
Thank you very much for your help! You made me understand where the mistake was. I've fixed it and it now works perfectly. But because I'm not as experienced as you and I was having difficulties to read that code, instead of doing as you did, I've added an else to every if inside the switch, which resets addDays to 0, because assignment statements copy their value, they don't move it, for some reasons I wasn't thinking about this stupid and basic thing.
And also thanks for letting me notice about the uncomplete leap year algorithm.
Here's the fixed code. Have a good day!
cin>>addDays;
while (addDays > 0) {
switch (month) {
//months with 31 days
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
{
finalDay = day + addDays;
if (finalDay > 31) {
addDays = finalDay - 31;
month++;
day = 0;
}
else {
addDays = 0;
}
break;
}
//months with 30 days
case 4:
case 6:
case 9:
case 11:
{
finalDay = day + addDays;
if (finalDay > 30) {
addDays = finalDay - 30;
month++;
day = 0;
}
else {
addDays = 0;
}
break;
}
//december
case 12:
{
finalDay = day + addDays; //oggi è 10. Voglio aggiungere 30
if (finalDay > 31) { //40 è maggiore di 31
addDays = finalDay - 31; //l'aggiunta 30 diventa 40 - 31 che fa 9
year++;
day = 0;
month = 1;
}
else {
addDays = 0;
}
break;
}
//february
case 2:
{
finalDay = day + addDays;
if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))) {
if (finalDay > 29) {
addDays = finalDay - 29;
month++;
day = 0;
}
else {
addDays = 0;
}
}
else {
if (finalDay > 28) {
addDays = finalDay - 28;
month++;
day = 0;
}
else {
addDays = 0;
}
}
break;
}
}
}
Having trouble determining the cause of this. Everything builds properly just does not print any type of output. I'm sure it is something minuscule so please be understanding and not chew me out for asking such a simple question. Trying my best to learn on my own. The program is supposed to ask you to enter a date dd/mm/yy. Below I have attached the main.cpp and date.h. Thank you for any assistance.
main.cpp
#ifndef DATE_H_
#define DATE_H_
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
class Date
{
private:
int day, month, year;
char format;
bool isLeapYear() const;
int days_in_month() const;
public:
Date(int month=1, int day=1, int year=2000);
void Input();
void Show();
bool Set(int m, int d, int y);
int GetMonth() const;
int GetDay() const;
int GetYear() const;
bool SetFormat(char f);
void Increment(int numDays=1);
int Compare(const Date& d);
void printJulianDate();
};
#endif
//end of date.h
// date.c
#include "date.h"
// constructor
Date::Date(int month, int day, int year)
{
// set the parameters to default values
this->month = 1;
this->day = 1;
this->year = 2000;
this->format = 'D';
// call the method to set the passed month, day and year
if(!Set(month,day,year))
{
cout<<"Invalid date"<<endl; // display error message if invalid date
}
}
// helper function to return if the year is leap or not
bool Date:: isLeapYear() const
{
return ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)));
}
// helper function to return the number of days in the month
int Date::days_in_month() const
{
if(month == 2)
{
if(isLeapYear())
return 29;
else
return 28;
}else if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month ==10 || month==12)
return 31;
else
return 30;
}
// function to input date from the user
void Date:: Input()
{
int m,d,y;
char sep;
// input of date
cout<<"Enter date:";
cin>>m>>sep>>d>>sep>>y;
// loop that continues till the user enters a valid date
while(!Set(m,d,y))
{
cout<<"Invalid date. Try again: ";
cin>>m>>sep>>d>>sep>>y;
}
}
// function to display the date in the format specified
void Date:: Show()
{
if(format == 'D')
{
cout<<month<<"/"<<day<<"/"<<year;
}else if(format == 'T')
{
cout<<setw(2)<<setfill('0')<<month<<"/"<<setw(2)<<setfill('0')<<day<<"/"<<setw(2)<<setfill('0')<<(year%100);
}else if(format == 'L')
{
switch(month)
{
case 1:
cout<<"Jan";
break;
case 2:
cout<<"Feb";
break;
case 3:
cout<<"Mar";
break;
case 4:
cout<<"Apr";
break;
case 5:
cout<<"May";
break;
case 6:
cout<<"June";
break;
case 7:
cout<<"July";
break;
case 8:
cout<<"Aug";
break;
case 9:
cout<<"Sep";
break;
case 10:
cout<<"Oct";
break;
case 11:
cout<<"Nov";
break;
case 12:
cout<<"Dec";
break;
}
cout<<" "<<day<<", "<<year;
}
}
// method to validate the passed arguments and set the date if the arguments represent a valid date
bool Date:: Set(int m, int d, int y)
{
if(y > 1582)
{
if(m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12)
{
if(d < 1 || d > 31)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else if(m == 4 || m == 6 || m == 9 || m == 11)
{
if(d < 1 || d > 30)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else if(m == 2)
{
if((y%400 == 0 ) || ((y%4 == 0) && (y%100) != 0))
{
if(d < 1 || d > 29)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else
{
if(d < 1 || d > 28)
return false;
else{
day = d;
month = m;
year = y;
return true;
}
}
}else
return false;
}else if(y == 1582)
{
if(m >= 10)
{
if(m == 10 || m == 12)
{
if(d < 1 || d > 31)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else if( m == 11)
{
if(d < 1 || d > 30)
return false;
else
{
day = d;
month = m;
year = y;
return true;
}
}else
return false;
}
}
return false;
}
// function to return the month
int Date::GetMonth() const
{
return month;
}
// function to return the day
int Date::GetDay() const
{
return day;
}
// function to return the year
int Date::GetYear() const
{
return year;
}
// function to set the format of the date
bool Date::SetFormat(char f)
{
if(f == 'D' || f == 'T' || f == 'L')
{
format = f;
return true;
}
return false;
}
// function to increment the number of days passed to the date and update the date accordingly
void Date:: Increment(int numDays)
{
day += numDays; // add number of days passed
// loop that continues till the date is valid
while(day > days_in_month())
{
day -= days_in_month();
month++;
if(month > 12) // if month > 12, i.e it represents the first month of next year
{
// increment year and set month to 1
year++;
month = 1;
}
}
}
// function to compare the passed date with this date and return
// -1, if the calling object comes first chronologically
// 0, if the calling object comes first chronologically
// 1, if the objects are the same date
int Date::Compare(const Date& d)
{
if(year < d.year)
return -1;
else if(year > d.year)
return 1;
else
{
if(month < d.month)
return -1;
else if(month > d.month)
return 1;
else
{
if(day < d.day)
return -1;
else if(day > d.day)
return 1;
else
return 0;
}
}
}
// function to print the julian date
void Date:: printJulianDate()
{
int days=0;
// loop to get the day number
for(int i=1;i<month;i++)
{
switch(i)
{
case 1:
days += 31;
break;
case 2:
if(isLeapYear())
days += 29;
else
days += 28;
break;
case 3:
days += 31;
break;
case 4:
days += 30;
break;
case 5:
days += 31;
break;
case 6:
days += 30;
break;
case 7:
days += 31;
break;
case 8:
days += 31;
break;
case 9:
days += 30;
break;
case 10:
days += 31;
break;
case 11:
days += 30;
break;
case 12:
days += 31;
break;
}
}
days += day;
cout<<days<<"-"<<setw(4)<<setfill('0')<<year;
}
Date.h
#ifndef UNTITLED16_DATE_H
#define UNTITLED16_DATE_H
#endif //UNTITLED16_DATE_H
date.cpp
int main(){return 0;}
Since your main function is int main(){return 0;} all your code is doing is: starting up, calling main(), and then returning back to the caller. Of course there is no output involved here...
There are many other details with your code where I am not sure if it will work as you intend. But the minimum change you have to do to see anything is something like this:
#include "Date.h"
#include <iostream>
int main() {
Date theDate;
theDate.Input();
theDate.Show();
// and maybe also
Date theDate2;
theDate2.Input();
if (theDate2.Compare(theDate)) {
std::cout << "true" << std::endl;
}
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am currently making a calendar algorithm and there is a question about it.
I would like to ask the calendar about changing the first day of the month on the calendar.
This is my calendar code:
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
int days(int year, int month)
{
int days, i;
for (i = 1; i<month; i++)
{
if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12)
{
days = days + 31;
}
else if (i == 4 || i == 6 || i == 9 || i == 11)
{
days = days + 30;
}
else if (i == 2)
{
days = days + 28;
}
}
days = days + 365 * (year - 1980);
return days;
}
int leapyear(int year, int month)
{
int i;
i = (year - 1977) / 4;
if (year % 4 == 0 && month>2)
{
i++;
}
return i;
}
int weekday(int days)
{
int i;
i = days % 7;
return i;
}
void calendar(int year, int month, int week)
{
int i, j, k, d, cal[42] = { 0 };
char m[12][10] = { "January", "February", "March", "April", "May", "June", "July", "Agust", "September", "Octorber", "November", "December" };
switch (month)
{
case 1: d = 31;
break;
case 2:
{
if ((year % 4) == 0) d = 29;
else d = 28;
}
break;
case 3: d = 31;
break;
case 4: d = 30;
break;
case 5: d = 31;
break;
case 6: d = 30;
break;
case 7: d = 31;
break;
case 8: d = 31;
break;
case 9: d = 30;
break;
case 10: d = 31;
break;
case 11: d = 30;
break;
case 12: d = 31;
break;
}
printf(" < %d %s >\n", year, m[month - 1]);
printf("===========================\n");
printf("Sun Mon Tue Wed Thu Fri Sat");
printf("\n---------------------------\n");
j = 1;
for (i = (week + 2) % 7; i<(d + (week + 2) % 7); i++)
{
cal[i] = j;
j++;
}
k = 0;
for (i = 0; i<6; i++)
{
for (j = 0; j<7; j++)
{
if (cal[k] == 0)
{
printf(" ");
}
else
{
printf("%3d ", cal[k]);
}
k++;
}
if (i<5)
{
printf("\n---------------------------\n");
}
else
{
printf("\n===========================\n");
}
}
}
void main()
{
int year, month, total_days, week;
char YN = 'Y';
do
{
printf("entered year and month with 1980 ~ 2030.(EX) :2003 5)\n");
scanf_s("%d %d", &year, &month);
if (year >= 1980 && year <= 2030 && month >= 1 && month <= 12)
{
printf("Your entered %dYear %dMonth.\n", year, month);
total_days = days(year, month) + leapyear(year, month);
week = weekday(total_days);
calendar(year, month, week);
}
printf("Retry It?(Y/N):");
YN = _getche();
printf("\n");
} while (YN != 'N');
}
I hope these results come out:
< 2003 May >
Sun Mon Tue Wed Thu Fri Sat
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Retry It?(Y/N):
You never initialize the variable days in the days function.
In C local variables are not automatically initialized to zero. If you don't initialize them, they contain un undetermined value.
So just write:
int days = 0, i;
or better
int days = 0;
for (int i = 1; i<month; i++)
...
I didn't check for other errors or problems, but with the correction the program apparently works fine.
To provide context, I'm working through Programming Praxis Bingo Challenge and wanted to see how fast I could make this code run.
static void fisher_yates(T& source) {
const size_t len = source.size();
for(size_t i = 1; i < len;++i) {
std::swap(source[i],source[rand() % (i+1)]);
}
}
std::array<int,25> generate_table() {
std::array<int,25> bingo_grid;
for(int i = 0 ; i < 25;++i) {
switch(i) {
case 0: case 1: case 2: case 3: case 4:
bingo_grid[i] = rand() % 15 + 1;
break;
case 5: case 6: case 7: case 8: case 9:
bingo_grid[i] = rand() % 15 + 16;
break;
case 10: case 11: case 12: case 13: case 14:
bingo_grid[i] = rand() % 15 + 31;
break;
case 15: case 16: case 17: case 18: case 19:
bingo_grid[i] = rand() % 15 + 46;
break;
case 20: case 21: case 22: case 23: case 24:
bingo_grid[i] = rand() % 15 + 61;
break;
}
}
bingo_grid[12] = 0;
return bingo_grid;
}
bool is_bingoed(const std::array<int,25>& grid) {
// Check columns
if(grid[0] == 0) {
if(grid[1] == 0 && grid[2] == 0 && grid[3] == 0 && grid[4] == 0)
return true;
if(grid[0] == 0 && grid[6] == 0 && grid[18] == 0 && grid[24] == 0)
return true;
if(grid[5] == 0 && grid[10] == 0 && grid[15] == 0 && grid[20] == 0)
return true;
}
if(grid[1] == 0) {
if(grid[6] == 0 && grid[11] == 0 && grid[16] == 0 && grid[21] == 0)
return true;
}
if(grid[2] == 0) {
if(grid[7] == 0 && grid[17] == 0 && grid[22] == 0)
return true;
}
if(grid[3] == 0) {
if(grid[8] == 0 && grid[13] == 0 && grid[18] == 0 && grid[23] == 0)
return true;
}
if(grid[4] == 0) {
if(grid[9] == 0 && grid[14] == 0 && grid[19] == 0 && grid[24] == 0)
return true;
if(grid[8] == 0 && grid[16] == 0 && grid[21] == 0)
return true;
}
if(grid[6] == 0) {
if(grid[6] == 0 && grid[7] == 0 && grid[8] == 0 && grid[9] == 0)
return true;
}
if(grid[12] == 0) {
if(grid[10] == 0 && grid[11] == 0 && grid[13] == 0 && grid[14] == 0)
return true;
}
if(grid[18] == 0) {
if(grid[15] == 0 && grid[16] == 0 && grid[17] == 0 && grid[19] == 0)
return true;
}
return false;
}
static bool mark_card(const int card,std::array<int,25>& bingo_grid) {
for(auto &i : bingo_grid)
if(card == i) {
i = 0;
return true;
}
return false;
}
int play_game() {
// Bingo is 5 columns, each column(n) is random permutation of 1-15*n
// Fisher-Yates to generate random permutations
// Create 500 playing cards
const int max = 500;
std::vector<std::array<int,25>> bingo_cards;
bingo_cards.reserve(max);
for(int i = 0; i<max;++i) {
bingo_cards.push_back(generate_table());
//display_bingo(bingo_cards[i]);
}
// Random shuffle 75 cards
auto iter = boost::counting_range(1,76);
std::vector<int> cards(std::begin(iter),std::end(iter));
fisher_yates(cards);
bool is_finished = false;
int counter = 0;
for(auto card : cards) {
for(auto& playing_card : bingo_cards) {
if(mark_card(card,playing_card)) {
//display_bingo(playing_card);
if(is_bingoed(playing_card))
return counter;
}
}
counter++;
}
return counter;
}
int bingo() {
srand(time(NULL));
int total = 0;
for(int i = 0 ; i < 10000;i++) {
total+=play_game();
}
boost::singleton_pool<boost::pool_allocator_tag, sizeof(int)>::release_memory();
return total / 10000;
}
The original version used a boost::multi_array to represent the grid. After profiling, I changed it to a std::array which got me a significant speed up. I then moved from using fisher_yates shuffle to generate bingo cards to using a random number generator.
Then finally I changed the is_bingoed test function to reduce the number of checks per call to speed up the game-over check.
All this has helped. Right now if I profile this code, the generate_table function takes up 72% of the time, mark_card() is 18%, and is_bingoed() about 6%. I'm looking for hints to see what can be done to improve the speed of either.
My first thought with is_bingoed() is to use the SSE intrinsics to do a compare with 0 (maybe use XOR?) but I don't have any ideas on the generate_table() or mark_car(). This is more of a self challenge for fun but wondered what others thought?
Current timing is it takes 4.6s on a 2Ghz Q6660 (down from 35s originally)
Just focussing on your most expensive function, generate_table, you can simplify this part of the code and make it less branchy, which may help:
for(int i = 0 ; i < 25;++i) {
switch(i) {
case 0: case 1: case 2: case 3: case 4:
bingo_grid[i] = rand() % 15 + 1;
break;
case 5: case 6: case 7: case 8: case 9:
bingo_grid[i] = rand() % 15 + 16;
break;
case 10: case 11: case 12: case 13: case 14:
bingo_grid[i] = rand() % 15 + 31;
break;
case 15: case 16: case 17: case 18: case 19:
bingo_grid[i] = rand() % 15 + 46;
break;
case 20: case 21: case 22: case 23: case 24:
bingo_grid[i] = rand() % 15 + 61;
break;
}
}
e.g.
for(int i = 0 ; i < 25;++i) {
int r = rand() % 15 + 1;
bingo_grid[i] = r + (i / 5) * 15;
}
Beyond that I'd look at a faster rand() and also see if you can get rid of the divide and and modulo.
On a separate note, your algorithm may be flawed in that there is nothing to prevent duplicate numbers in bingo_grid.
Changing the is_bingoed() method to use SSE instructions (using Agner Fog's library) and Paul R's generate_table() reduced the time to just 1.05s. And using Intel's fast_rand() function got it down to 0.38s.
So I thought I'd paste the code changes for others who might be interested.
static unsigned int g_seed;
//Used to seed the generator.
inline void fast_srand( int seed )
{
g_seed = seed;
}
//fastrand routine returns one integer, similar output value range as C lib.
inline int fastrand()
{
g_seed = (214013*g_seed+2531011);
return (g_seed>>16)&0x7FFF;
}
bool is_bingoed(const std::array<int,25>& grid) {
// Check columns
Vec8i vec(grid[0],grid[1],grid[2],grid[3],grid[4],0,0,0);
Vec4i vec2(grid[6],grid[18],grid[24],0);
Vec4i vec3(grid[5],grid[10],grid[15],20);
Vec8i vec4(grid[1],grid[6],grid[11],grid[16],grid[21],0,0,0);
Vec4i vec5(grid[2],grid[7],grid[17],grid[22]);
Vec8i vec6(grid[3],grid[8],grid[13],grid[18],grid[23],0,0,0);
Vec8i vec7(grid[4],grid[9],grid[14],grid[19],grid[24],0,0,0);
Vec4i vec8(grid[8],grid[16],grid[21],grid[4]);
Vec4i vec9(grid[6],grid[7],grid[8],grid[9]);
Vec8i vec10(grid[12],grid[10],grid[11],grid[13],grid[14],0,0,0);
Vec8i vec11(grid[18],grid[15],grid[16],grid[17],grid[19],0,0,0);
if(horizontal_and(vec) && horizontal_and(vec2) && horizontal_and(vec3) && horizontal_and(vec4) &&
horizontal_and(vec5) && horizontal_and(vec6) && horizontal_and(vec7) && horizontal_and(vec8)) {
return false;
}
if(horizontal_and(vec9) && horizontal_and(vec10) && horizontal_and(vec11)) {
return false;
}
return true;
}
Im writing a code that, if you input your birthday date and any other date, it returns the total number of years, months and day that you are alive.
Obs.:including (leap) bissextile years.
Obs.2:for invalid dates, the output must be "data invalida" (invalid date in portuguese).
Inputs/Outputs:
Obs.: The date format is in the brazillian standard, the format is Day / Month / Year.
8 //the first input is the number of inputs that you will test.
Input 1: 29/02/2000
Input 2: 01/03/2001
Output: 1 0 1
Input 1: 29/02/2000
Input 2: 28/02/2001
Output: 1 0 0
Input 1: 29/12/2012
Input 2: 13/01/2013
Output: 0 0 15
Input 1: 27/05/2012
Input 2: 27/05/2013
Output: 1 0 0
Input 1: 01/01/2012
Input 2: 05/01/2013
Output: 1 0 4
Input 1: 13/05/1966
Input 2: 05/02/2015
Output: 48 8 23
Input 1: 29/02/2003
Input 2: 4/05/2012
Output: data invalida
Input 1: 14/13/1995
Input 2: 7/8/1996
Output: data invalida
The Code:
#include <iostream>
#include <cstdio>
using namespace std;
int verificar(int ano)
{
if (((ano % 4 == 0) && (ano % 100 != 0)) || (ano % 400 == 0))
return 1;
else
return 0;
}
int checkdia(int dia, int mes, int ano){
if (dia>0)
if (((mes==1)||(mes==3)||(mes==5)||(mes==7)||(mes==8)||(mes==10)||(mes==12)) && (dia<=31))
return 1;
else{
if (((mes==4)||(mes==6)||(mes==9)||(mes==11)) && (dia<=30))
return 1;
else{
if ((mes==2) && (dia<=28))
return 1;
else{
if ((((verificar(ano))==true)&&(dia<=29))&&(mes==2))
return 1;
else
return 0;
}
}
}
else
return 0;
}
int checkmes(int mes)
{
if ((mes>0) && (mes<=12))
return 1;
else
return 0;
}
int checkano(int ano)
{
if ((ano>0) && (ano<11000))
return 1;
else
return 0;
}
int main(){
int numerodetestes, mes1, mes2, dia1, dia2, ano1, ano2, teste11, teste12, teste13, teste21, teste22, teste23;
cin>>numerodetestes;
for(int c=0;c<=numerodetestes;c++){
scanf("%d/%d/%d", &dia1, &mes1, &ano1);
scanf("%d/%d/%d", &dia2, &mes2, &ano2);
teste11=checkano(ano1);
teste12=checkdia(dia1,mes1,ano1);
teste13=checkmes(mes1);
teste21=checkano(ano2);
teste22=checkdia(dia2,mes2,ano2);
teste23=checkmes(mes2);
if ((dia1==29)&&(mes1==02))
dia1=28;
if ((teste11+teste12+teste13+teste21+teste22+teste23)==6){
total=((365*(ano2-ano1))+sexto);
//... incomplete part ...//
}
else
cout<<"data invalida"<<endl;
}
return 0;
}
Glossary:
dia: day
mes: month
ano: year
numerodetestes: number of tests
verificar: function for bissextile
check(...): function to check "X"
teste"XX": int variable that will receive a 0 or 1 of a check function.
THE PROBLEM IS: I cant figure out how to calculate it in an organized way.
You should use bool instead of int for your return values :
bool verificar(int ano)
{
return ((ano % 4 == 0) && (ano % 100 != 0)) || (ano % 400 == 0));
}
Also your check functions could be greatly simplified :
bool checkmes(int mes) {
return ( (mes > 0) && (mes <= 12) );
}
bool checkano(int ano) {
return ( (ano > 0) && (ano < 11000) );
}
bool checkdia(int dia, int mes, int ano) {
if(dia < 1 || dia > 31) return false;
if(mes%2 == 0 && dia >30) return false;
if(mes == 2 && dia >28) return verificar(ano);
return true;
}
Then you could write something like :
bool checkdata(int dia, int mes, int ano) {
return ( checkano(ano) && checkmes(mes) && checkdia(dia, mes, ano) );
}
Which would allow you to write :
if( !checkdata(dia1,mes1,ano1) || !checkdata(dia2,mes2,ano2) ) {
cout<< "data invalida" <<endl;
}
Now for the main problem, you could easily get an estimation of the number of day between two dates, but you can't easily get the real number, because dates are nothing but logical. You would have to take into account all calendar modifications across history.
For an easy estimation, I would first add/subtract the dates offset to the first of January, and then add the year difference :
bool isLeap(int year) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
int monthLengths[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int monthLength(int month, int year) {
int n = monthLengths[month-1];
if(month == 2 && isLeap(year)) n += 1;
return n;
}
int yearLength(int year) {
return isLeap(year) ? 366 : 365;
}
int nDay = 0; /* day counter */
/* subtract data1 offset to 01/01 */
nDay -= dia1;
for(int i = mes1; i > 1; --i) {
nDay -= monthLength(i - 1, ano1);
}
/* add data2 offset to 01/01 */
nDay += dia2;
for(int i = mes2; i > 1; --i) {
nDay += monthLength(i - 1, ano2);
}
/* add year offset */
for(int i = ano2; i > ano1; --i) {
nDay += yearLength(i);
}
cout << "Difference = " << nDay << " days" << endl;