infinite loop while counting dates - c++

I'm trying to solve problem that asks to find how many times 13th day occurs at each weekday in period of 1990+N-1 years.
int weekDay = 1;
int week[] = {0,0,0,0,0,0,0};
N = 20;
for (int year = 1990; year <= 1990+N-1; year++){
for (int month = 1; month <= 12; month++){
int days = numberOfDays(year,month);
for (int day = 1; day <= days; day++){
if (day == 13)
week[weekDay] += 1;
weekDay += 1;
if (weekDay > 7)
weekDay = 1;
}
}
}
Here's my solution, however I get stuck in an infinite loop in year and can't seem to fix it.
EDIT : numberOfDays function.
int numberOfDays(int year, int month)
{
if (month == 2 && leapYear(year))
return 29;
else if (month == 2)
return 28;
if (month == 9 || month == 4 || month == 6 || month == 11)
return 30;
return 31;
}

You are using weekdays in the range 1..7 but your histogram array week[] is indexed 0..6.
One possible solution - change:
week[weekDay] += 1;
to:
week[weekDay - 1] += 1;
Another solution - make week[] one element bigger and don't use element 0, i.e. change:
int week[] = {0,0,0,0,0,0,0};
to:
int week[] = {0,0,0,0,0,0,0,0};
A third possible solution - use week days in the range 0..6, i.e. change:
int weekDay = 1;
to:
int weekDay = 0;
and change:
if (weekDay > 7)
weekDay = 1;
to:
if (weekDay > 6)
weekDay = 0;

Off-by-one. Your week[] array has 7 elements, indexed 0..6. You write to week[7], which overwrites something you didn't intend, such as e.g. the year variable.

Related

Extend from 3 hour slot to N days

I want to set up params.arrival_rate every 3 hours of sim_time. This comprises a day but I would like to extend to N days. So, each time slot of 3 hours (in the code below is in minutes) of this N day, params.arrival_rate takes a value. Any optimal function to do so?
My actual code looks like this:
if(sim_time >= 0 && sim_time <= 180) //00:00 - 03:00
{
params.arrival_rate = 10;
}
else if(sim_time > 180 && sim_time <= 360) //03:00-06:00
{
params.arrival_rate = 9;
}
else if(sim_time > 360 && sim_time <= 540) //06:00-09:00
{
params.arrival_rate = 10.5;
}
else if(sim_time > 540 && sim_time <= 720) //09:00-12:00
{
params.arrival_rate = 12;
}
else if(sim_time > 720 && sim_time <= 900) //12:00-15:00
{
params.arrival_rate = 11.5;
}
else if(sim_time > 900 && sim_time <= 1080) //15:00-18:00
{
params.arrival_rate = 11;
}
else if(sim_time > 1080 && sim_time <= 1260) //18:00-21:00
{
params.arrival_rate = 10.5;
}
else if(sim_time > 1260 && sim_time <= 1440) //21:00-24:00
{
params.arrival_rate = 9;
}
else //by default
{
params.arrival_rate = 9;
}
Many thanks.
Assuming you want the same pattern every day, it suffices to take the time modulo 1440 minutes:
int day_time = sim_time % 1440;
int day_no = sim_time / 1440;
Now you can use day_time to get the time in the current day and use that to calculate params.arrival_rate. day_no will contain the day number (starting from 0).
As a further enhancement, consider using an array for your arrival rates instead of a long if-elseif chain:
const double arrival_rates[] = { 10, 9, 10.5, 12, 11.5, 11, 10.5, 9 };
params.arrival_rate = arrival_rates[day_time / (3 * 60)];
The calculation inside the brackets will round down the day_time to the start of the nearest three-hour block.

Deduce the accurate month by the number of the days

I've got a function that extracts the month from a given number of days( days > 0 && days < 366):
int findMonth(int days)
{
int i, months[] = {31,28,31,30,31,30,31,31,30,31,30,31};
for (i = 0; i < 12 && days > 0;i++)
days -= months[i];
return i;
}
Is there any more rational way to deduce it?(I am ignoring the leap year)
If you are trying to make it shorter I think you can't. If you just want something different and maybe more close to C++, you can try this:
int findMonth(int days) {
int i = 0, months[] = {31,28,31,30,31,30,31,31,30,31,30,31};
return std::count_if(std::begin(months), std::end(months), [&i, &days](int x) { return (i += x) - x <= days; });
}
or using std::vector:
int findMonth(int days) {
int i = 0;
std::vector<int> months = {31,28,31,30,31,30,31,31,30,31,30,31};
return std::count_if(months.begin(), months.end(), [&i, &days](int x) { return (i += x) - x <= days; });
}

Number of Mondays, Tuesdays, etc.. in a given month in C++

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++;
}
}

c++ bad access error on find()

I am getting a bad access error while trying to find days between two dates given as a string. I found that the maximum number of days that my function will find is 1884 but I don't know why. The bad access error is in the a.find("/") function call.
Here is the code. Any help would be much appreciated, thanks.
int daysBetweenDates(string a, string b) {
if (a == b) {
return 0;
}
cout << a << endl;
int month = stoi(a.substr(0, a.find("/")));
a = a.substr(a.find("/")+1);
int day = stoi(a.substr(0, a.find("/")));
a = a.substr(a.find("/")+1);
int year = stoi(a);
int k = 0; // days in the month;
if (month == 2) {
k = year%4==0 ? 29 : 28;
}
else if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) {
k = 30;
}
else {
k = 31;
}
day++;
if (day > k) {
month++;
day = 1;
}
if (month > 12) {
year++;
month = 1;
}
string new_a = to_string(month) + "/" + to_string(day) + "/" + to_string(year);
return 1 + daysBetweenDates(new_a, b);
}
The recursive calls are eventually causing a stack overflow. Change the code to remove the potentially deeply nested calls. For example, by changing the routine to use a loop. C++ compilers typically do not do tail recursion optimization.

I don't know what to do my calender code [closed]

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.