I'm giving a lecture on basic programming to first-year mathematics students. The programming language is Java (defined by curriculum).
Last week I gave the following task:
Write a program, that reads in the date of birth of the user separated into year, month and day and subsequently calculates the days the user has lived until today.
Do consider leap years.
This task seems not to be too hard, but there are some restrictions (as they are first-year students and never had had any experiences in programming):
- only the basic data types are known (
int
,double
,boolean
,String
etc.) - arrays are not known
- writing own functions is not known (i.e. everything is within the
main
) - except of
System.out.print
/ln
none of the Java API functions are known - user input is realised through a provided method
readInteger(String promt)
(the students just use it, but don't know why and how it works)
Here I present my sample solution and would like to know, whether there are some more possibilities of "smoothing" the code, optimising it or just increasing the readability. Only tweaks and tricks are allowed, which can be done given the knowledge-restrictions above.
public static void main(String[] args) {
// define today's day
final int TODAY_YEAR = 2011, TODAY_MONTH = 4, TODAY_DAY = 29;
// define a leapyear in the past
final int LEAPYEAR = 1904;
// is the current year a leapyear?
boolean todayIsLeapyear = false;
// get user input
int birthYear = readInteger("Please enter the year of your birth:");
int birthMonth = readInteger("Please enter the month of your birth:");
int birthDay = readInteger("Please enter the day of your birth:");
// check input for validity
boolean inputOK = true;
int birthYearLeapShift = 0;
boolean birthYearWasLeap = false;
if (birthYear > 2011 || birthMonth > 12) {
System.out.println("Your input was not correct.");
if (birthYear > 2011) {
System.out.println("You are from the future! How is it there?");
} else {
System.out.println("We will calculate in the usual gregorian calendar.");
}
inputOK = false;
} else {
// calculate shift of year of birth to the prior leapyear
birthYearLeapShift = (birthYear - LEAPYEAR) % 4;
birthYearWasLeap = (birthYearLeapShift == 0);
// check the input of the month of birth for validity
switch (birthMonth) {
case 1: //january
inputOK = (birthDay <= 31);
break;
case 2: //february
inputOK = (birthDay <= 28);
inputOK = (birthDay <= 29 && birthYearWasLeap);
break;
case 3: //march
inputOK = (birthDay <= 31);
break;
case 4: //april
inputOK = (birthDay <= 30);
break;
case 5: //may
inputOK = (birthDay <= 31);
break;
case 6: //june
inputOK = (birthDay <= 30);
break;
case 7: //july
inputOK = (birthDay <= 31);
break;
case 8: //august
inputOK = (birthDay <= 31);
break;
case 9: //september
inputOK = (birthDay <= 30);
break;
case 10: //october
inputOK = (birthDay <= 31);
break;
case 11: //november
inputOK = (birthDay <= 30);
break;
case 12: //december
inputOK = (birthDay <= 31);
break;
}
}
if (inputOK) {
// calculate the days fo the current year
int daysInCurrYear = TODAY_DAY;
switch (TODAY_MONTH - 1) {
case 11:
daysInCurrYear += 30;
case 10:
daysInCurrYear += 31;
case 9:
daysInCurrYear += 30;
case 8:
daysInCurrYear += 31;
case 7:
daysInCurrYear += 31;
case 6:
daysInCurrYear += 30;
case 5:
daysInCurrYear += 31;
case 4:
daysInCurrYear += 30;
case 3:
daysInCurrYear += 31;
case 2:
daysInCurrYear += todayIsLeapyear ? 29 : 28;
case 1:
daysInCurrYear += 31;
}
// calculate the lived (full) days in the year of birth
int daysInBirthYear = 0;
switch (birthMonth) {
case 1:
daysInBirthYear += 31 - birthDay;
case 2:
if (birthYearWasLeap) {
daysInBirthYear += (birthMonth == 2) ? (29 - birthDay) : 29;
} else {
daysInBirthYear += (birthMonth == 2) ? (28 - birthDay) : 28;
}
case 3:
daysInBirthYear += (birthMonth == 3) ? (31 - birthDay) : 31;
case 4:
daysInBirthYear += (birthMonth == 4) ? (30 - birthDay) : 30;
case 5:
daysInBirthYear += (birthMonth == 5) ? (31 - birthDay) : 31;
case 6:
daysInBirthYear += (birthMonth == 6) ? (30 - birthDay) : 30;
case 7:
daysInBirthYear += (birthMonth == 7) ? (31 - birthDay) : 31;
case 8:
daysInBirthYear += (birthMonth == 8) ? (31 - birthDay) : 31;
case 9:
daysInBirthYear += (birthMonth == 9) ? (30 - birthDay) : 30;
case 10:
daysInBirthYear += (birthMonth == 10) ? (31 - birthDay) : 31;
case 11:
daysInBirthYear += (birthMonth == 11) ? (30 - birthDay) : 30;
case 12:
daysInBirthYear += (birthMonth == 12) ? (31 - birthDay) : 31;
}
// calculate the full lived years since birth
int fullYearsSinceBirth = TODAY_YEAR - birthYear - 1;
// ... and considere the leapyears lived
int leapyearsLived = (fullYearsSinceBirth + birthYearLeapShift) / 4;
// and calculate the lived days in the lived full years
int daysInFullYears = fullYearsSinceBirth * 365 + leapyearsLived;
// add everything together
int daysLived = daysInBirthYear + daysInFullYears + daysInCurrYear;
// and finally return the result
System.out.println("You have been living for " + daysLived
+ " days now.");
System.out.println("In addition, this is approximately "
+ (daysLived / 30) + " full months and "
+ fullYearsSinceBirth + " full years.");
System.out.println("Congratulations!");
}
}