I want to subtract months from integer without any library.
The problem is that when I reduce 1 month from first month : 0 (January) it should be 12 (Dec) but it will be -1..
This is my code for adding
int currentMonthInt = Integer.parseInt(currentMonth) - 1;
int currentYearInt = Integer.parseInt(currentYear);
// show today month
if (dateposition == 0){
showListView(currentMonth, currentYear, db);
}
// show next month
for (int i = 1; i <=200; i++){
if (dateposition == i){
int month = currentMonthInt + i;
int year = currentYearInt + (month / 12);
month = (month % 12)+1;
String monthString = String.format("%02d", month);
String yearString = String.valueOf(year);
showListView(monthString, yearString, db);
}
}
and this is my code for subtracting : (but it dosen't work)
for (int i = -200; i < 0; i++){
//This is not correct!
//int month = currentMonthInt + i;
//int year = currentYearInt + (month / 12);
//month = (month % 12)+1;
String monthString = String.format("%02d", month);
String yearString = String.valueOf(year);
showListView(monthString, yearString, db);
}
P.S. dateposition is for position of month if its 0 its today months and year and if its +1 its next month and so on and if its -1 its prev month
OK I wrote it and I test it its worked!
for (int i = -200; i < 0; i++){
if (dateposition == i){
int month = currentMonthInt + i;
int year = currentYearInt + (month / 12);
if (month >= 0){
month = (month % 12)+1;
} else {
int c1 = Math.abs(month / 12) + 1;
month += (12 * c1);
}
String monthString = String.format("%02d", month);
String yearString = String.valueOf(year);
showListView(monthString, yearString, db);
}
}
Using Joda library
public void test() {
LocalDate fromDate = LocalDate.now();
System.out.println(fromDate);
LocalDate newYear = fromDate;
for (int i = 0; i < 10; i++) {
newYear = newYear.minusMonths(1);
System.out.print(newYear + ", ");
}
System.out.println("\n-------");
newYear = fromDate;
for (int i = 0; i < 10; i++) {
newYear = newYear.plusMonths(1);
System.out.print(newYear + ", ");
}
}
Output:
2014-10-20
2014-09-20, 2014-08-20, 2014-07-20, 2014-06-20, 2014-05-20, 2014-04-20, 2014-03-20, 2014-02-20, 2014-01-20, 2013-12-20,
-------
2014-11-20, 2014-12-20, 2015-01-20, 2015-02-20, 2015-03-20, 2015-04-20, 2015-05-20, 2015-06-20, 2015-07-20, 2015-08-20,
Related
This question already has answers here:
Calculating the difference between two Java date instances
(45 answers)
Calculate difference between two dates (number of days)?
(17 answers)
Closed 4 years ago.
Task: It is necessary to calculate the user's age, in days, hours, minutes. Enter a date of birth and today's date.
It seems like, age calculates correctly, but in days there is not the right figure. How to calculate the difference between dates in days?
import java.util.Scanner;
class Solution {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int day;
int year;
int month;
int day2; //today
int year2; //today's year
int month2; //today's month
do {
System.out.print("Enter the year of birth: ");
year = scanner.nextInt();
} while (year < 1000 || year > 2019);
do {
System.out.print("Enter the month of birth: ");
month = scanner.nextInt();
} while (month < 1 || month > 12);
do {
System.out.print("Enter the day of birth: ");
day = scanner.nextInt();
} while (day < 1 || day > 31);
do {
System.out.print("Enter today's year: ");
year2 = scanner.nextInt();
} while (year2 < 1000 || year2 > 2019);
do {
System.out.print("Enter today's month: ");
month2 = scanner.nextInt();
} while (month2 < 1 || month2 > 12);
do {
System.out.print("Enter today: ");
day2 = scanner.nextInt();
} while (day2 < 1 || day2 > 31);
int year_leap;
int[] month_day = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
year_leap = 366;
month_day[1] = 29;
} else {
month_day[1] = 28;
year_leap = 365;
}
int userYear = 0;
int userMonth;
int userDay;
if (year <= year2) {
userYear = year2 - year;
} else System.out.printf("Error!!! %n");
if (month > month2) {
userYear--;
userMonth = month2 + 12 - month;
} else userMonth = month2 - month;
if (day > day2) {
userMonth--;
userDay = day2 + month_day[userMonth] - day;
} else userDay = day2 - day;
int day_year = 0;
int day_month = 0;
int day_age = 0;
while (year < year2 - 1) {
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
year_leap = 366;
month_day[1] = 29;
} else {
year_leap = 365;
month_day[1] = 28;
}
year++;
day_year = day_year + year_leap;
}
day_month = month_day[1] * userMonth + userDay; // 31 days in a month
day_age = day_year + day_month;
System.out.printf("------------------------------------ %n");
System.out.println("Your age: " + userYear + "." + userMonth + "." + userDay);
System.out.println("Your in days:" + day_age);
}
}
Found the necessary algorithm on Python. Tell me how to implement it in Java?
def dateIsBefore(year1, month1, day1, year2, month2, day2):
return (year1, month1, day1) < (year2, month2, day2)
def daysBetweenDates(year1, month1, day1, year2, month2, day2):
assert not dateIsBefore(year2, month2, day2, year1, month1, day1)
days = 0
while dateIsBefore(year1, month1, day1, year2, month2, day2):
days += 1
year1, month1, day1 = nextDay(year1, month1, day1)
return days
Use the API provided by Java:
LocalDate now = LocalDate.now();
LocalDate birthDate = LocalDate.of(1975, 7, 19);
long days = ChronoUnit.DAYS.between(birthDate, now);
System.out.println("days = " + days);
You can calculate
eg:
Date date1 =
Date date2 =
long diff = date2.getTime() - date1.getTime();
System.out.println ("Days: " + TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS));
OR
float days = (diff / (1000*60*60*24));
Your year_leap = 364; for non leap years should be equal to 365 and 366 for leap years.
This line day_month = month_day[1] * userMonth + userDay; is always using 29 as month_day[1] is always referring to February.
Also if it is not mandatory to do the calculations yourself look at the suggested API`s as they give you much better functionality.
I am trying to write a program where the user inputs 2 dates and the program calculates the days in between (without using any of the calendar classes) and prints the results, but I keep getting crazy numbers that make no sense. When I tried to make it calculate 5 days it printed the results of 333 and when I try to do something like 20 years it prints numbers in the millions.
import java.util.Scanner;
public class DaysCalc {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("Please enter starting date (mm-dd-yyyy) ");
String startingdate = input.next();
System.out.print("Please enter ending date (mm-dd-yyyy) ");
String finishingdate = input.next();
String startingdayst = startingdate.substring(3, 5);
String startingmonthst = startingdate.substring(0, 2);
String startingyearst = startingdate.substring(6, 10);
String finishingdayst = finishingdate.substring(3, 5);
String finishingmonthst = finishingdate.substring(0, 2);
String finishingyearst = finishingdate.substring(6, 10);
int startingyear = Integer.parseInt(startingyearst);
int startingday = Integer.parseInt(startingdayst);
int startingmonth = Integer.parseInt(startingmonthst);
int finishingyear = Integer.parseInt(finishingyearst);
int finishingday = Integer.parseInt(finishingdayst);
int finishingmonth = Integer.parseInt(finishingmonthst);
System.out.println(startingyear + "," + startingday + "," + startingmonth );
System.out.println(finishingyear + "," + finishingday + "," + finishingmonth);
int daysLeft = 0;
int daysUntilEnd = 0;
int i = 0;
daysLeft = daysInAMonth(startingmonth, startingyear) - startingday;
daysUntilEnd = finishingday;
for (int monthCount = startingmonth + 1; monthCount <= 12; monthCount++)
{
i += daysInAMonth(monthCount, startingyear);
}
for (int yearCount = startingyear + 1; yearCount <= finishingyear; yearCount++)
{
if (isLeapYear(yearCount))
{
i = i * 366;
}
else
{
i = i * 365;
}
i += daysUntilEnd;
}
System.out.println(i);
}
private static boolean isLeapYear(int year) {
boolean isLeapYear = ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0));
return isLeapYear;
}
private static int daysInAMonth(int month, int year) {
if (month == 2)
{
if (isLeapYear(year) )
{
return 29;
}
else
{
return 28;
}
}
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 9 || month == 11) {
return 31;
}
return 30;
}
}
the problem was with this part
for (int monthCount = startingmonth + 1; monthCount < finishingmonth; monthCount++)
{
i += daysInAMonth(monthCount, startingyear);
}
for (int yearCount = startingyear + 1; yearCount <= finishingyear; yearCount++)
{
if (isLeapYear(yearCount))
{
i = i + 366;
}
else
{
i = i + 365;
}
}
i += daysUntilEnd;
i += daysInAMonth(startingmonth, startingyear)-startingday-1;
System.out.println(i);
it's not completely bug free but i hope it helps you to see where it went wrong. it was kind of an eye mistake
My IncDate Class extends my DaysBetween Class. I am trying to create an increment method within my IncDate class to represent the next day. However I am getting this error right beside where I implement super and I can not find the fix. The error is telling me:
Constructor DaysBetween in class DaysBetween cannot be applied to given types;
required:no arguments
found:int,int,int
reason:actual and formal argument lists differ in length
Why is the error saying that no arguments are required when they are in fact passed within my DaysBetween class. I know extended classes have to pass their own constructors. But that is what I am trying to do with super. So why am I getting the error? My DaysBetween Class works as it supposed to without any errors, but clearly something within it is affecting my IncDate class. So what am overlooking within my DaysBetween Class that is affecting its extended IncDate Class?
DaysBetween Class:
package dateclass1;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.Scanner;
class DateClass {
protected int year;
protected int month;
protected int day;
public static final int MINYEAR = 1583;
// Constructor
public DateClass(int newMonth, int newDay, int newYear)
{
month = newMonth;
day = newDay;
year = newYear;
}
// Observers
public int getYear()
{
return year;
}
public int getMonth()
{
return month;
}
public int getDay()
{
return day;
}
public int lilian()
{
// Returns the Lilian Day Number of this date.
// Precondition: This Date is a valid date after 10/14/1582.
//
// Computes the number of days between 1/1/0 and this date as if no calendar
// reforms took place, then subtracts 578,100 so that October 15, 1582 is day 1.
final int subDays = 578100; // number of calculated days from 1/1/0 to 10/14/1582 November 17, 1858
int numDays;
// Add days in years.
numDays = year * 365;
// Add days in the months.
if (month <= 2)
numDays = numDays + (month - 1) * 31;
else
numDays = numDays + ((month - 1) * 31) - ((4 * (month-1) + 27) / 10);
// Add days in the days.
numDays = numDays + day;
// Take care of leap years.
numDays = numDays + (year / 4) - (year / 100) + (year / 400);
// Handle special case of leap year but not yet leap day.
if (month < 3)
{
if ((year % 4) == 0) numDays = numDays - 1;
if ((year % 100) == 0) numDays = numDays + 1;
if ((year % 400) == 0) numDays = numDays - 1;
}
// Subtract extra days up to 10/14/1582.
numDays = numDays - subDays;
return numDays;
}
#Override
public String toString()
// Returns this date as a String.
{
String monthString = new DateFormatSymbols().getMonths()[month-1];
return(monthString + "/" + day + "/" + year);
}
public class mjd
{
public int mjd()
{
final int subDays = 678941;
int numDays;
numDays = year * 365;
if (month <= 2)
numDays = numDays + (month - 1) * 31;
else
numDays = numDays + ((month -1) * 31) - ((4 * (month-1) + 27)/10);
numDays = numDays + day;
numDays = numDays + (year / 4) - (year / 100) + (year / 400);
if (month < 3)
{
if ((year % 4) == 0) numDays = numDays -1;
if ((year % 100) == 0) numDays = numDays + 1;
if ((year % 400) == 0) numDays -= numDays -1;
}
// Days subtracted up to 10/14/1582
numDays = numDays - subDays;
return numDays;
}
}
public class djd
{
public int djd()
{
final int subDays = 693961; // number of calculated days from 1/1/0 to January 1,1900
int numDays;
// Add days in years.
numDays = year * 365;
// Add days in the months.
if (month <= 2)
numDays = numDays + (month - 1) * 31;
else
numDays = numDays + ((month - 1) * 31) - ((4 * (month-1) + 27) / 10);
// Add days in the days.
numDays = numDays + day;
// Take care of leap years.
numDays = numDays + (year / 4) - (year / 100) + (year / 400);
// Handle special case of leap year but not yet leap day.
if (month < 3)
{
if ((year % 4) == 0) numDays = numDays - 1;
if ((year % 100) == 0) numDays = numDays + 1;
if ((year % 400) == 0) numDays = numDays - 1;
}
// Subtract extra days up to 10/14/1582.
numDays = numDays - subDays;
return numDays;
}
}
}
public class DaysBetween
{
public static void main(String[] args)
{
Scanner conIn = new Scanner(System.in);
int day, month, year;
System.out.println("Enter two 'modern' dates: month day year");
System.out.println("For example, January 12, 1954, would be: 1 12 1954");
System.out.println();
System.out.println("Modern dates occur after " + DateClass.MINYEAR + ".");
System.out.println();
System.out.println("Enter the first date:");
month = conIn.nextInt();
day = conIn.nextInt();
year = conIn.nextInt();
DateClass date1 = new DateClass(month, day, year);
System.out.println("Enter the second date:");
month = conIn.nextInt();
day = conIn.nextInt();
year = conIn.nextInt();
DateClass date2 = new DateClass(month, day, year);
if ((date1.getYear() <= DateClass.MINYEAR)
||
(date2.getYear() <= DateClass.MINYEAR))
System.out.println("You entered a 'pre-modern' date.");
else
{
System.out.println("The number of days between");
System.out.print(date1);
System.out.print(" and ");
System.out.print(date2);
System.out.print(" is ");
System.out.println(Math.abs(date1.lilian() - date2.lilian()));
}
}
}
IncMain Class:
package dateclass1;
import java.util.Calendar;
/**
*
* #author macbookpro
*/
class IncDate extends DaysBetween {
public IncDate(int newMonth, int newDay, int newYear)
{
super(newMonth, newDay, newYear);
}
public void increment()
{
if(month == 1){
if(day>30){
day=1;
month=2;
}
else{
day=day+1;
}
}
else if (month == 2){
if ((year%4 == 0 && year%100 !=0) || year%400 == 0)
{
if(day>28){
day = 1;
month=3;
}
else{
day = day +1;
}
}
else{
if(day > 27){
day = 1;
month = 3;
}
else{
day = day + 1;
}
}
}
else if(month == 3){
if(day > 30){
day=1;
month=4;
}
else{
day = day + 1;
}
}
else if (month == 4){
if(day > 29){
day = 1;
month = 5;
}
else{
day = day + 1;
}
}
else if (month ==5){
if(day>30){
day = 1;
month= 6;
}
else{
day = day +1;
}
}
else if (month==6){
if(day>29){
day = 1;
month=7;
}
else{
day = day + 1;
}
}
else if (month==7){
if (day>30){
day = 1;
month = 8;
}
else{
day = day +1;
}
}
else if (month==8){
if (day>30){
day = 1;
month = 9;
}
else{
day = day + 1;
}
}
else if (month==9){
if (day>29){
day = 1;
month = 10;
}
else{
day = day + 1;
}
}
else if (month==10){
if (day>30){
day = 1;
month = 11;
}
else{
day = day + 1;
}
}
else if (month==11){
if (day>29){
day = 1;
month = 12;
}
else{
day = day + 1;
}
}
else if (month==12){
if (day>30){
day = 1;
month = 1;
year = year+1;
}
else{
day = day + 1;
}
}
}
}
There are a lot of bugs in my program but I feel as though this bug is ground zero. Please help.
DaysBetween has no constructor specified so that means the default constructor with no arguments is used. Because you pass arguments, it reports the error of argument mismatch. DateClass has the constructor with three integers, presumably you're trying to extend that:
public class IncDate extends DateClass {
...
}
Here are also some things to remember:
One public class per file
Constructors have no return type specifiers
Make sure you are extending the correct classes
You can't have public classes inside public classes
Hi guys i really need your help. I need to output a 3 year calendar in 3 columns. In the first column the year should be the year that the user input.
I have a code that will post a 3 year calendar but only in 1 column. I need to separate the other year in another column plss help me
package project;
import java.util.*;
public class les1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Calendar cal = Calendar.getInstance();
String ans;
// getting the system calendar's year, maximum days,
// weeks per month and system calendar's month.
int year = cal.get(Calendar.YEAR);
int day = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
int week = cal.get(Calendar.DAY_OF_WEEK);
int month = cal.get(Calendar.MONTH);
int col[] = new int[3];
do {
// validation for input year
do {
System.out.print("\nEnter year: ");
while (true)
try {
year = Integer.parseInt(in.next());
break;
} catch (Exception ex) {
System.out.println("Try again!");
System.out.print("\nEnter year: ");
}
if (year < 1900 || year > 2099) {
System.out.println("Try again!");
}
} while (year < 1900 || year > 2099);
/*
* System.out.println("enter number of elements");
*
* int n = in.nextInt();
*
* int arr[] = new int[n];
*
* for (int j = 0; j < n; j++) {// for reading array
*
* }
*
* for (int j : arr) {
*/
// loop for months
for (month = 1; month <= 1; month++) {
// calculating years, month, days and weeks.
int y = year - (14 - month) / 12;
int x = y + y / 4 - y / 100 + y / 400;
int m = month + 12 * ((14 - month) / 12) - 2;
int d = (1 + x + (31 * m) / 12) % 7;
// calculate leap year
boolean LeapYear = (year % 400 == 0);
// displaying month as String
cal.set(year, month, 0);
System.out
.print(cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.ENGLISH) + "\t\t\t\t\t\t");
System.out.print("Sun Mon Tue Wed Thu Fri Sat" + "\t\t\t");
int length = (int) (30 + ((month + (month / 8.0)) % 2));
if (month == 2) {
if (LeapYear) {
length -= 1;
} else {
length -= 2;
}
}
for (int a = 0; a < col.length; a++) {
int counter = 1;
// spacing for first day of the month
for (int i = 0; i < d; i++) {
System.out.print(" ");
counter++;
}
// spacing for days
for (day = 1; day <= length; day++) {
System.out.printf("%2d", day);
System.out.print((counter++ % 7 != 0) ? " " : "\n");
}
}
week = (week + length) % 6;
}
year++;
/* } */
System.out.print("\n\n" + "Enter another year (Y/N)? ");
ans = in.next();
} while (ans.equals("Y") || ans.equals("y"));
System.out.println("\nEnd!");
in.close();
}
}
Take a look at the following code. It will print three different years' calendars in three columns. I have used this formula to determine the day of the week in any month.
import java.util.*;
public class les1 {
public static void main(String[] args) {
String[] days = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
Scanner in = new Scanner(System. in );
Calendar cal = Calendar.getInstance();
String ans;
int year = cal.get(Calendar.YEAR);
int day = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
int week = cal.get(Calendar.DAY_OF_WEEK);
int month = cal.get(Calendar.MONTH);
int col[] = new int[3];
do {
// validation for input year
do {
System.out.print("\nEnter year: ");
while (true)
try {
year = Integer.parseInt( in .next());
break;
} catch (Exception ex) {
System.out.println("Try again!");
System.out.print("\nEnter year: ");
}
if (year < 1900 || year > 2099) {
System.out.println("Try again!");
}
} while (year < 1900 || year > 2099);
for (month = 1; month <= 1; month++) {
HashMap < Integer, Integer > map = new HashMap < Integer, Integer > ();
map.put(1, 0);
map.put(7, 6);
map.put(2, 3);
map.put(8, 2);
map.put(3, 3);
map.put(9, 5);
map.put(4, 6);
map.put(10, 0);
map.put(5, 1);
map.put(11, 3);
map.put(6, 4);
map.put(12, 5);
System.out.println();
for (int a = 0; a < col.length; a++) {
int counter = 1;
System.out.printf("%-6s%-6s%-6s%-6s%-6s%-6s%-6s", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
System.out.printf("\t\t\t"); //Formatting for days
}
// System.out.println();
// calculate leap year
boolean LeapYear = false;
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) LeapYear = true;
// displaying month as String
ArrayList < Integer > dds = new ArrayList < Integer > ();
dds.add(0);
dds.add(0);
dds.add(0);
dds.add(0);
int indexofA = 0;
String yy = year + "";
int m;
if (LeapYear && month == 1) m = map.get(month) + 6;
else if (LeapYear && month == 2) m = map.get(month) - 1;
else m = map.get(month);
int y = Integer.parseInt(yy.substring(2, 4));
int c = (year / 100);
if (c % 4 == 0) c = 6;
else if (c % 4 == 1) c = 4;
else if (c % 4 == 2) c = 2;
else c = 0;
int x = y + y / 4 + c;
int d = (1 + x + m) % 7;
// cal.set(year, month, 0);
int length = (int)(30 + ((month + (month / 8.0)) % 2));
if (month == 2) {
if (LeapYear) {
length -= 1;
} else {
length -= 2;
}
}
System.out.print("len : " + length);
System.out.println();
boolean thirtyone = false;
int count = 0;
for (int r = 0; r < 6; r++) { //For each row of the calendars
String[] dayss = new String[7];
int index = 0;
for (int a = 0; a < col.length; a++) { //For each column of a calendar
for (int i = 0; i < d && dds.get(indexofA) == 0; i++) {
dayss[index] = " ";
index++;
}
for (day = dds.get(indexofA) + 1; day <= length; day++) {
if (day == 31) {
dayss[index] = day + "";
index++;
thirtyone = true;
} else if (day < 31) {
dayss[index] = day + "";
index++;
}
if (index == 7) {
dds.set(indexofA, day);
break;
}
}
indexofA++;
System.out.printf("%-6s%-6s%-6s%-6s%-6s%-6s%-6s", dayss[0], dayss[1], dayss[2], dayss[3],
dayss[4], dayss[5], dayss[6]);
System.out.printf("\t\t\t");
index = 0;
year++;
LeapYear = false;
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) LeapYear = true;
yy = year + "";
if (LeapYear && month == 1) m = map.get(month) + 6;
else if (LeapYear && month == 2) m = map.get(month) - 1;
else m = map.get(month);
y = Integer.parseInt(yy.substring(2, 4));
c = (year / 100);
if (c % 4 == 0) c = 6;
else if (c % 4 == 1) c = 4;
else if (c % 4 == 2) c = 2;
else c = 0;
x = y + y / 4 + c;
d = (1 + x + m) % 7;
}
year -= 3;
yy = year + "";
LeapYear = false;
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) LeapYear = true;
if (LeapYear && month == 1) m = map.get(month) + 6;
else if (LeapYear && month == 2) m = map.get(month) - 1;
else m = map.get(month);
y = Integer.parseInt(yy.substring(2, 4));
c = (year / 100);
if (c % 4 == 0) c = 6;
else if (c % 4 == 1) c = 4;
else if (c % 4 == 2) c = 2;
else c = 0;
x = y + y / 4 + c;
d = (1 + x + m) % 7;
indexofA = 0;
System.out.println();
}
}
System.out.print("\n\n" + "Enter another year (Y/N)? ");
ans = in .next();
} while (ans.equals("Y") || ans.equals("y"));
System.out.println("\nEnd!"); in .close();
}
}
I am new to Programming, and to Java, and I'm trying to teach myself by working through the Project Euler website. I am trying to complete this problem: http://projecteuler.net/problem=19, which is:
How many Sundays fell on the first of the month during the twentieth
century (1 Jan 1901 to 31 Dec 2000)?
The way I thought to solve it, was to make a 2D array that represents a calander, and to loop through the array by counting to 7, and then each time I count to 7, add 1 to that point in the array. At the end, I will sum the first row of the array, and that should be how many sundays were on the first of the month.
But I am having trouble with my loops, my counting to 7 resets when it gets to the end of a month, and I can't figure out how to stop it from doing that?
Here is my code:
public class Problem019 {
public static void main (String[] args){
//System.out.println(LeapYearTest(1996));
int ThirtyOne = 31;
int Thirty = 30;
int FebNorm = 28;
int FebLeap = 29;
int a, b, c, Day, e = 0, f = 0;
int Calander[] []= new int [12] [] ;
Calander[0] = new int [ThirtyOne];
Calander[1] = new int [FebNorm];
Calander[2] = new int [ThirtyOne];
Calander[3] = new int [Thirty];
Calander[4] = new int [ThirtyOne];
Calander[5] = new int [Thirty];
Calander[6] = new int [ThirtyOne];
Calander[7] = new int [ThirtyOne];
Calander[8] = new int [Thirty];
Calander[9] = new int [ThirtyOne];
Calander[10] = new int [Thirty];
Calander[11] = new int [ThirtyOne];
for (a=1901;a<2001;a++){
//System.out.println(a);
if (LeapYearTest(a))
{
Calander[1] = new int [FebLeap];
}
else
{
Calander[1] = new int [FebNorm];
}
for (e=0;e<Calander.length;e++)
{
System.out.println("e: " + e);
f=0;
while (f<Calander[e].length)
{
//System.out.println(Calander[e].length);
Day=1;
while (Day<8 && f<Calander[e].length)
{
System.out.println("f: " + f + "\tDay: " + Day + "\tCalander[e][f]: " + Calander[e][f]);
Day++;
f++;
if (f<Calander[e].length && f!=0 && Day==7)
{
Calander[e][f]+= 1;
}
}
}
}
//System.out.println(a);
}
for (b=0;b<Calander.length;b++)
{
System.out.print(Calander[0][b]);
}
}
public static boolean LeapYearTest(int x)
{
if (x%4==0 || x%400==0){
return true;
}
if (x%100==0){
return false;
}
else return false;
}
}
This is what it prints, e is the month, f is the days in the month, and Day is counting to 7:
f: 25 Day: 5 Calander[e][f]: 0
f: 26 Day: 6 Calander[e][f]: 0
f: 27 Day: 7 Calander[e][f]: 100
f: 28 Day: 1 Calander[e][f]: 0
f: 29 Day: 2 Calander[e][f]: 0
**f: 30 Day: 3 Calander[e][f]: 0**
e: 10
**f: 0 Day: 1 Calander[e][f]: 0**
f: 1 Day: 2 Calander[e][f]: 0
f: 2 Day: 3 Calander[e][f]: 0
How can I set up the loops so that Day doesn't reset at the end of the month? Or is there another way to solve this problem that doesn't involve so many nested loops?
Thankyou!
WOuldnt it be much quicker to have an outer loop that increments the year from 1901 to 2001, and an inner loop that checks Jan -> Dec, and then just see if the first of that month was a Sunday?
100 * 12 iterations in total,10 lines of code, tops.
Edit: To expand on this.
You can go about the problem in two ways - look at all the sundays and see if they're on the first of a month, or look at the first day of all the months and see if its a sunday.
Untested code:
Calendar calendar = Calendar.getInstance();
int count = 0;
for(int i=1901;i<2000;i++){
for(int j=1;i<12;j++){
calendar.set(Calendar.YEAR, i);
calendar.set(Calendar.MONTH,j);
calendar.set(Calendar.DAY,1);
if(calendar.get(Calendar.DAY_OF_WEEK).equals(Calendar.SUNDAY)){
count++;
}
}
}
System.out.println(count);
I think you need to toss out your existing code and start fresh. Since you're trying to learn how to code by solving Project Euler problems, I won't ruin the fun for you by giving you the code. It seems you do want the full working code, so I've fixed your code, including a few bugs that were present due to some subtle details in the problem statement that you may have misunderstood or overlooked.
Just for fun, let's take a look at the immediate problem with your code that you want fixed...
When you initially declare Day, initialize it to 1. Then replace this line:
Day=1;
with this:
if (Day > 7) {
Day = 1;
}
and move it inside of the loop that goes over the days of the month.
But there's still a serious problem. You keep overwriting your Feb array every year. You should only initialize it once, and set its length to 29. But this also has the unfortunate side effect of breaking any loops that depend on calendar[month].length, so you'll have to account for that, too.
All you really need to track are the number of Sundays that fell on the first of the month, so you just need to store and increment one variable. This solves the aforementioned problem with overwriting the Feb array, because you won't use it (or any other month's array) any more. On the other hand, if you really just want to practice using arrays, you could use a 3-dimensional array (in which the additional dimension is the year). But I'd venture to guess that most Java programmers use Lists instead of arrays most of the time, and when they do use arrays, they hardly ever use arrays with more than one dimension.
A few more notes
Your outer while loop is redundant.
Your LeapYearTest method will incorrectly return true for all leap years divisible by 100 (all years divisible by 100 are also divisible by 4, so you'll never enter the if block that tests years divisible by 100).
At the end, you're looping over every day of January (instead of looping over the first day of every month).
Also note that the problem states,
1 Jan 1900 was a Monday.
But you're supposed to find Sundays starting from 1 Jan 1901.
After fixing these and other bugs (such as the conditions in your loops), I've included a fully working version of your code below. Note that you could easily optimize this to run in a fraction of the time by making more use of the modulus (%) operator and by not computing the number of Sundays on other days of the month (since you throw them away anyway in the end).
public class Problem019 {
public static void main (String[] args){
final int ThirtyOne = 31;
final int Thirty = 30;
final int FebNorm = 28;
final int FebLeap = 29;
int numOfSundays = 0;
int calendar[][]= new int [12][];
calendar[0] = new int [ThirtyOne];
calendar[1] = new int [FebLeap];
calendar[2] = new int [ThirtyOne];
calendar[3] = new int [Thirty];
calendar[4] = new int [ThirtyOne];
calendar[5] = new int [Thirty];
calendar[6] = new int [ThirtyOne];
calendar[7] = new int [ThirtyOne];
calendar[8] = new int [Thirty];
calendar[9] = new int [ThirtyOne];
calendar[10] = new int [Thirty];
calendar[11] = new int [ThirtyOne];
int dayOfWeek = 1;
for (int year = 1900; year < 2001; year++) {
for (int month = 0; month < calendar.length; month++) {
int dayOfMonth=0;
int daysInMonth;
if (month == 1) {
daysInMonth = isLeapYear(year) ? FebLeap : FebNorm;
}
else {
daysInMonth = calendar[month].length;
}
while (dayOfWeek < 8 && dayOfMonth < daysInMonth) {
System.out.println("year: " + year + "\tday: " + dayOfWeek
+ "\tcalendar["+month+"]["+dayOfMonth+"]: " + calendar[month][dayOfMonth]);
if (dayOfWeek == 7 && year > 1900) {
calendar[month][dayOfMonth]++;
if (dayOfMonth == 0) {
numOfSundays++;
}
}
dayOfMonth++;
dayOfWeek++;
if (dayOfWeek > 7) {
dayOfWeek=1;
}
}
}
}
for (int month = 0; month < calendar.length; month++) {
System.out.println(calendar[month][0]);
}
System.out.println(numOfSundays);
}
public static boolean isLeapYear(int year){
if (year % 400 == 0) {
return true;
}
else if (year % 100 == 0) {
return false;
}
else if (year % 4 == 0){
return true;
}
else {
return false;
}
}
}
Again, this could be improved upon quite a lot. For example, you could simply loop over the years and months, and use Java's built-in Calendar API or a third-party API, to check whether the first day of the month is a Sunday, but perhaps the coolest way to solve the problem is to implement the Doomsday Algorithm yourself. This will allow you to easily compute the day of the week for any given date, without using java.util.Calendar.
Once you have implemented the Doomsday Algorithm, you don't necessarily have to loop over all the months every time, so you could do even more optimizations. For instance, isSunday(MAR,1,year) == (! isLeapYear(year)) && isSunday(FEB,1,year).
Try this:
import java.util.Calendar;
public class Problem019 {
public static void main (String[] args){
Calendar calendar = Calendar.getInstance();
int countFirstSunday = 0;
for(int year = 1901; year <= 2000 ; year++) {
for(int month = 0; month <= 11; month++) {
calendar.set(year, month, 1);
if(calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
countFirstSunday++;
}
}
}
System.out.println("Sundays as the first of month: " + countFirstSunday);
}
}
Here is my proposition. It use Gregorian calendar to identify the date, and then if it's a Sunday.
import java.util.Date;
import java.util.GregorianCalendar;
public class SundayOfXX {
public static void main(String [] argv) {
int counter = 0;
for (int year = 1901, last_year = 2000; year <= last_year ; year++) {
for (int month = 1, last_month = 12; month <= last_month ; month++) {
Date d = new GregorianCalendar(year,month-1,1).getTime(); // GregorianCalendar use 0 for January
if (d.getDay() == 0) { // sunday is day number 0
counter++;
System.out.println(String.valueOf(counter) + " " + d);
}
}
}
System.out.println("Total sunday in XX century: "+counter);
}
}
This solution is fully tested. It finds 171 sundays that are 1st day of a month in 20th century.
This is your code cleaned up and simplified:
public static void main(String[] args) {
final int thirtyOne = 31, thirty = 30;
final int calendar[][] = new int[12][];
final int[] febLeap = new int[29];
final int[] febNorm = new int[28];
calendar[0] = new int[thirtyOne];
calendar[2] = new int[thirtyOne];
calendar[3] = new int[thirty];
calendar[4] = new int[thirtyOne];
calendar[5] = new int[thirty];
calendar[6] = new int[thirtyOne];
calendar[7] = new int[thirtyOne];
calendar[8] = new int[thirty];
calendar[9] = new int[thirtyOne];
calendar[10] = new int[thirty];
calendar[11] = new int[thirtyOne];
int dow = 0; // set to day of week for Jan 1 1901
for (int y = 1901; y < 2001; y++) {
calendar[1] = leapYearTest(y)? febLeap : febNorm;
for (int m = 0; m < calendar.length; m++)
for (int d = 0; d < calendar[m].length; d++)
if (dow++ % 7 == 0) calendar[m][d]++;
}
int sumSundays = calendar[0][0] + febLeap[0] + febNorm[0];
for (int i = 2; i < calendar.length; i++) sumSundays += calendar[i][0];
System.out.println("Number of Sundays is " + sumSundays);
}
public static boolean leapYearTest(int x) {
if (x % 4 == 0 || x % 400 == 0)
return true;
return x % 100 != 0;
}
Here's what I meant when I said you don't need arrays:
public static void main(String[] args) {
final int[] mLens = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int dow = 0; // initialize to day of week on Jan 1, 1901
int suns = 0;
for (int y = 1901; y < 2001; y++)
for (int m = 0; m < mLens.length; m++) {
if (dow++ % 7 == 0) suns++;
final int mLen = mLens[m] + leapAdd(y, m);
for (int d = 1; d < mLen; d++) dow++;
}
System.out.println(suns);
}
static int leapAdd(int y, int m) {
if (m != 1) return 0;
if (y % 4 == 0 || y % 400 == 0) return 1;
return y % 100 == 0 ? 0 : 1;
}
But immediately you realize there's no sense in that inner loop running through days of month, when it's all just modulo 7. So the inner loop should say
for (int m = 0; m < mLens.length; m++) {
if (dow == 0) suns++;
final int mLen = mLens[m] + leapAdd(y, m);
dow = (dow + mLen) % 7;
}
I'd do it like so (pseudocode):
class MyDate { ... } // support adding a number of days and comparing with another MyDate
MyDate end = new MyDate(31. Dec 2000)
MyDate start = new MyDate(first sunday in 20th century)
int count = start.mday == 1 ? 1 : 0;
start.add(7);
while (start < end) (
if (start.mday == 1) count++;
start.add(7);
}
Note that one doesn't need any arrays, much less 2d arrays. (To get the month length, however, in the add method of MyDate, using a simple constant array is ok.)
Here are 2 solutions:
1) Using Calendar - it is more simple, but it is not so efficient - 135 ms
import java.util.Calendar;
public class P19 {
public static void main(String[] args) {
int result = 0;
for ( int year = 1901 ; year <= 2000 ; year++ ) {
for ( int month = Calendar.JANUARY ; month <= Calendar.DECEMBER ; month++ ) {
Calendar c = getCalendar(year, month, 1);
if ( c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ) {
result++;
}
}
}
System.out.println(result);
}
private static Calendar getCalendar(int year, int month, int day) {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, day); // or Calendar.DATE
return c;
}
}
Notice that:
DAY_OF_MONTH and DATE are equivalent.
I used Calendar.JANUARY because the first month is 0, not 1, even if the first day/date is 1.
2) Using my own Date class - it takes only 1.65 ms:
public class P19 {
public static void main(String[] args) {
// 1 Jan 1900 - Monday
// 1900 is not leap => it has 365 days
// 365 % 7 = 1 => 1 Jan 1901 - Tuesday => 6 Jan 1901 - Sunday
int yearStart = 1901, yearEnd = 2000;
int monthStart = 1, monthEnd = 12;
int dayStart = 6, dayEnd = 31;
Date dateStart = new Date(yearStart, monthStart, dayStart);
Date dateStop = new Date(yearEnd, monthEnd, dayEnd);
int result = 0;
while (Date.compareDates(dateStart, dateStop) < 0) {
if (dateStart.day == 1) {
result++;
}
dateStart.addDays(7);
}
System.out.println(result);
}
}
class Date {
int year;
int month;
int day;
Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public void addDays(int days) {
int numberOfDaysForMonth = getTotalMonthDays(month, year);
day += days;
if (day >= numberOfDaysForMonth) {
day -= numberOfDaysForMonth;
month++;
if (month > 12) {
month = 1;
year++;
}
}
}
public static int compareDates(Date d1, Date d2) {
if (d1.year == d2.year && d1.month == d2.month && d1.day == d2.day) {
return 0;
}
if (d1.year < d2.year) {
return -1;
}
if (d1.year == d2.year && d1.month < d2.month) {
return -1;
}
if (d1.year == d2.year && d1.month == d2.month && d1.day < d2.day) {
return -1;
}
return 1;
}
private int getTotalMonthDays(int m, int y) {
if (m == 2 && isLeapYear(y)) {
return 29;
}
if (m == 2) {
return 28;
}
if (m == 4 || m == 6 || m == 9 || m == 11) {
return 30;
}
return 31;
}
private boolean isLeapYear(int y) {
if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) {
return true;
}
return false;
}
}
This implementation iterates only through Sundays ( addDays(7) ).
Some possible improvements:
increase the step (E.g.: for 1, we can add 28 instead of 7 without skipping any day)
change the compare method to return a boolean and to simplify its body
public class CountingSundays {
public static void main(String[] args) {
int lastDayOfPreviousMonth = 6; //31 Dec 1899 is Sunday as 1 Jan 1900 is Monday
int countOfSundayOnFirstOfMonth = 0;
for (int year = 1900; year <= 2000; year++) {
for (int month = 1; month <= 12; month++) {
int dayOnFirstOfThisMonth = (lastDayOfPreviousMonth + 1) % 7;
if (year > 1900 && dayOnFirstOfThisMonth == 6)
countOfSundayOnFirstOfMonth++;
switch (month) {
case 1: // Jan
case 3: // Mar
case 5: // May
case 7: // Jul
case 8: // Aug
case 10: // Oct
case 12: // Dec
lastDayOfPreviousMonth = (lastDayOfPreviousMonth + 3) % 7;
break;
case 4: // Apr
case 6: // Jun
case 9: // Sep
case 11: // Nov
lastDayOfPreviousMonth = (lastDayOfPreviousMonth + 2) % 7;
break;
case 2: // Feb
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
lastDayOfPreviousMonth = (lastDayOfPreviousMonth + 1) % 7;
}
}
}
System.out.println(countOfSundayOnFirstOfMonth);
}
}