Offset for a calendar program - c++

This program takes any user input year since 1753 and month and creates a calendar for it. However I'm having issues with the offset which is the day the month starts out on. As far as I can tell it is just the offset that is off and everything else seems to work great.
Here is my code.
#include <iostream>
#include <iomanip>
using namespace std;
int getMonth(int month);
int getYear(int year);
int computeOffset(int year, int month);
int numDaysYear(int year);
int numDaysMonth(int year, int month);
bool isLeapYear(int year);
void display(int year, int month, int offset);
/**********************************************************************
* This function will call all the functions necessary to make a calendar
* for any given month and year.
***********************************************************************/
int main()
{
int numDays;
int offset;
int month;
int year;
month = getMonth(month);
year = getYear(year);
offset = computeOffset(year, month);
display(year, month, offset);
return 0;
}
/***********************************************************************
* Gets the month number.
**********************************************************************/
int getMonth(int month)
{
cout << "Enter a month number: ";
cin >> month;
while ( month < 1 || month > 12)
{
cout << "Month must be between 1 and 12.\n"
<< "Enter a month number: ";
cin >> month;
}
return month;
}
/***********************************************************************
* Gets the year.
**********************************************************************/
int getYear(int year)
{
cout << "Enter year: ";
cin >> year;
while ( year < 1753)
{
cout << "Year must be 1753 or later.\n"
<< "Enter year: ";
cin >> year;
}
return year;
}
/***********************************************************************
* Computes the offset.
**********************************************************************/
int computeOffset(int year, int month)
{
int offset = 0;
int count = year - 1753;
for ( int iYear = 0; iYear < count; iYear++)
{
offset = ( offset + 365 + isLeapYear(year)) % 7;
}
for ( int iMonth = 1; iMonth < month; iMonth++)
{
offset = ( offset + numDaysMonth(year, iMonth)) % 7;
}
return offset;
}
/***********************************************************************
* Computes the number of days in the given year.
**********************************************************************/
int numDaysYear(int year)
{
int daysYear = 365 + isLeapYear(year);
return daysYear;
}
/***********************************************************************
* Calculates the number of days in the given month.
**********************************************************************/
int numDaysMonth(int year, int month)
{
int daysMonth;
if ( month == 1)
daysMonth = 31;
else if ( month == 2)
{
if (isLeapYear(year) == true)
daysMonth = 29;
else
daysMonth = 28;
}
else if ( month == 3)
daysMonth = 31;
else if ( month == 4)
daysMonth = 30;
else if ( month == 5)
daysMonth = 31;
else if ( month == 6)
daysMonth = 30;
else if ( month == 7)
daysMonth = 31;
else if ( month == 8)
daysMonth = 31;
else if ( month == 9)
daysMonth = 30;
else if ( month == 10)
daysMonth = 31;
else if ( month == 11)
daysMonth = 30;
else if ( month == 12)
daysMonth = 31;
return daysMonth;
}
/***********************************************************************
* Determines if given year is a leap year.
**********************************************************************/
bool isLeapYear(int year)
{
if ( year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
return true;
else
return false;
}
/**********************************************************************
* Displays the calender table.
**********************************************************************/
void display(int year, int month, int offset)
{
int dayOfWeek;
int day;
cout << endl;
if ( month == 1)
cout << "January";
else if ( month == 2)
cout << "February";
else if ( month == 3)
cout << "March";
else if ( month == 4)
cout << "April";
else if ( month == 5)
cout << "May";
else if ( month == 6)
cout << "June";
else if ( month == 7)
cout << "July";
else if ( month == 8)
cout << "August";
else if ( month == 9)
cout << "September";
else if ( month == 10)
cout << "October";
else if ( month == 11)
cout << "November";
else if ( month == 12)
cout << "December";
cout << ", " << year << "\n";
// Display month header
cout << " Su Mo Tu We Th Fr Sa\n";
// Gets the correct offset width and end the line on the right
//day of the week
if (offset == 0)
{
day = 2;
cout << setw(6);
}
else if (offset == 1)
{
day = 3;
cout << setw(10);
}
else if (offset == 2)
{
day = 4;
cout << setw(14);
}
else if (offset == 3)
{
day = 5;
cout << setw(18);
}
else if (offset == 4)
{
day = 6;
cout << setw(22);
}
else if (offset == 5)
{
day = 7;
cout << setw(26);
}
else if (offset == 6)
{
day = 1;
cout << setw(2);
}
else
cout << "Error offset must be >= 0 and <=6\n";
// The loop for displaying the days and ending the line in the right place
for ( dayOfWeek = 1; dayOfWeek <= numDaysMonth(year, month); dayOfWeek++ )
{
cout << " " << setw(2) << dayOfWeek;
++day;
if (day == 8)
{
cout << "\n";
day = 1;
}
}
if ( day >= 2 && day <= 7)
cout << "\n";
return;
}`

New answer for old question. Rationale for new answer: Better tools and technology in this area.
This answer is heavily using this free, open-source header-only library. I'm going to present this answer starting at the highest level, and drilling down to the lower level details. But at all levels at no time do we have to get into detailed calendrical computations. "date.h" handles that for us.
Here's main:
#include "date.h"
#include <iomanip>
#include <ostream>
#include <string>
#include <iostream>
int
main()
{
print_calendar_year(std::cout);
}
This just output for me:
January 2016
S M T W T F S
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
February 2016
S M T W T F S
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
March 2016
S M T W T F S
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
April 2016
S M T W T F S
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
May 2016
S M T W T F S
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
June 2016
S M T W T F S
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
July 2016
S M T W T F S
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
August 2016
S M T W T F S
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
September 2016
S M T W T F S
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
October 2016
S M T W T F S
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
November 2016
S M T W T F S
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
December 2016
S M T W T F S
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
One could print out next year's calendar with:
using namespace date::literals;
print_calendar_year(std::cout, 2017_y);
I'll start out with the statement:
This is a type-safe system.
The literal 2017_y is an object of type date::year, not a simple integer. Having types that mean year and month means it is far less likely to mix up these concepts. Mistakes tend to be caught at compile time.
print_calendar_year is pretty simple:
void
print_calendar_year(std::ostream& os, date::year y = current_year())
{
using namespace date;
for (auto ym = y/jan; ym < y/jan + years{1}; ym += months{1})
{
print_calendar_month(os, ym);
os << '\n';
}
}
The expression year/month creates a type called date::year_month which is nothing more than a simple struct {year, month}. So this function simply sets up a loop to iterate from Jan of the year y, to the next Jan, excluding the next Jan. It is all quite readable. And note that "bare ints" are not allowed. Everything has a non-integral type.
print_calendar_month is where the rubber meets the road:
void
print_calendar_month(std::ostream& os, date::year_month ym = current_year_month())
{
using namespace std;
using namespace date;
os << format("%B %Y\n", sys_days{ym/1});
os << " S M T W T F S\n";
auto wd = unsigned{weekday{ym/1}};
os << string(wd*3, ' ');
auto const e = (ym/last).day();
for (day d = 1_d; d <= e; wd = 0)
{
for (; wd < 7 && d <= e; ++wd, ++d)
os << setw(3) << unsigned{d};
os << '\n';
}
}
os << format("%B %Y\n", sys_days{ym/1}); is what prints out the title for each month (e.g. January 2016). These are strftime-like formatting flags that will respect the localization settings of the current global std::locale (as much as the OS supports).
The subexpression ym/1 creates a type date::year_month_day which stands for the first day of the indicated month and year. date::year_month_day is a simply class holding {year, month, day}.
sys_days is a chrono::time_point based on system_clock with a precision of days. date::format can take any precision system_clock time_point and format it using strftime-like formatting flags. A year_month_day can be converted to a sys_days as shown. This is a conversion from a {year, month, day} field type to a serial {count of days} type.
os << " S M T W T F S\n"; obviously prints out the day-of-the-week header for the calendar.
auto wd = unsigned{weekday{ym/1}}; finds the day of the week of the first day of the month and converts that weekday into an unsigned using the encoding [Sun == 0, Sat == 6]. [Note: gcc requires the syntax unsigned(weekday{ym/1}). It doesn't like the {} for unsigned. — end note]
os << string(wd*3, ' '); just prints out 3 spaces for each day before the first day of the month to pad out the first row.
auto const e = (ym/last).day(); is a constant of type date::day that is equal to the last day of the month for this year and month combination.
for (day d = 1_d; d <= e; wd = 0)
Starting with day 1 loop until the last day of the month (inclusive) and set the unsigned wd back to the encoding for Sunday on each iteration.
for (; wd < 7 && d <= e; ++wd, ++d): Until you reach the end of the week or the end of the month, increment both day of the week and day of the month.
os << setw(3) << unsigned{d};: Convert the day of the month to an unsigned and print it out right-aligned in a width a of 3 spaces.
os << '\n'; return after printing the week.
And that's the bulk of the program! Almost all of the tricky calendrical logic is encapsulated within these two lines of code:
auto wd = unsigned{weekday{ym/1}};
auto const e = (ym/last).day();
For completeness here are the functions to get the current date::year and the current date::year_month:
date::year_month
current_year_month()
{
using namespace std::chrono;
using namespace date;
year_month_day ymd = floor<days>(system_clock::now());
return ymd.year()/ymd.month();
}
date::year
current_year()
{
using namespace std::chrono;
using namespace date;
year_month_day ymd = floor<days>(system_clock::now());
return ymd.year();
}
Both of these simply truncate a system_clock::time_point returned from system_clock::now() to a precision of days using floor, and then convert that days-precision time_point to a date::year_month_day type. This type then has getters for year and month to pick out the desired partial calendar types.
Update
Well, TemplateRex asked a question below that I didn't want to answer at first, and then I couldn't help myself because the answer highlights how powerful "date.h" is to work with. ;-)
The question is:
Can you print out the calendars in a 3x4 format like this?
January 2016 February 2016 March 2016
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 1 2 3 4 5 6 1 2 3 4 5
3 4 5 6 7 8 9 7 8 9 10 11 12 13 6 7 8 9 10 11 12
10 11 12 13 14 15 16 14 15 16 17 18 19 20 13 14 15 16 17 18 19
17 18 19 20 21 22 23 21 22 23 24 25 26 27 20 21 22 23 24 25 26
24 25 26 27 28 29 30 28 29 27 28 29 30 31
31
April 2016 May 2016 June 2016
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 1 2 3 4 5 6 7 1 2 3 4
3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11
10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18
17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25
24 25 26 27 28 29 30 29 30 31 26 27 28 29 30
July 2016 August 2016 September 2016
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 1 2 3 4 5 6 1 2 3
3 4 5 6 7 8 9 7 8 9 10 11 12 13 4 5 6 7 8 9 10
10 11 12 13 14 15 16 14 15 16 17 18 19 20 11 12 13 14 15 16 17
17 18 19 20 21 22 23 21 22 23 24 25 26 27 18 19 20 21 22 23 24
24 25 26 27 28 29 30 28 29 30 31 25 26 27 28 29 30
31
October 2016 November 2016 December 2016
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 1 2 3 4 5 1 2 3
2 3 4 5 6 7 8 6 7 8 9 10 11 12 4 5 6 7 8 9 10
9 10 11 12 13 14 15 13 14 15 16 17 18 19 11 12 13 14 15 16 17
16 17 18 19 20 21 22 20 21 22 23 24 25 26 18 19 20 21 22 23 24
23 24 25 26 27 28 29 27 28 29 30 25 26 27 28 29 30 31
30 31
Evidently so, because I wasn't about to type in all that above manually! ;-)
It requires a rewrite of print_calendar_year and the introduction of a a couple of new functions, most notably:
void
print_line_of_calendar_month(std::ostream& os, date::year_month ym, unsigned line,
date::weekday firstdow);
This function prints just one line of the calendar associated with the year_month ym and is the heart of this 3x4 format.
I also thought it would be fun to make this program localizable so that the desired first-day-of-week could be printed out, as well as localized names for the month and day-of-week (as much as the std::locale on your platform allows).
The lines are numbered [0, infinity]. Line 0 prints out the month year such as January 2016. Line 1 prints out the day-of-week headers: Su Mo Tu We Th Fr Sa. And then lines [2, infinity] print out the days of the month.
Why infinity?
Because different months take different number of lines, so I wanted to be able to tell a year/month to print a next line even if it didn't need to (because another month in the quarter needed it). So when you ask for a calendar to print out a line that it doesn't need, it just outputs the proper number of ' ' for padding purposes.
Enough intro, here's the function:
void
print_line_of_calendar_month(std::ostream& os, date::year_month ym, unsigned line,
date::weekday firstdow)
{
using namespace std;
using namespace date;
switch (line)
{
case 0:
os << left << setw(21) << format(os.getloc(), " %B %Y", sys_days{ym/1}) << right;
break;
case 1:
{
auto sd = sys_days{ym/firstdow[1]};
for (auto const esd = sd + weeks{1}; sd < esd; sd += days{1})
{
auto d = format(os.getloc(), "%a", sd);
d.resize(2);
os << ' ' << d;
}
break;
}
case 2:
{
auto wd = weekday{ym/1}; // This line and the next are the "offset"
os << string((wd-firstdow).count()*3, ' '); // referred to in the question.
auto d = 1_d;
do
{
os << setw(3) << unsigned(d);
++d;
} while (++wd != firstdow);
break;
}
default:
{
unsigned index = line - 2;
auto sd = sys_days{ym/1};
if (weekday{sd} == firstdow)
++index;
auto ymdw = ym/firstdow[index];
if (ymdw.ok())
{
auto d = year_month_day{ymdw}.day();
auto const e = (ym/last).day();
auto wd = firstdow;
do
{
os << setw(3) << unsigned(d);
} while (++wd != firstdow && ++d <= e);
os << string((firstdow-wd).count()*3, ' ');
}
else
os << string(21, ' ');
break;
}
}
}
So switch on line number [0, infinity], and for each line number, do the right thing:
0. Print out the Month Year heading.
This passes to format the locale of the os to get the localized month name.
1. Print out the day-of-the-week heading.
This passes to format the locale of the os to get the localized weekday names, and prints the first 2 characters. This is (unfortunately) only approximately correct when these are multi-byte characters, but this post is mostly about calendars, not Unicode.
2. Print out the first week, which might be prefixed with spaces. The number of spaces to prefix with is 3*(number of days the first of the month is past the first day of the week). Then append days until you reach the last day of the week. Note that weekday subtraction is always modulo 7 so you don't have to worry about the underlying encoding of the days of the weeks. The weekdays form a circular range. This does require something along the lines of this do-while as opposed to a traditional for when looping over all the days in a week.
3 - infinity. Ah, here's the fun part.
There's a type in "date.h" called year_month_weekday which is a type storing {year, month, weekday, unsigned}. This is how you might specify Mother's day: The second Sunday of May: sun[2]/may/2016. This expression creates a struct {2016, 5, 0, 2} (roughly speaking). And so if the switch lands here, then we are looking for the [first, last] Sunday of this month and year, where the exact index is dependent upon line, and whether or not we printed a Sunday out on line 2.
Also key, this library allows any index to be used:
auto ymdw = ym/firstdow[index];
index could be 1, or it could be 57. The above line compiles and is not a run-time error.
But months can't have 57 Sundays (or Mondays or whatever)!
No problem. You can ask if ym/firstdow[index] is a valid date. This is what the next line does:
if (ymdw.ok())
If the date is valid, then you've got work to do. Else you just print out a blank row.
If we've got work to do, then convert the year_month_weekday to a year_month_day so that you can get the day of the month from it (d). And find the last day of the month:
auto const e = (ym/last).day();
Then iterate from the first day of the week to whichever comes first: the end of the month or the last day of the week. Print out the day of the month for each spot. And then if you didn't end on the last day of the week, print spaces to pad out to the last day of the week.
And we're done with print_line_of_calendar_month! Note that newlines were never output on this level. Not even inter-month padding is output on this level. Each calendar is exactly 21 char wide, and can be printed out to an arbitrary number of rows.
Now we need another minor utility: What is the number of rows a calendar month needs before it starts padding with blank rows?
unsigned
number_of_lines_calendar(date::year_month ym, date::weekday firstdow)
{
using namespace date;
return ceil<weeks>((weekday{ym/1} - firstdow) +
((ym/last).day() - day{0})).count() + 2;
}
This is the number of days in the month, plus the number of days from the first day of the week to the first of the month, plus 2 more rows for the day-of-the-week heading and the year-month heading. Fractional weeks at the end are rounded up!
Notes:
The number of days from the first day of the week to the first of the month is simply: (weekday{ym/1} - firstdow).
The number of days in the month is encoded here as ((ym/last).day() - day{0}). Note that day{0} is not a valid day, but can still be useful in the subtraction: day - day gives a result of the chrono::duration days. Another way to say this would have been ((ym/last).day() - day{1} + days{1}).
Note that ceil<weeks> is used here to convert the number of days to number of weeks, rounding up to the next weeks if the conversion is not exact. 1 week == 1 row. This roundup accounts for the last week that ends prior to the last day of the week.
Now print_calendar_year can be rewritten in terms of these primitives:
void
print_calendar_year(std::ostream& os, unsigned const cols = 3,
date::year const y = current_year(),
date::weekday const firstdow = date::sun)
{
using namespace date;
if (cols == 0 || 12 % cols != 0)
throw std::runtime_error("The number of columns " + std::to_string(cols)
+ " must be one of [1, 2, 3, 4, 6, 12]");
// Compute number of lines needed for each calendar month
unsigned ml[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
for (auto& m : ml)
m = number_of_lines_calendar(y/month{m}, firstdow);
for (auto r = 0u; r < 12/cols; ++r) // for each row
{
const auto lines = *std::max_element(std::begin(ml) + (r*cols),
std::begin(ml) + ((r+1)*cols));
for (auto l = 0u; l < lines; ++l) // for each line
{
for (auto c = 0u; c < cols; ++c) // for each column
{
if (c != 0)
os << " ";
print_line_of_calendar_month(os, y/month{r*cols + c+1}, l, firstdow);
}
os << '\n';
}
os << '\n';
}
}
First compute for each month how many lines it needs:
// Compute number of lines needed for each calendar month
unsigned ml[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
for (auto& m : ml)
m = number_of_lines_calendar(y/month{m}, firstdow);
Then for each "calendar row", find the number of lines needed for that row by searching the proper subset of ml.
And then for each line, and for each "calendar column", print out the line of the corresponding calendar month for that column.
After each line print a '\n'.
After each calendar row, print a '\n'.
Note that still at no time did we need to sink down into calendrical arithmetic. At this level we needed to know "7 days per week", "3 spaces per day" and "12/cols months per calendar row".
On macOS this driver:
using namespace date::literals;
std::cout.imbue(std::locale("de_DE"));
print_calendar_year(std::cout, 3, 2016_y, mon);
Outputs:
Januar 2016 Februar 2016 März 2016
Mo Di Mi Do Fr Sa So Mo Di Mi Do Fr Sa So Mo Di Mi Do Fr Sa So
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6
4 5 6 7 8 9 10 8 9 10 11 12 13 14 7 8 9 10 11 12 13
11 12 13 14 15 16 17 15 16 17 18 19 20 21 14 15 16 17 18 19 20
18 19 20 21 22 23 24 22 23 24 25 26 27 28 21 22 23 24 25 26 27
25 26 27 28 29 30 31 29 28 29 30 31
April 2016 Mai 2016 Juni 2016
Mo Di Mi Do Fr Sa So Mo Di Mi Do Fr Sa So Mo Di Mi Do Fr Sa So
1 2 3 1 1 2 3 4 5
4 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12
11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19
18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26
25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 30
30 31
Juli 2016 August 2016 September 2016
Mo Di Mi Do Fr Sa So Mo Di Mi Do Fr Sa So Mo Di Mi Do Fr Sa So
1 2 3 1 2 3 4 5 6 7 1 2 3 4
4 5 6 7 8 9 10 8 9 10 11 12 13 14 5 6 7 8 9 10 11
11 12 13 14 15 16 17 15 16 17 18 19 20 21 12 13 14 15 16 17 18
18 19 20 21 22 23 24 22 23 24 25 26 27 28 19 20 21 22 23 24 25
25 26 27 28 29 30 31 29 30 31 26 27 28 29 30
Oktober 2016 November 2016 Dezember 2016
Mo Di Mi Do Fr Sa So Mo Di Mi Do Fr Sa So Mo Di Mi Do Fr Sa So
1 2 1 2 3 4 5 6 1 2 3 4
3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11
10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18
17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25
24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31
31
Your milage may vary on how well your std::lib/OS supports localization. But now you can print your calendar out in columns of months varying among any divisor of 12 ([1, 2, 3, 4, 6, 12]), using any year, using any day of the week as the first day of the week, and using any locale (modulo OS support for locales).
Here's the output for print_calendar_year(std::cout, 4, 2017_y);
January 2017 February 2017 March 2017 April 2017
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 7 1 2 3 4 1 2 3 4 1
8 9 10 11 12 13 14 5 6 7 8 9 10 11 5 6 7 8 9 10 11 2 3 4 5 6 7 8
15 16 17 18 19 20 21 12 13 14 15 16 17 18 12 13 14 15 16 17 18 9 10 11 12 13 14 15
22 23 24 25 26 27 28 19 20 21 22 23 24 25 19 20 21 22 23 24 25 16 17 18 19 20 21 22
29 30 31 26 27 28 26 27 28 29 30 31 23 24 25 26 27 28 29
30
May 2017 June 2017 July 2017 August 2017
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 1 2 3 1 1 2 3 4 5
7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12
14 15 16 17 18 19 20 11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19
21 22 23 24 25 26 27 18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26
28 29 30 31 25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 30 31
30 31
September 2017 October 2017 November 2017 December 2017
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 1 2 3 4 5 6 7 1 2 3 4 1 2
3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11 3 4 5 6 7 8 9
10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18 10 11 12 13 14 15 16
17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25 17 18 19 20 21 22 23
24 25 26 27 28 29 30 29 30 31 26 27 28 29 30 24 25 26 27 28 29 30
31

This code does not address your issue (I could not tell what the issue was) but it may be informative to contrast it with your version.
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int getMonth();
int getYear();
int computeOffset(int year, int month);
int numDaysYear(int year);
int numDaysMonth(int year, int month);
bool isLeapYear(int year);
void display(int year, int month, int offset);
/**********************************************************************
* This function will call all the functions necessary to make a calendar
* for any given month and year.
***********************************************************************/
int main()
{
int offset;
int month;
int year;
month = getMonth();
year = getYear();
offset = computeOffset(year, month);
display(year, month, offset);
return 0;
}
/***********************************************************************
* Gets the month number.
**********************************************************************/
int getMonth()
{
int month = 0;
cout << "Enter a month number: ";
cin >> month;
while (month < 1 || month > 12)
{
cout << "Month must be between 1 and 12.\n"
<< "Enter a month number: ";
cin >> month;
}
return month;
}
/***********************************************************************
* Gets the year.
**********************************************************************/
int getYear()
{
int year = 0;
cout << "Enter year: ";
cin >> year;
while ( year < 1753)
{
cout << "Year must be 1753 or later.\n"
<< "Enter year: ";
cin >> year;
}
return year;
}
/***********************************************************************
* Computes the offset.
**********************************************************************/
int computeOffset(int year, int month)
{
int offset = 0;
int count = year - 1753;
for (int iYear = 0; iYear < count; iYear++)
{
offset = (offset + 365 + isLeapYear(year)) % 7;
}
for (int iMonth = 1; iMonth < month; iMonth++)
{
offset = (offset + numDaysMonth(year, iMonth)) % 7;
}
return offset;
}
/***********************************************************************
* Computes the number of days in the given year.
**********************************************************************/
int numDaysYear(int year)
{
return 365 + isLeapYear(year);
}
/***********************************************************************
* Calculates the number of days in the given month.
**********************************************************************/
int numDaysMonth(int year, int month)
{
std::vector<int> days { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int daysMonth = days[month-1];
if (month == 2 && isLeapYear(year))
{
daysMonth = 29;
}
return daysMonth;
}
/***********************************************************************
* Determines if given year is a leap year.
**********************************************************************/
bool isLeapYear(int year)
{
return (year % 400 == 0) || (year % 100 != 0 && year % 4 == 0);
}
/**********************************************************************
* Displays the calender table.
**********************************************************************/
void display(int year, int month, int offset)
{
int day;
cout << endl;
std::vector<std::string> mth { "January", "February", "March",
"April", "May", "June", "July", "August", "September",
"October", "November", "December" };
cout << mth[month-1];
cout << ", " << year << "\n";
// Display month header
cout << " Su Mo Tu We Th Fr Sa\n";
// Gets the correct offset width and end the line on the right
// day of the week
if (0 <= offset && offset <= 6)
{
day = ((offset + 1) % 7) + 1;
cout << setw((day - 2) * 4 + 6);
}
else
cout << "Error offset must be >= 0 and <=6\n";
// The loop for displaying the days and ending the line in the right place
for (int dayOfWeek = 1; dayOfWeek <= numDaysMonth(year, month); dayOfWeek++ )
{
cout << " " << setw(2) << dayOfWeek;
++day;
if (day == 8)
{
cout << "\n";
day = 1;
}
}
if (day >= 2 && day <= 7)
cout << "\n";
return;
}

I know this was posted over a year ago, but I do have a solution for future visitors. In the computeOffset function in the original post, the function isn't actually counting how many days have passed in all. You need to count how many years have passed, and how many days were in those years, as well as the days in the months after those years, if that makes any sense. Here is the code for my working computeOffset function:
int computeOffset(int month, int year)
{
int numDaysYear = 0;
int yearCounter = 0;
int monthCounter = 0;
int months = 1 // NOT the same at the "month" variable coming in
// This loop counts how many days have passed in the full years up to the given year
for (int iYear = 1753; iYear < year; iYear++)
{
numDaysYear = numDaysYear + 365;
if (isLeapYear(iYear))
yearCounter++;
}
// This loop counts the days in the remaining months after all the years
for (int iMonth = 1; iMonth < month; iMonth++)
{
monthCounter = monthCounter + numDaysMonth(months, year); //MONTHS not month
months++;
}
int offset = (numDaysYear + yearCounter + monthCoutner) % 7;
return offset;
Hopefully this makes sense, sorry if some variables have weird names or if the style isn't what you're used to. Hope this helped!

Related

struct method partly changes the values of it's member array cpp

Some information about the overall project:
I have to find if specific nodes remain connected if i start removing the lowest width edges from a graph. I have a struct solve, which has a member array called connected. In a method of this struct , FindConnections I go over some of the edges, from the Kth till the last and see which nodes are connected. The way I keep track of the connected nodes is to have an array that for each node points to the lowest id node it is connected, with the lowest pointing to itself
for example
if nodes 2 5 6 12 are directly connected
connected[2] =connected[5] =connected[6] =connected[12] = 2
so now if 12 and 23 are connected (and 12 is the lowest connection of 23)
connected [23] = 12 and connected[connected[23]] = 2 so i can reach 2 from 23 with recursion
My problem is that after finishing modifying the connected array inside FindConnections, some of the changes are preserved while other not
Here is the code:
void FindConnections(int index)
{
for (int temp, i = index; i < NumberOfPortals; i++)
{
temp = min(first[i], second[i]); // the nodes which edge i connects
connected[first[i]] = temp;
connected[second[i]] = temp;
}
}
which is called by
void seeAllConnections() // this function is for visualization it will not be included
{
for (int i = NumberOfPortals - 1; i >= 0; --i)
{
printf("Only using %d Portals:\n", NumberOfPortals - i);
FindConnections(i);
seeconnected(); // prints connected array
for (int i = 0; i < NumberOfUniverses; i++) //resets connected array
{
connected[i] = i;
}
}
}
In the two first iterations of the for loop in seeAllConnections, everything is good, the edges that are examined are
first second width(irrelevant for now)
6 7 255
26 2 111
11 7 36
in the beginning everyone is connected with himself
in the first one we get the output
(I am placing ** around the values that are changed and !! around the one that was supposed to change but didn't , just so you can see it better, the program prints just the numbers)
Only using 1 Portals:
connected are:
0 1 2 3 4 5 6 7 8 9 10 *7* 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
and we can see that connected[11] = 7 just like we wanted to
in the second one
Only using 2 Portals:
connected are:
0 1 2 3 4 5 6 7 8 9 10 *7* 12 13 14 15 16 17 18 19 20 21 22 23 24 25 *2* 27 28 29
connected[11] =7 just like before
connected[26] = 2 just like we wanted
in the third one
Only using 3 Portals:
connected are:
0 1 2 3 4 5 6 !7! 8 9 10 *7* 12 13 14 15 16 17 18 19 20 21 22 23 24 25 *2* 27 28 29
connected [7] = 7 , not 6
moreover, when i use gdb, inside the FindConnections loop, connected[7] = 6 like we wanted
(gdb) print first[i]
$10 = 6
(gdb) print second[i]
$11 = 7
(gdb) print connected[first[i]]
$12 = 6
(gdb) print connected[second[i]]
$13 = 6
but when it exits the function and returns to seeAllConnected
connected[7] = 7
What Am I doing wrong? how can the first two changes be preserved form the same function in the same struct in the same loop, while the second one isn't?
Also after every time I call FindConnections I reset the array to it's original values, so the changes couldn't have been preserved from before
Thank you in advance
I found out what was wrong, as it was a reverse iteration connected[7] got overwritten.

sas proc sql join causes ERROR: Expression using equals (=) has components that are of different data types

SAS EG gives these errors:
ERROR: Expression using not equals (^=) has components that are of
different data types.
ERROR: Expression using equals (=) has components that are of
different data types.
for this line:
on I.app_id = v.appl_id
proc contents on both fields are Type= Char, Len = 15, Format =$15.00, Informat=$15.00.
I inherited this project and I'm very new to SAS. Any help greatly appreciated.
The CONTENTS Procedure
Data Set Name TEMP7D.DFS_VER_PANEL Observations 8953153
Alphabetic List of Variables and Attributes
# Variable Type Len Format Informat
1 APPL_ID Char 15 $15.00 $15.00
2 VER_MAKE_NAME Char 36 $36.00 $36.00
3 VER_MODEL_NAME Char 50 $50.00 $50.00
6 cash_down Num 8 13.2 13.2
4 cash_price Num 8 13.2 13.2
15 collat_val Num 8 13.2 13.2
12 dealer_adds Num 8 13.2 13.2
16 gap_fee Num 8
18 gapi_fee Num 8
17 gapw_fee Num 8
9 net_trade_in Num 8 13.2 13.2
8 owing_on_trade Num 8 13.2 13.2
5 rebate Num 8 13.2 13.2
13 sales_tax_fees Num 8 13.2 13.2
19 tot_be_wgap Num 8
10 tot_down_pmt Num 8 13.2 13.2
14 total_amt_financed Num 8 13.2 13.2
7 trade_in Num 8 13.2 13.2
11 unpaid_cash_bal Num 8 13.2 13.2
The CONTENTS Procedure
Data Set Name TEMP7D.INFILE_1 Observations 1852630
Alphabetic List of Variables and Attributes
# Variable Type Len Format Informat
63 AMT_APP_VER_FINANCED Num 8 13.2 13.2
62 AMT_APRV Num 8 13.2 13.2
61 AMT_APRV_FINCD Num 8 13.2 13.2
65 AMT_APRV_PMT Num 8 11.2 11.2
73 AMT_COLLAT Num 8 13.2 13.2
41 AMT_DLR_RESV Num 8
66 AMT_INC_TOT Num 8 15.2 15.2
15 AMT_ORIG_NOTE Num 8
64 AMT_RQSTD Num 8 13.2 13.2
11 AMT_TOT_ANN_INC Num 8
37 AMT_VER_RATE Num 8 9.3 9.3
2 APP_ID Char 15 $15.00 $15.00
14 CDE_ACCT_STAT Char 2 $2.00 $2.00
74 CDE_ACL_NEW_USED Char 1 $1.00 $1.00
75 CDE_ACL_YEAR Num 8 3 3
43 CDE_ADJ_USER_CUR Char 8 $8.00 $8.00
29 CDE_CREDIT_ANALYST Char 6 $6.00 $6.00
54 CDE_DIST_PLAN Num 8
44 CDE_LOCATION Char 6 $6.00 $6.00
69 CDE_NEW_USED_COLL Char 3 $3.00 $3.00
27 CDE_OFFICER_APRV Char 6 $6.00 $6.00
28 CDE_OFFICER_CUR Char 6 $6.00 $6.00
55 CDE_PAYOFF_CHARGEBACK Char 3 $3.00 $3.00
25 CDE_PROD_APRV Char 5 $5.00 $5.00
26 CDE_PROD_RQSTD Char 5 $5.00 $5.00
70 COLL_MAKE Char 100 $100.00 $100.00
71 COLL_MODEL Char 100 $100.00 $100.00
72 COLL_YR Char 4 $4.00 $4.00
110 CRS Num 8
56 CURR_UW Char 30 $30.00 $30.00
9 CUSTOM_SCORE Num 8
87 CompareVar Num 8
45 DEALER_CODE Char 5 $5.00 $5.00
48 DEALER_NAME Char 30 $30.00 $30.00
52 DLRACTIVE Char 1 $1.00 $1.00
51 DLRMSA Char 5 $5.00 $5.00
49 DLRSTATE Char 2 $2.00 $2.00
50 DLRZIP Char 9 $9.00 $9.00
13 DLR_NUM_KEY_1 Char 30 $30.00 $30.00
60 DRAG_REDUCTION Num 8
40 DTE_ENTERED Num 8 DATETIME20. DATETIME20.
5 DTE_ORIG_PROCESS Num 8 DATETIME20. DATETIME20.
1 DW_ACCT_KEY Num 8
93 DlrZipClean Char 5
81 FCTR Num 8
20 FTP_RATE Num 8
102 FicoBand Num 8
19 GLAdjBal Num 8
39 ID_PROMOTIONAL Char 18 $18.00 $18.00
42 IND_DLR_FLAT_FEE Char 1 $1.00 $1.00
21 IND_SOLD Char 1 $1.00 $1.00
12 LTV Num 8
53 MARKET_REP_NAME Char 50 $50.00 $50.00
34 MAXCUSTSCOR Num 8
58 NME_DLR_GROUP Char 50 $50.00 $50.00
32 NUM_ACL_MILEAGE Num 8 7 7
10 NUM_ORIG_TERM Num 8
22 NUM_POOL Char 4 $4.00 $4.00
24 NUM_TERM Num 8 6 6
6 ORIGDATEEOM Num 8 DATETIME20. DATETIME20.
7 ORIG_CR_SCORE Num 8
88 OrigDate Num 8 DATE9.
33 PAYMENT Num 8
59 PAYOFF_PERIOD Num 8
35 PCT_APP_RECOMMEND_RATE Num 8 9.3 9.3
16 PCT_APR_RTE Num 8 13.7 13.7
36 PCT_BANK_BUY_RATE Num 8 9.3 9.3
30 PCT_BUY_DOWN_RATE Num 8 8.3 8.3
31 PCT_DLR_FLAT_FEE_RATE Num 8 8.3 8.3
18 PCT_DLR_RATE Num 8
8 PCT_ORIG_DTI Num 8
17 PCT_RATE Num 8
23 PMT_TO_INCOME Num 8 16.3 16.3
4 PROD_KEY_2 Char 20 $20.00 $20.00
46 REC_RATE Num 8
38 RO_OVERRIDE_CODE Char 2 $2.00 $2.00
3 SRC_SYS_ACCT_KEY Char 20 $20.00 $20.00
68 TFLFlg Num 8
57 TXT_CENTER Char 15 $15.00 $15.00
103 TermBand Num 8
76 VEHICLE_TYPE Char 120 $120.00 $120.00
47 VER_RATE Num 8 9.3 9.3
94 VehYr4 Char 7
89 Vintage Num 8
90 VintageHalf Char 6 $6.00
92 VintageMon Char 7 $7.00
91 VintageQtr Char 6 $6.00
95 amt Num 8 10.2
107 aprround Num 8 10.3
101 back_end_exc Num 8
106 bkround Num 8 10.3
99 cs_exceptions Num 8
85 cust_scr Num 8
105 dlrsplit Num 8 10.3
79 docst_fee Num 8
83 estdrl1 Num 8
67 exception Num 8
80 fchg_fee Num 8
100 hd Char 3
108 ltv_PreBE Num 8 10.2
96 new_used Num 8
104 oac Char 1
86 orig_cr_scoreAdj Num 8
82 pct_bk_rate Num 8
98 price_except Num 8
109 pti_PreBE Num 8 10.2
97 region Num 8
77 segment Char 29
84 term Num 8
78 total_backend_fees Num 8
/* CREATE TABLE TEMP7D.InFile_2 AS*/
SELECT DISTINCT
I.*,
D.pp AS PP_bkround,
D2.pp AS PP_aprround,
PEL.new AS PelNew,
PEL.used AS PelUsed,
ELA.Add_ON AS ElaAddOnHist,
ELA_LTV.Factor AS ELAFactor_LTV,
ELA_OAC.Factor AS ELAFactor_OAC,
ELA_Term.Factor AS ELAFactor_Term,
ELAF.NEW AS ElafNew,
ELAF.USED AS ElafUsed,
ELAL.ADD_ON AS ElalAddOn,
PCS.Points AS CSPoints,
PFICO.Points AS FicoPoints,
PLTV.Points AS LTVPoints,
PPMT.Points AS PMTPoints,
PPTI.Points AS PTIPoints,
COALESCE(FIP.FIP,FIP2.FIP) AS FIP,
COALESCE(FIP.MSA,FIP2.MSA) AS MSA,
ADJ.ELGeoAdj,
CASE
WHEN F.src_sys_acct_key NE ''
THEN 1
ELSE 0
END AS FraudFlg,
CASE
WHEN S.src_sys_acct_key NE ''
THEN 1
ELSE 0
END AS SoldFlg,
CASE
WHEN S2.src_sys_acct_key NE ''
THEN 1
ELSE 0
END AS SecureFlg,
(-1*ND.value) AS Net_Drag_2,
v.ver_make_name,
PD1.Factor AS LTVFactor,
PD2.Factor AS PTIFactor,
PD3.Factor As TermFactor,
EAD.Factor AS EADFactor,
case
when year(datepart(dte_entered)) LT 2013
then coalesce(C.CreditSeg,4)
else coalesce(C.CreditSeg,999)
end AS CreditSeg,
case
when year(datepart(dte_entered)) LT 2013
then coalesce(C.CreditSource,2)
else C.CreditSource
end format CredSrcFmt. As CreditSource
FROM TEMP7D.InFile_1 AS I
/*
The Sandbox.DFSDrag table was updated in Dec. 2018 with new prepayment
rates. APR was no longer part of the criteria so I set this
variable = 9999 to indicate the new prepayment data. FICO and
TERM bands have changed as well. The previous prepayment data
is still stored in this table as well and can be identified
where APR <> 9999.
*/
LEFT JOIN Sandbox.DFSDrag AS D
ON I.New_used = d.New_used
AND I.orig_cr_score BETWEEN D.fico_start AND D.fico_end
AND I.num_term BETWEEN D.term_start AND D.term_end
AND D.apr = 9999
LEFT JOIN Sandbox.DFSDrag AS D2
ON I.New_used = d2.New_used
AND I.orig_cr_score BETWEEN D2.fico_start AND D2.fico_end
AND I.num_term BETWEEN D2.term_start AND D2.term_end
AND D2.apr = 9999
/*These two tables were updated based on changes to the EL model.
The original table was kept (Version = 0).
Factors effective November 2016 (Version 1)
Factors effective September 2017 (Version 2)*/
LEFT JOIN Sandbox.DFS_EL_PEL AS PEL
ON I.dte_entered BETWEEN PEL.el_sm AND PEL.el_em
AND COALESCE(I.orig_cr_score, 0) BETWEEN PEL.fsmin AND PEL.fsmax
AND COALESCE(I.custom_score, COALESCE(I.cust_scr, 0)) BETWEEN PEL.csmin AND PEL.csmax
AND PEL.Version = 2
LEFT JOIN Sandbox.DFS_EL_ELA2 AS ELA
ON I.dte_entered BETWEEN ELA.el_sm AND ELA.el_em
AND ELA.hd = I.hd
AND ELA.oac = I.oac
AND I.num_term BETWEEN ELA.term_min AND ELA.term_max
AND I.ltv BETWEEN ELA.ltv_min AND ELA.ltv_max
AND ELA.new_used = I.new_used
AND ELA.CRS = I.CRS
AND ELA.Version = 2
AND datepart(ELA.EL_EM) NE '31Dec9999'd
LEFT JOIN Sandbox.DFS_EL_ELA3 AS ELA_LTV
ON datepart(I.dte_entered) BETWEEN ELA_LTV.StartDate and ELA_LTV.EndDate
AND I.Cust_Scr BETWEEN ELA_LTV.CustScore_Min and ELA_LTV.CustScor_Max
AND I.num_term BETWEEN ELA_LTV.Term_Min AND ELA_LTV.Term_Max
AND I.LTV BETWEEN ELA_LTV.LTV_Min AND ELA_LTV.LTV_Max
AND I.New_Used = ELA_LTV.New_Used
AND ELA_LTV.Metric EQ 'LTV'
LEFT JOIN Sandbox.DFS_EL_ELA3 AS ELA_OAC
ON datepart(I.dte_entered) BETWEEN ELA_OAC.StartDate and ELA_OAC.EndDate
AND I.New_Used = ELA_OAC.New_Used
AND I.oac = ELA_OAC.oac
AND I.Cust_Scr BETWEEN ELA_OAC.CustScore_Min and ELA_OAC.CustScor_Max
AND I.num_term BETWEEN ELA_OAC.Term_Min AND ELA_OAC.Term_Max
AND I.LTV BETWEEN ELA_OAC.LTV_Min AND ELA_OAC.LTV_Max
AND ELA_OAC.Metric EQ 'OAC'
LEFT JOIN Sandbox.DFS_EL_ELA3 AS ELA_Term
ON datepart(I.dte_entered) BETWEEN ELA_Term.StartDate and ELA_Term.EndDate
AND I.New_Used = ELA_Term.New_Used
AND I.Cust_Scr BETWEEN ELA_Term.CustScore_Min and ELA_Term.CustScor_Max
AND I.num_term BETWEEN ELA_Term.Term_Min AND ELA_Term.Term_Max
AND I.LTV BETWEEN ELA_Term.LTV_Min AND ELA_Term.LTV_Max
AND ELA_Term.Metric EQ 'Term'
LEFT JOIN Sandbox.dfs_el_adj_factor As ELAF
ON I.num_term BETWEEN ELAF.term_min AND ELAF.term_max
AND I.ltv BETWEEN ELAF.ltv_min AND ELAF.ltv_max
LEFT JOIN Sandbox.dfs_el_ltv_adj_mar2016 As ELAL
ON ELAL.new_used = I.new_used
AND I.ltv BETWEEN ELAL.ltv_min AND ELAL.ltv_max
LEFT JOIN Sandbox.DFS_Points PCS
ON PCS.JoinVar = COALESCE(I.custom_score, COALESCE(I.cust_scr, 0))
AND PCS.PointType EQ 'CustomScorePoints'
LEFT JOIN Sandbox.DFS_Points PFICO
ON PFICO.JoinVar = COALESCE(I.orig_cr_score, 0)
AND PFICO.PointType EQ 'FicoPoints'
LEFT JOIN Sandbox.DFS_Points PLTV
ON PLTV.JoinVar = INT(I.ltv)
AND PLTV.PointType EQ 'LTVPoints'
LEFT JOIN Sandbox.DFS_Points PPMT
ON PPMT.JoinVar = FLOOR(I.payment)
AND PPMT.PointType = 'PMTPoints'
LEFT JOIN Sandbox.DFS_Points PPTI
ON INT(PPTI.JoinVar*10)/10 = INT(I.pmt_to_income*10)/10
AND PPTI.PointType = 'PTIPoints'
LEFT JOIN decan1.zipfip_201904 AS FIP
ON I.DlrZipClean = FIP.Zip2
LEFT JOIN (SELECT DISTINCT FIP,MSA
FROM decan1.zipfip_201904) AS FIP2
ON strip(I.DlrMSA) = strip(FIP2.FIP)
LEFT JOIN Sandbox.DFSELGeoAdjust AS ADJ
ON DATEPART(I.dte_entered) BETWEEN ADJ.StartDate AND ADJ.EndDate
AND I.DlrState = ADJ.DlrState
AND COALESCE(FIP.FIP,FIP2.FIP) = ADJ.FIP
LEFT JOIN FraudAccts AS F
ON I.src_sys_acct_key = F.src_sys_acct_key
LEFT JOIN SoldAccts AS S
ON I.src_sys_acct_key = S.src_sys_acct_key
LEFT JOIN SecureAccts AS S2
ON I.src_sys_acct_key = S2.src_sys_acct_key
/*This was added in Dec. 2018 for new drag rates*/
LEFT JOIN Sandbox.NetDragRates_2018Q3 AS ND
ON I.num_term BETWEEN ND.num_term_min AND ND.num_term_max
AND CASE WHEN I.ind_dlr_flat_fee EQ '' THEN 'N' ELSE I.ind_dlr_flat_fee END = ND.ind_dlr_flat_fee
AND CASE WHEN I.ind_dlr_flat_fee IN ('Y','X') THEN 100
WHEN I.ind_dlr_flat_fee EQ 'N' AND I.cde_dist_plan LT 70 THEN 100
ELSE I.cde_dist_plan END = ND.cde_dist_plan
LEFT JOIN Sandbox.DFS_PD AS PD1
ON round(I.ltv_PreBE,0.001) BETWEEN PD1.MetricMin and PD1.MetricMax
AND I.New_Used = PD1.NewUsed
AND datepart(I.dte_entered) BETWEEN PD1.StartDate AND PD1.EndDate
AND PD1.Metric = 'LTV'
LEFT JOIN Sandbox.DFS_PD AS PD2
on round(I.pti_PreBE,0.001) BETWEEN PD2.MetricMin and PD2.MetricMax
and I.New_Used = PD2.NewUsed
and datepart(I.dte_entered) BETWEEN PD2.StartDate AND PD2.EndDate
and PD2.Metric = 'PTI'
LEFT JOIN Sandbox.DFS_PD AS PD3
on I.num_term BETWEEN PD3.MetricMin and PD3.MetricMax
and I.New_Used = PD3.NewUsed
and datepart(I.dte_entered) BETWEEN PD3.StartDate AND PD3.EndDate
and PD3.Metric = 'Term'
left join Sandbox.DFS_EAD AS EAD
on round(I.ltv_PreBE,0.001) BETWEEN EAD.LTVMin and EAD.LTVMax
and round(I.pti_PreBE,0.001) BETWEEN EAD.PTIMin and EAD.PTIMax
and I.num_term BETWEEN EAD.TermMin and EAD.TermMax
and datepart(I.dte_entered) BETWEEN EAD.StartDate AND EAD.EndDate
left join Sandbox.DFS_Credit AS C
on I.app_id = C.id_appl
left join temp7d.dfs_ver_panel as v
on I.app_id = v.appl_id
;
QUIT;
Per #alexey-sigida, if indeed your Proc CONTENTS examination is correct
Check if either one or both tables (or table alias) has both columns
app_id
appl_id
If so, your join criteria would likely need to be changed from:
I.app_id = v.appl_id
to one of these:
I.app_id = v.app_id
I.appl_id = v.appl_id

read string and numbers to vector c++

What can I do when my file s2.txt looks like
ID 1 (string)
22 30 30 4 2 4 5 7 5 3 ......................................(a few lines
of numbers)
ID 2
30 4 2 1 2 ................................. (other lines of numbers)
I want save numbers to vector but it doesn't work:
void readFromFile (){
ifstream file("s2.txt");
if( file.good() == true )
cout << "open" << endl;
else
cout << "denied" << endl;
int m=0;
while(!file.eof()) {
string ID;
int qual;
vector <int> quality;
getline(file,ID);
while (file>>qual) {
quality.push_back(qual);
cout<<quality[m]<<endl;
m++;
}
}
file.close();
}
}
main () {
readFromFile();
}
When I click "Run" only one string of numbers is save to a vector (for ID1).
PS. Reading ID is not important.
You should read each line to a string. Then check for "ID" string. If "ID" string is found at position 0 of a line then read that line as a ID line, if not, read that line as a line of integer numbers.
As suggested in the answer of Linh Dao, I made a respective sample code:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
void readFromFile(std::istream &in)
{
if (!in.good()) {
std::cerr << "ERROR!" << std::endl;
}
std::string buffer;
std::vector<int> quality;
while (std::getline(in, buffer)) {
if (buffer.size() >= 2 && buffer.compare(0, 2, "ID") == 0) {
std::cout << buffer << std::endl;
quality.clear(); // reset quality vector
} else {
// read numbers
std::istringstream in(buffer); int qual;
while (in >> qual) {
quality.push_back(qual);
std::cout << quality.back() << std::endl;
}
}
}
}
int main(void)
{
#if 0 // in OP
{ std::ifstream fIn("s2.txt");
readFromFile(fIn);
} // fIn goes out of scope -> file is closed
#else // instead
readFromFile(std::cin);
#endif // 0
return 0;
}
Input:
ID 1 (string)
22 30 30 4 2 4 5 7 5 3
22 30 30 4 2 4 5 7 5 3
ID 2
30 4 2 1 2
Output:
ID 1 (string)
22
30
30
4
2
4
5
7
5
3
22
30
30
4
2
4
5
7
5
3
ID 2
30
4
2
1
2
Life demo on ideone.
Note:
The input stream is read line by line (into std::string buffer).
The further processing depends on whether the input buffer contents starts with ID.
If not, the buffer is used with std::istringstream to extract int numbers.
If I understood the comment right, the questioner intended to output the whole collected quality vector in each iteration. Hence, I modified the first sample and added an output operator<<() for std::vector<int>:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
// a stream operator for vector<int> ouput
std::ostream& operator<<(std::ostream &out, const std::vector<int> &values)
{
const char *sep = "";
for (int value : values) {
out << sep << value; sep = " ";
}
return out;
}
void readFromFile(std::istream &in)
{
if (!in.good()) {
std::cerr << "ERROR!" << std::endl;
}
std::string buffer;
std::vector<int> quality;
while (std::getline(in, buffer)) {
if (buffer.size() >= 2 && buffer.compare(0, 2, "ID") == 0) {
std::cout << buffer << std::endl;
quality.clear(); // reset quality vector
} else {
// read numbers
std::istringstream in(buffer); int qual;
while (in >> qual) {
quality.push_back(qual);
std::cout << quality << std::endl;
}
}
}
}
int main(void)
{
#if 0 // in OP
{ std::ifstream fIn("s2.txt");
readFromFile(fIn);
} // fIn goes out of scope -> file is closed
#else // instead
readFromFile(std::cin);
#endif // 0
return 0;
}
Input: the same like above
Output:
ID 1 (string)
22
22 30
22 30 30
22 30 30 4
22 30 30 4 2
22 30 30 4 2 4
22 30 30 4 2 4 5
22 30 30 4 2 4 5 7
22 30 30 4 2 4 5 7 5
22 30 30 4 2 4 5 7 5 3
22 30 30 4 2 4 5 7 5 3 22
22 30 30 4 2 4 5 7 5 3 22 30
22 30 30 4 2 4 5 7 5 3 22 30 30
22 30 30 4 2 4 5 7 5 3 22 30 30 4
22 30 30 4 2 4 5 7 5 3 22 30 30 4 2
22 30 30 4 2 4 5 7 5 3 22 30 30 4 2 4
22 30 30 4 2 4 5 7 5 3 22 30 30 4 2 4 5
22 30 30 4 2 4 5 7 5 3 22 30 30 4 2 4 5 7
22 30 30 4 2 4 5 7 5 3 22 30 30 4 2 4 5 7 5
22 30 30 4 2 4 5 7 5 3 22 30 30 4 2 4 5 7 5 3
ID 2
30
30 4
30 4 2
30 4 2 1
30 4 2 1 2
Life demo on ideone.

Comparison of two CSV files in Python

I want to compare two csv files looking like below.
Here I want to find out unmatched signals.
I need some help in python. Please help me.
File 1
2
USER Name
7/31/2015 0:00
<XXXXXXX>
1 Signal_1 10
2 Signal_2 1 2 3 4 5
3 Signal_3 X 5 10 15 20 25 Y 6 11 16 21 26
1 Signal_4 20
1 Signal_5 30
2 Signal_6 6 7 8 9 10 11 12 13
2 Signal_7 55 1.05 1.6 14.1
3 Signal_8 X 30 40 50 60 40 Y 14 15 26 14 26
2 Signal_9 1 1 2 3 2
1 Signal_10 40
File 2
2
USER Name
7/31/2015 0:00
<XXXXXXX>
3 Signal_3 X 20 10 15 17 25 Y 6 11 16 21 26
1 Signal_5 5
2 Signal_7 55 1.05 1.6 14.1
1 Signal_1 10
3 Signal_8 X 30 40 50 60 40 Y 14 15 26 14 26
1 Signal_10 14
2 Signal_9 1 1 2 3 2
2 Signal_6 6 7 8 59 10 15 12 13
1 Signal_4 20
2 Signal_2 1 2 3 4 5
Result:
File
3 Signal_3 X 5 10 15 20 25 Y 6 11 16 21 26
1 Signal_5 30
1 Signal_10 40
2 Signal_6 6 7 8 9 10 11 12 13
File 2
3 Signal_3 X 20 10 15 17 25 Y 6 11 16 21 26
1 Signal_5 5
1 Signal_10 14
2 Signal_9 1 1 2 3 2
If you want to check for fairly exact comparisons, you can use sets quite easily:
def sigset(fname):
with open(fname, 'rb') as f:
data = set(' '.join(line.split()) for line in f
if 'Signal' in line)
return data
s1 = sigset('sig1.txt')
s2 = sigset('sig2.txt')
print('File 1')
for line in sorted(s1 - s2):
print(line)
print('')
print('File 2')
for line in sorted(s2 - s1):
print(line)
with open('Sample1.csv', 'r') as t1, open('Sample2.csv', 'r') as t2:
fileone = t1.readlines()
filetwo = t2.readlines()
print fileone
print filetwo
with open('update.csv', 'w') as outFile:
for line in filetwo:
if line not in fileone:
outFile.write(line)
for line in fileone:
if line not in filetwo:
outFile.write(line)

Pickuping the Common 1d sequence in 1d array's?

How to pick the best uniformed 1d array from the 2d arrays ?
I have two 2d array of : 11 x 10
Example :
4 8 12 12 12 14 16 18 4 1 0
5 7 11 12 13 11 15 18 3 2 1
8 3 12 14 18 19 20 21 8 5 4 ,
8 2 11 12 17 17 19 20 7 4 3 ,
4 7 11 11 11 15 17 19 5 1 1 ,
3 8 11 13 11 15 14 17 4 1 0 ,
4 7 12 13 13 14 16 19 3 1 1 ,
5 9 11 12 13 15 17 19 5 0 1 ,
9 7 25 22 24 18 23 17 3 3 3 ,
4 8 13 13 13 15 17 17 5 2 0 ,
here we have 2d arrays of size 11x10 - Need to analysis and have to find out the common 1d array which has common like.
find the best closing number and its difference- and keep doing for all the corresponding columns in an array .
below answer should be like - finding the corresponding very column and comparing with the next row column - if it has some difference below ( 5 ) take the both column of two rows are same and process for next column of the same row..process untill finding the 1 row where it has at least nearby matches of 5
4 8 11 12 13 13 15 18 4 1 0
why don't you do something like this
int[] count(int[][] array)
int result[11];
for(int x = o; x<= 11;x++)
{
int temp[10];
for(int y = o; y<= 10;y++)
{
temp[y] = array[y][x];
}
result[x] = getHighest(temp);
}
return result;
}
int getHighest(int[] array)
{
int size = array.length;
int[size][1] temp;
for(int x; x<= size;x++)
{
int z = array[x];
temp[z][0]++;
}
int highest = -1;
for(int z; z<= size;z++)
{
int z = array[x];
int h = temp[z][0];
if(h > highest)
{
highest = h;
}
}
return highest;
}
Something like this, but my C++ has gotten a bit of rusty so sorry if there are any mistakes.