Beginner level Java - Zellers algotrithm - java

I have an assignment in Java (intro to programming) based on Zellers algorithm, Write input as integers, loop and counter code and I have to use a while loop to get the day and year first then the month, treating Jan & Feb as prior year. I thought I was at least in the ballpark, but cannot get my code to work. Any suggestions on how to improve?
import java.util.Scanner;
import java.text.NumberFormat;
public class ZellersAlgorithm {
public static void main(String[] args) {
//declarations go here
int count, Month, Day, Year;
int C = (int)(Year / 100.0); // the century
int D = (int) (Year % 100); // The year of the century
int K = Day;
int M = Month;
int G = (K + (int)((26 * (M + 1)) / 10.0) + C + (int)(C / 4.0)
+ (int)(D / 4.0) + (5 * D)) % 7;
Month = (M);
Day = (K);
Year = (C + D);
Scanner scan = new Scanner(System.in);
//Title
System.out.println("Project 2 - Zellers Algorithm");
while(M != 0){
System.out.print("Enter a numberic day: ");
K = scan.nextInt();
if (K == 0)
System.out.print("Saturday");
else if (K == 1)
System.out.print("Sunday");
else if (K == 2)
System.out.print("Monday");
else if (K == 3)
System.out.print("Tuesday");
else if (K == 4)
System.out.print("Wednesday");
else if (K == 5)
System.out.print("Thursday");
else
System.out.print("Friday");
System.out.print("Enter a nummeric year: ");
///Need to convert 4 digit year to C & D variable
// Add counter, possibly include length counter 1st 2 digits are century/C last 2 are year
Year = scan.nextInt();
System.out.print("Enter a numeric month: ");
M = scan.nextInt();
switch (M) {
case 1:
System.out.println("March");
break;
case 2:
System.out.println("April");
break;
case 3:
System.out.println("May");
break;
case 4:
System.out.println("June");
break;
case 5:
System.out.println("July");
break;
case 6:
System.out.println("August");
break;
case 7:
System.out.println("September");
break;
case 8:
System.out.println("October");
break;
case 9:
System.out.println("November");
break;
case 10:
System.out.println("December");
break;
case 11:
System.out.println("January" + D + count--);
break;
case 12:
System.out.println("February" + D + count--);
break;
default:
System.out.println("Invalid month.");
break;
}
}
//formula one
//G =([2.6M-.2]+K+D+[D/4]+[C/4]-2C mod 7;
//display as integer
String result = "Day of the week is ";
System.out.println();

Please clarify on what but cannot get my code to work means.
Some comments though
int count, Month, Day, Year; -- variables should be lower case (this does not change the behaviour of your program but is common code style for Java programs - Most people would read Year as a class name). The same goes for "all uppercase" like C, which is normally used for constants
Use variable names that express meaning. M, K, C, D do not help the reader to understand, what they mean.

Related

How to Properly print Month Calendar on Terminal

Hello and thanks in advance for the assistance. I have a program that is supposed to print the current month calendar based on the user inputs of month and year. The program mostly work but i am having issues with formatting and the first day of the month is not starting under the proper date.
Example output:
October 2020
------------------------------
Sun Mon Tue Wed Thu Fri Sat
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
October 2020 will begin on a Thursday, but 1 is printed under Mon. October 4th is a Sunday, so that is where the new line should begin.
Please see attached my code. Thanks again
import java.util.*;
public class CalendarMonthDisplay {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); //Scan for user input
System.out.print("Please enter a month between 1 and 12 (e.g. 5): "); //Prompt user to enter month
int m = input.nextInt();
System.out.print("Please enter a full year (e.g. 2018): "); //Prompt user to enter year
int y = input.nextInt();
//Print calendar for the month of the year
if ( m < 1 || m > 12)
System.out.print("Wrong input! Please try again.");
else
printMonthCalendar(m, y);
}
static void printMonthCalendar (int m, int y) { //Display calendar in format above
int startDay = getStartDay(m, y);
int numDaysInMonths = getNumDaysInMonth(m, y);
printMonthHeader(m, y);
printMonthBody(startDay, numDaysInMonths);
}
static void printMonthBody (int startDay, int numDaysInMonths) { //Display the days in the calendar
int i;
for (i = 0; i <= startDay; i++)
System.out.print(" ");
for (i = 1; i <= numDaysInMonths; i++) {
if ( i < 10 )
System.out.print(" " + i );
else
System.out.print(" " + i + " ");
if ((startDay + i) % 7 == 0)
System.out.println();
}
System.out.println();
}
static void printMonthHeader (int m, int y) { //Display the header information
System.out.println("\t" + getMonthName(m) + " " + y);
System.out.println("------------------------------");
System.out.println(" Sun Mon Tue Wed Thu Fri Sat");
}
static String getMonthName (int m) {
String monthName = null;
switch (m) {
case 1: monthName = "January";
break;
case 2: monthName = "February";
break;
case 3: monthName = "March";
break;
case 4: monthName = "April";
break;
case 5: monthName = "May";
break;
case 6: monthName = "June";
break;
case 7: monthName = "July";
break;
case 8: monthName = "August";
break;
case 9: monthName = "September";
break;
case 10: monthName = "October";
break;
case 11: monthName = "November";
break;
case 12: monthName = "December";
}
return monthName;
}
static int getNumDaysInMonth (int m, int y) {
int numDaysInMonths= 0;
switch (m) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
numDaysInMonths= 31;
break;
case 4: case 6: case 9: case 11:
numDaysInMonths = 30;
break;
case 2:
if (isLeapYear(y))
numDaysInMonths = 29;
else
numDaysInMonths = 28;
break;
}
return numDaysInMonths;
}
static boolean isLeapYear (int y) {
return (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0);
// return true;
// return false;
}
static int getStartDay (int m, int y) {
// Adjust month number & year to fit Zeller's numbering system
if (m < 3)
m = m + 12;
y = y - 1;
int d = 1; //Set day parameter to 1
int k = y % 100; // Calculate year within century
int j = y / 100; // Calculate century term
int h = 0; // Day number of first day in month 'm'
h = ( d + ( 13 * ( m + 1 ) / 5 ) + k + ( k / 4 ) + ( j / 4 ) + ( 5 * j ) ) % 7;
// Convert Zeller's value to ISO value (1 = Mon, ... , 7 = Sun )
int dayNum = ( ( h + 5 ) % 7 ) + 1;
return dayNum;
}
}
I recommend you do it using the modern date-time API. Learn more about the modern date-time API from Trail: Date Time.
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); // Scan for user input
System.out.print("Please enter a month between 1 and 12 (e.g. 5): "); // Prompt user to enter month
int m = input.nextInt();
System.out.print("Please enter a full year (e.g. 2018): "); // Prompt user to enter year
int y = input.nextInt();
printMonth(y, m);
}
static void printMonth(int year, int month) {
YearMonth ym = YearMonth.of(year, month);
System.out.println("Sun Mon Tue Wed Thu Fri Sat");
int counter = 1;
// Get day of week of 1st date of the month and print space for as many days as
// distant from SUN
int dayValue = LocalDate.of(year, month, 1).getDayOfWeek().getValue();
for (int i = 0; i < dayValue; i++, counter++) {
System.out.printf("%-4s", "");
}
for (int i = 1; i <= ym.getMonth().length(ym.isLeapYear()); i++, counter++) {
System.out.printf("%-4d", i);
// Break the line if the value of the counter is multiple of 7
if (counter % 7 == 0) {
System.out.println();
}
}
}
}
A sample run:
Please enter a month between 1 and 12 (e.g. 5): 9
Please enter a full year (e.g. 2018): 2020
Sun Mon Tue Wed Thu Fri Sat
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
Note: Learn about formatted printing at Formatter.
I don’t think your getStartDay method returns the day of week number that you expect. It seems to be returning 1 for Wednesday through 7 for Tuesday. Examples:
Month Start day of week getStartDay()
------------------------------------------------
July 2020 Wednesday 1
August 2020 Saturday 4
September 2020 Tuesday 7
October 2020 Thursday 2
There is probably one or two more problems in your code, but I think you should fix this fundamental one first.
It’s a fine exercise, you’re surely learning. For production code one would never implement Zeller’s algorithm or any other algorithm for finding lengths of months and days of week. This is done much more reliably by the standard library as shown in the answer by Arvind Kumar Avinash.

Number theory modular arithmetic how to account for adjustments

I am not sure whether my solution is justifiable (ans. 171) - Project Euler Q.19 since I am having a hard time getting my head around modular arithmetic and not really sure whether my approach to it was correct or not... I was having trouble on trying to get the equivalence of having 0 as a key rather than 1 to Monday for reference in a hash table. The question was;
1 Jan 1900 was a Monday.
Thirty days has September, April, June and November. All the rest have thirty-one, Saving February alone, which has twenty-eight, rain
or shine. And on leap years, twenty-nine.
A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
How many Sundays fell on the first of the month during the twentieth
century (1 Jan 1901 to 31 Dec 2000)?
So what I did was start the sum of days at 1 (reference for days in hash table) and subtract 1 after finding the sum of Sunday's, since doing it by 0 caused problems when the total sum of days were divisible by 3 and 6 (3:Wednesday, 6:Sunday). How could I have done this by using 0 as reference for Monday?
import java.util.*;
public class p19 {
public static void main(String[] args) {
Hashtable<Integer, String> days = new Hashtable<Integer, String>();
days.put(1, "Monday");
days.put(2, "Tuesday");
days.put(3, "Wednesday");
days.put(4, "Thursday");
days.put(5, "Friday");
days.put(6, "Saturday");
days.put(7, "Sunday");
Hashtable<Integer, String> months = new Hashtable<Integer, String>();
months.put(1, "January");
months.put(2, "February");
months.put(3, "March");
months.put(4, "April");
months.put(5, "May");
months.put(6, "June");
months.put(7, "July");
months.put(8, "August");
months.put(9, "September");
months.put(10, "October");
months.put(11, "November");
months.put(12, "December");
int min, max;
min = 1900;
max = 2000;
String[][] arr = new String[12 * (max - min + 1)][];
// Total days starts at 1 to make modular arithmetic easier when accounting for days
// (i.e., 1 Monday, 2 Tuesday, etc.) and since the first day, hence, 0th day on 1 Jan 1900 is Monday.
for (int year = min, index = 0, totalDays = 1; year <= max; year++) {
for (int month = 1; month <= 12; month++, index++) {
arr[index] = new String[numberOfDays(month,year)];
int sum = 1;
System.out.println(months.get(new Integer(month)) + " " + year);
for (int day = 1; day <= numberOfDays(month, year); day++, totalDays++) {
if (totalDays % 7 == 0) {
arr[index][day - 1] = days.get(new Integer((totalDays % 7 + 7) % 365));
}
else {
arr[index][day - 1] = days.get(new Integer((totalDays % 7) % 365));
}
if (sum > 7) {
System.out.println();
sum = 1;
}
System.out.print(totalDays + ":= " + arr[index][day - 1] + ", " + day + " | ");
sum++;
}
System.out.println("\n");
}
}
int count = 0;
for (int i = 1; i < arr.length; i++) {
if (arr[i][0] == "Sunday") {
count++;
}
}
// Subtract 1 from count since the total days were overstated by 1 before inititallizing array
System.out.println("Number of Sundays that fell on the first of the month from: 1/Jan/1901 - 31/Dec/2000: " + (count - 1));
}
public static int numberOfDays (int month, int year) {
int days = 0;
switch (month) {
case 7:
case 4:
case 6:
case 11:
days = 30;
break;
case 2:
if (isLeapYear(year)) {
days = 29;
}
else {
days = 28;
}
break;
default: days = 31;
break;
}
return days;
}
public static boolean isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
}
Your daysInMonth check is incorrect - the result must have been correct by incidence:
switch (month) {
case 4:
case 6:
case 9:
case 11:
days = 30;
break;
The rest of the program can be simplified - note that the start year has to be corrected too, dow stands for DayOfWeek:
public static void main (String[] args) {
int count = 0;
// dow = 2, since 1.1.1901 was a Thuesday (2)
for (int year = 1901, dow = 2; year <= 2000; ++year)
{
for (int month = 1; month <= 12; ++month)
{
if (dow == 0) {
// System.out.println ("Date: " + year + "-" + month);
++count;
}
dow = (dow + numberOfDays (month, year)) % 7;
}
}
System.out.println ("Number of Sundays that fell on the first of the month from: 1/Jan/1901 - 31/Dec/2000: " + count);
}

How do i convert an if-else statement to a switch statement

I have this program of rolling dice by 1000000 and finding the number of 1's, 2's, 3's, 4's, 5's, 6's`but i need to make a switch statement as well. Im having trouble using the scanner input
import java.util.Random;
public class DiceRoll_NP {
public static void main(String[] args) {
Random rand = new Random();
final double NUMBER_OF_ROLLS = 1000000.0;
int x = rand.nextInt();
// System.out.println(x);
int ones = 0, twos = 0, threes = 0, fours = 0, fives = 0, sixes = 0;
for (int i = 1; i <= NUMBER_OF_ROLLS; i = i + 1) {
int y = rand.nextInt(6) + 1;
if (y == 1) ones++;
else if (y == 2) twos++;
else if (y == 3) threes++;
else if (y == 4) fours++;
else if (y == 5) fives++;
else if (y == 6) sixes++;
System.out.print(y + " ");
}
System.out.printf("\nOnes: %.2f%%\n", 100 * ones / NUMBER_OF_ROLLS);
System.out.printf("Twos: %.2f%%\n", 100 * twos / NUMBER_OF_ROLLS);
System.out.printf("Threes: %.2f%%\n", 100 * threes / NUMBER_OF_ROLLS);
System.out.printf("Fours: %.2f%%\n", 100 * fours / NUMBER_OF_ROLLS);
System.out.printf("Fives: %.2f%%\n", 100 * fives / NUMBER_OF_ROLLS);
System.out.printf("sixes: %.2f%%\n", 100 * sixes / NUMBER_OF_ROLLS);
}
}
This i what i have so far. When i run it, nothing comes up
import java.util.Random;
public class DiceRoll_Switch {
public static void main(String[] args) {
Random rand = new Random();
int ones = 0, twos = 0, threes = 0, fours = 0, fives = 0, sixes = 0;
int y = rand.nextInt(6) + 1;
for (int i = 1; i <= 1000000; i = i + 1)
switch (y){
case 1: ones++;
break;
case 2: twos++;
break;
case 3: threes++;
break;
case 4: fours++;
break;
case 5: fives++;
break;
case 6: sixes++;
break;
In the early days of programming, the goto statement was heavily used. It works like this:
if ( true )
goto label;
System.out.println("A");
label:
System.out.println("B");
The above code would jump to the label, skipping printing the A. It's pretty simple.
Now, why did I mention this? Here's an example of an if statement:
if ( y == 1 )
System.out.println("It is 1");
else
System.out.println("It is not 1");
and here's how it works using goto:
if ( y != 1 )
goto not_1;
// this is the 'then' part:
System.out.println("It is 1");
goto done; // we don't want to run the 'else' part!
not_1:
// this is the 'else' part
System.out.println("It is not 1");
done:
If you understand this, then a switch statement won't be any trouble.
A switch statement looks like this:
switch (y) {
case 1: ones++; break;
case 2: tows++; break;
default: System.out.println("Unexpected number of eyes: " + y);
}
It compares the value of y with all the values after the case, and if it is a match, starts executing the code at that case. The break indicates that that case is done. The default 'case' gets executed when none of the cases is a match.
And here's how it basically works using goto:
if ( y == 1 ) goto case_1;
if ( y == 2 ) goto case_2;
// here comes the default:
default:
System.out.println("Unexpected number of eyes: " + y);
goto switch_done;
case_1:
ones++;
goto switch_done; // this is the 'break' statement.
case_2:
twos++;
goto switch_done;
switch_done: // end of the switch.
I hope this makes things a bit more clear as to how it works!
That said, you're better off using an array:
int eyes[] = new int[] { 0,0,0,0,0,0 };
for ( int i = 1; i <= NUMBER_OF_ROLLS; i++ )
{
int y = rand.nextInt(6) + 1;
eyes[y] ++;
}
This also makes your printing much shorter:
for ( int i = 0; i < eyes.length; i ++ )
System.out.printf( (i+1) + ": %.2f%%\n", 100 * eyes[i] / NUMBER_OF_ROLLS );
You are basically doing the same thing for each y, and you should want to write as little code as possible: it is easier to maintain and to understand, and, there is less chance of bugs.
It's very similar. These two are pretty much doing the exact same thing:
int x = 2;
if(x == 1) {
System.out.println("1");
}
else if(x == 2) {
System.out.println("2");
}
else {
System.out.println("None of the above");
}
int x = 2;
switch(x) {
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
default:
System.out.println("None of the above");
break;
}
A switch statement consists in:
switch (y) {
case 1:
ones++;
break;
case 2:
twos++;
break;
...
}
and so on, where the value inside the parenthesis is the variable name you want to check, and the number after "case" is the cases it may happen. You MUST put a break after your instruction is over to tell the program it can exit the switch statement after he founds the correct one and stops executing. Otherwise, if you don't put the break; command in the "case 1" block, it'll keep executing every line until it finds a break, and both "ones" and "twos" will be added

Eliminating only Certain Dates from Java Using Switch Statements [duplicate]

This question already has answers here:
Excluding Dates from Print Loop
(2 answers)
Closed 10 years ago.
I have almost completed my code; however, instead of eliminating solely the dates which fall on Friday and also happen to be the 13th day of the month, it has eliminated every 13th submission. I thought that:
int friday = ((startingDayOfWeek+dayOfYear) % 7);
if (dayOfYear != 13 && friday != 5)
System.out.println(month + "/" + dayOfYear);
dayOfYear++;
Would work, but it is eliminating them all. I understand that there are easier ways to accomplish this; however, I am required to do it in this manner. Here is the full code:
public class LoopDate {
public static void main(String[] args) {
//Denotes that Tuesday is the first day of 2013
int startingDayOfWeek = 2;
int year = 2013;
int numDays = 0;
for (int month = 1; month <= 12; month++) {
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if (((year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0))
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
int dayOfYear = 1;
while (dayOfYear <= numDays)
{
int friday = ((startingDayOfWeek+dayOfYear) % 7);
if (dayOfYear != 13 && friday != 5)
System.out.println(month + "/" + dayOfYear);
dayOfYear++;
}
}
}
}
Your boolean logic is wrong.
if (dayOfYear != 13 && friday != 5)
Should be:
if (dayOfYear != 13 || friday != 5)
You are doing the negative check of "is it friday the 13th". When converting a positive check into a negative check, you need to NOT the conditions (done), and flip the operators (OR becomes AND, AND becomes OR).
Also, when dealing with boolean logic like that, I usually give the segments meaningful names. It 'costs' a variable, but can save you countless hours later on!
boolean isFridayThe13th = (dayOfYear == 13 && friday == 5);
if (!isFridayThe13th) ...

Printing Ordered Dates from a Switch Statement

I am attempting to write a loop that will get its values from my switch statement. I want it to print out the dates in order each on their own line, such as:
1/1
1/2
1/3
...
12/31
I have attempted to write it myself, but I'm not entirely sure how to assign the months in correct order to the 3 cases I have in the switch statement.
Below is the switch statement I am using:
int month = 0;
int yearInt = year;
int totalDays = 0;
switch (month) {
case 1:
totalDays = 30;
break;
case 2:
if (((yearInt % 4 == 0) && !(yearInt % 100 == 0))
|| (yearInt % 400 == 0))
totalDays = 29;
else
totalDays = 28;
break;
default:
totalDays = 31;
break;
Like this? January is assumed 1
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
totalDays = 31;
break;
case 2:
if (((yearInt % 4 == 0) && !(yearInt % 100 == 0))
|| (yearInt % 400 == 0))
totalDays = 29;
else
totalDays = 28;
break;
default:
totalDays = 30;
break;
Note that the fall-through syntax I used is sometimes considered harmfull
You can as well get the desired result using built-in methods:
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, yearInt);
c.set(Calendar.MONTH, month);
int totalDays = c.getActualMaximum(Calendar.DAY_OF_MONTH);
Note: Value of month starts from 0 (0 for January, 1 for February..).

Categories

Resources