GeoTeo
GeoTeo

Reputation: 73

Java: How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

I am new to programming and java and I am trying to solve the following problem: How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

Here is my code:

int count, sum = 0;           
for (int i = 1901; i < 2001; i++) {
    LocalDate test = LocalDate.of(i, 1, 1);
    sum += test.lengthOfYear();
}
for (int i = 1; i < sum; i++) {
    LocalDate date1 = LocalDate.of(1901, 1, 1);
    date1 = date1.plusDays(i);
    if (date1.getMonth() == JANUARY && date1.getDayOfWeek() == SUNDAY) {
        count++;
    }
}
System.out.println(count);

If I print the results, it seems to be working fine.

My result is 443, but the correct answer is 171. What am I doing wrong?

Thank you!

Upvotes: 7

Views: 7455

Answers (7)

MC Emperor
MC Emperor

Reputation: 23017

I suspect 443 is the total number of Sundays in January in the twentieth century. This happens because you walk over all possible days of the twentieth century and then check if the current month is January and if the current day is Sunday.

This is not what you want.

I would use a different approach:

  • Walk over the 1st day of each month of each year.
  • And then check if it's a Sunday.

The code will probably be much faster.

// Each year
for (int y = 1901; y < 2001; y++) {
    // Each month of the year
    for (int m = 1; m <= 12; m++) {
        if (LocalDate.of(y, m, 1).getDayOfWeek() == DayOfWeek.SUNDAY) {
            count++;
        }
    }
}

Your code would have been correct if you changed date1.getMonth() == JANUARY to date1.getDayOfMonth() == 1. However, the method is very inefficient, because it checks each day of the twentieth century, while it only needs to check the first day of each month. The abovementioned code is approximately 40 times faster on my machine.

Here is an equivalent of the abovementioned code, with functional style:

long count = Stream.iterate(YearMonth.of(1901, 1), ym -> ym.plusMonths(1))
    .takeWhile(ym -> ym.isBefore(YearMonth.of(2001, 1)))
    .map(ym -> ym.atDay(1).getDayOfWeek())
    .filter(DayOfWeek.SUNDAY::equals)
    .count();

Using Todd's Java-TimeStream, with functional style:

YearMonthStream
    .from(YearMonth.of(1901, 1))
    .until(YearMonth.of(2000, 12))
    .stream()
    .map(ym -> ym.atDay(1).getDayOfWeek())
    .filter(DayOfWeek.SUNDAY::equals)
    .count();

Upvotes: 11

heaven2sai
heaven2sai

Reputation: 129

You are considering only January month from 1901 to 2000, which is incorrect, you should consider whether first day of every month from 1901 to 2000 was sunday or not.

Upvotes: 0

limaia
limaia

Reputation: 96

443 is number of Sundays in January, if you want the Sundays on the first of the month, you have to change your code to:

if(date1.getDayOfMonth() == 1 && date1.getDayOfWeek() == SUNDAY) {
            count++;
            }
        }

Sugestion: instead of walk over all days of each year, you can just add 1 month to the date util 12 month:

    for (int i = 1901; i < 2001; i++) {
      for(int mon =0; mon<12; mon++){
          LocalDate date1= LocalDate.of(i,mon,1);
          if(date1.getDayOfWeek() == SUNDAY) {
           count++;
          }
       }
    }

Upvotes: 0

assylias
assylias

Reputation: 328737

Apart from the error that has already been flagged, you could reconsider your design and use the YearMonth class which seems better suited to your use case than LocalDate:

public static void main(String[] args) {
  YearMonth start = YearMonth.of(1901, 1);
  YearMonth end = YearMonth.of(2000, 12);

  int count = 0;
  for (YearMonth ym = start; !ym.isAfter(end); ym = ym.plusMonths(1)) {
    //is first day of month a sunday?
    if (ym.atDay(1).getDayOfWeek() == SUNDAY) count ++;
  }

  System.out.println(count); //171
}

Upvotes: 6

ernest_k
ernest_k

Reputation: 45329

The following code should output the correct value.

public static void main(String[] args) {
    int count = 0, sum = 0;
    for (int i = 1901; i < 2001; i++) {
        LocalDate test = LocalDate.of(i, 1, 1);
        sum += test.lengthOfYear();
    }

    for (int i = 1; i < sum; i++) {
        LocalDate date1 = LocalDate.of(1901, 1, 1);
        date1 = date1.plusDays(i);
        if (date1.getDayOfMonth() == 1 && date1.getDayOfWeek() == java.time.DayOfWeek.SUNDAY) {
            count++;
        }
    }

    System.out.println(count);
}

Note that:

  1. You don't need to check that month is January, because your requirement is about any 1st of the month.
  2. You must also ensure that the current day is the first day of the month.

Upvotes: 3

David P&#233;rez Cabrera
David P&#233;rez Cabrera

Reputation: 5068

I see some mistakes:

public static void main(String[] args) {
    int count, sum = 0;           
    for (int i = 1901; i < 2001; i++) { // There is a mistake here, I dont know what you want to compute in this loop!
        LocalDate test = LocalDate.of(i,1,1);
        sum += test.lengthOfYear();
    }
    for (int i = 1; i < sum; i++) {
        LocalDate date1 = LocalDate.of(1901,1,1); // There is a mistake here, date1 must be outside of this loop
        date1 = date1.plusDays(i); // There is a mistake here, plusDays why?? 
    if(date1.getMonth() == JANUARY && date1.getDayOfWeek() == SUNDAY) { // There is a mistake here, why are you cheking this: date1.getMonth() == JANUARY ?
        count++;
        }
    }
    System.out.println(count);
}

A simple solution:

public static void main(String[] args) {
    int count = 0;
    LocalDate date1 = LocalDate.of(1901, Month.JANUARY, 1);
    LocalDate endDate = LocalDate.of(2001, Month.JANUARY, 1);
    while (date1.isBefore(endDate)) {
        date1 = date1.plusMonths(1);
        if (date1.getDayOfWeek() == DayOfWeek.SUNDAY) {
            count++;
        }
    }
    System.out.println(count);
}

Upvotes: 6

Chris H
Chris H

Reputation: 810

You start by finding the number of days in the period you're checking, and then start a for loop to run through that period. So far so good. But your condition for incrementing the count is wrong:

if(date1.getMonth() == JANUARY && date1.getDayOfWeek() == SUNDAY)

This means that as you loop over each day, you increase count if that date is a Sunday in January. You don't check whether that Sunday was the first of January, and you don't count anything from February to December.

You should be checking that it's the first day of the month and Sunday, not the first month of the year and Sunday.

Upvotes: 3

Related Questions