The question asks to calculate the number of 13ths that fall on each day of the week. This is my code.
class CopyOffriday {
public static void main(String[] args
As pointed out in comments, you are iterating for 11 months. I tried this problem after you posted to know if I am missing something. Other than that it looks okay. Let us know if 12 months fixes the problem. Otherwise I'll try looking more into your code.
SPOILER ALERT for my referred code.
HashMap<Integer, Integer> daysInAMonth = new HashMap<Integer, Integer>();
daysInAMonth.put(0, 31);
daysInAMonth.put(2, 31);
daysInAMonth.put(3, 30);
daysInAMonth.put(4, 31);
daysInAMonth.put(5, 30);
daysInAMonth.put(6, 31);
daysInAMonth.put(7, 31);
daysInAMonth.put(8, 30);
daysInAMonth.put(9, 31);
daysInAMonth.put(10, 30);
daysInAMonth.put(11, 31);
HashMap<Integer, Integer> dayFrequency = new HashMap<Integer, Integer>(7);
//sat - 0
// sun -1
// mon -2
// tue -3
// wed -4
// thu -5
// fri -6
dayFrequency.put(0, 0);
dayFrequency.put(1, 0);
dayFrequency.put(2, 0);
dayFrequency.put(3, 0);
dayFrequency.put(4, 0);
dayFrequency.put(5, 0);
dayFrequency.put(6, 0);
int N = Integer.parseInt(st.nextToken());
if (N==0) {
out.println("0 0 0 0 0 0 0");
System.exit(0);
}
System.out.println(N);
int firstFriday = 0;
int lastFriday = 0;
for(int i=0 ;i<N; i++) {
int year = 1900+i;
for(int month=0; month<12;month++){
if(month ==0 && year ==1900) {
int prevCount = dayFrequency.get(0);
dayFrequency.put(0, prevCount + 1);
lastFriday = 0;
}
int noOfdays;
if(month != 1)
noOfdays = daysInAMonth.get(month);
else
noOfdays = daysInFebruary(year);
int wrapDays = (noOfdays-13) + 13;
lastFriday = (lastFriday + wrapDays)%7;
dayFrequency.put(lastFriday, dayFrequency.get(lastFriday) + 1);
}
}
dayFrequency.put(lastFriday, dayFrequency.get(lastFriday) - 1);
for(int i=0;i<7;i++) {
out.print(dayFrequency.get(i));
if( i != 6)
out.print(" ");
}
out.println("");
out.close();
System.exit(0);
}
public static int daysInFebruary(int year) {
if(year % 400 == 0)
return 29;
if(year % 4 == 0 && year % 100 != 0)
return 29;
return 28;
}
}
Gotcha!
for (int i = 1900; i <= N; i++) {
for (int month = 1; month <= 12; month++) {
if ((i == 1900) && (month == 1)) {
counter[position - 1]++;
position = 31%7 + 1;
}
There were two mistakes, first that 9 should be there instead of 8. The general logic we've followed is that we know the day of the first ever 13th in 1900. Once you are in the code for January 1900, you need to do two things. First, increment count for Saturday and then since Jan has 31 days, you loop over to find the day 13th falls on in February i.e you move from 13th January 1900 to 13th February 1900 in the same piece of code which is accomplished by adding 31 days which is the number of days between 13 Feb and 13 Jan. To translate this into a day you do the 31%7(+1 in your case as your numbering starts from 1). So in the loop for month = January, you increment for Feb as well.
For month = Feb you loop over to find day for March and increment when the for loop closes. Similarly in the loop month = Nov, you loop over to find the day for Decemeber and then break if the year is the final year so as not spill over into the next year. If the year isnt final you go into
if ((month == 4) || (month == 6) || (month == 9)
|| (month == 11))
and do your usual business and increment for December without breaking. For month = December you increment the day count for 13 January of the following year thus allowing us to isolate our special case for January 1900 since January of any other year will skip all if statements and do
position += 3;
without any problem. Special case :
if ((i == 1900) && (month == 1)) {
counter[position - 1]++;
position = 31%7 + 1;
}
Your full code.
public static void main(String[] args) throws IOException {
// Use BufferedReader rather than RandomAccessFile; it's much faster
BufferedReader f = new BufferedReader(new FileReader(
"/home/shaleen/USACO/friday/friday.in"));
// input file name goes above
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
"/home/shaleen/USACO/friday/friday.out")));
// Use StringTokenizer vs. readLine/split -- lots faster
// StringTokenizer st = new StringTokenizer(f.readLine());
// Get line, break into tokens.
int n1 = Integer.parseInt(f.readLine());
int[] counter = new int[7];
int N = 1900 + n1 - 1;
int position = 1; // first 13th is a Saturday
for (int i = 1900; i <= N; i++) {
for (int month = 1; month <= 12; month++) {
if ((i == 1900) && (month == 1)) {
counter[position - 1]++;
position = 31%7 + 1;
}
else if ((i == N) && (month == 11)) {
position += 2;
position %= 7;
counter[position - 1]++;
System.out.println(i + " " + month + " " + position + " ");
break;
} else if ((month == 4) || (month == 6) || (month == 9)
|| (month == 11))
position += 2;
else if (month == 2) {
if ((i % 400 == 0) || ((i % 100 != 0) && (i % 4 == 0)))
position += 1;
else
position += 0;
} else
position += 3;
if (position > 7)
position %= 7;
counter[position - 1]++;
System.out.println(i + " " + month + " " + position + " ");
}
}
for (int x : counter) {
System.out.print(x + " ");
}
}
}