Reputation: 43
A homework assignment includes this task:
The user should input a date, like the date of their birth, and the program should calculate and display which day of the week this date corresponds to.
Hint: make use of Zeller's rule
I guess the user should input the date in a XX/XX/XXXX format, but what about the calculation and displaying the day?
Also, how should I handle the user input? Should I use three variables for input or just ask for the date at once?
Upvotes: 2
Views: 173
Reputation: 350252
As to getting the input, I would go with asking three numerical inputs. If you would ask the input as a string, realise that the user must then enter and submit each character separately, which doesn't seem that user-friendly. So I would execute three Input
instructions one for each date part.
For the algorithm, Wikipedia has the following on Zeller's congruence:
For the Gregorian calendar, Zeller's congruence is
here
- β is the day of the week (0 = Saturday, 1 = Sunday, 2 = Monday, ..., 6 = Friday)
- π is the day of the month
- π is the month (3 = March, 4 = April, 5 = May, ..., 14 = February)
- πΎ the year of the century (π¦πππ mod 100).
- π½ is the zero-based century (actually βπ¦πππ/100β) For example, the zero-based centuries for 1995 and 2000 are 19 and 20 respectively (not to be confused with the common ordinal century enumeration which indicates 20th for both cases).
- β...β is the floor function or integer part
- mod is the modulo operation or remainder after division
Note: In this algorithm January and February are counted as months 13 and 14 of the previous year. E.g. if it is 2 February 2010 (02/02/2010 in DD/MM/YYYY), the algorithm counts the date as the second day of the fourteenth month of 2009 (02/14/2009 in DD/MM/YYYY format)
To avoid a negative dividend when calculating the final (mod 7) result, the same article suggests to replace -2J
with +5J
. Wikipedia continues with other alternatives which are common for computer implementations, but those involve divisions with relatively larger quotients (like Y/4), which is less interesting for the basic division algorithm we would use in a MARIE implementation.
In a JavaScript implementation the chosen formula would be calculated like this:
function dayOfWeek(day, month, year) {
if (month < 3) {
month += 12;
year -= 1;
}
const K = year % 100;
const J = (year - K) / 100;
const h = (day
+ Math.floor(13 * (month + 1) / 5)
+ K
+ Math.floor(K / 4)
+ Math.floor(J / 4)
+ 5*J) % 7;
return h; // 0 = Saturday
}
// demo run
console.log(dayOfWeek(8, 8, 2024)); // -> 5 == Thursday
Some things to consider here when thinking of translating this code to MARIE:
that 13 * (month + 1) / 5
looks complicated (for MARIE), but when we realise there are only 12 different possible values for month
, we could just use a lookup table for it. And that lookup table could already apply the mod 7
operation. This leads to an array [3, 6, 1, 4, 6, 2, 5, 0, 3, 5, 1, 4]
, where the first entry is for when month
is 3, ...etc.
The Wikpedia formula and JavaScript function return 0 for Saturday, but the ISO 8601 standard has Monday as the first day, so let's adapt the above mentioned lookup table, adding 5 mod 7 so to get a 0 for Monday: [1, 4, 6, 2, 4, 0, 3, 5, 1, 3, 6, 2]
.
5*J
is just J+J+J+J+J
. That means we don't need multiplication, and are left with division and modulo operations. We could think of a divmod
function that would perform a naive division by repeated subtraction. It can assume that the operands are not negative.
Instead of outputting the day number, we could use it as an index in an array of day name strings and print that.
That leads to this JavaScript implementation, getting prepared for a translation to MARIE:
function divmod(dividend, divisor) {
// Assume both arguments are unsigned integers
let quotient = 0,
remainder = dividend;
while (true) {
const diff = remainder - divisor;
if (diff < 0) break;
remainder = diff;
quotient += 1;
}
return [quotient, remainder];
}
const lookup = [1, 4, 6, 2, 4, 0, 3, 5, 1, 3, 6, 2];
function dayOfWeek(day, month, year) {
month -= 3;
if (month < 0) {
month += 12;
year -= 1;
}
const [J, K] = divmod(year, 100);
const K4 = divmod(K, 4)[0];
const J4 = divmod(J, 4)[0];
day += lookup[month];
day += K;
day += K4;
day += J4;
day += J;
day += J;
day += J;
day += J;
day += J;
const h = divmod(day, 7)[1]; // 0 = Monday
return h;
}
function printString(strings, index) {
console.log(strings[index]);
}
const dayNames = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
const dayNum = dayOfWeek(8, 8, 2024);
printString(dayNames, dayNum); // Thursday
Here is the above program converted to MARIE:
/ -------- Main -------------------------------------------------
Input
Store Day
Input
Store Month
Input
Store Year
JnS DayOfWeek
Store StringIndex / 0 = Monday, 1 = Tuesday, ...
Load DayNamesAdr
Store StringsAdr
JnS PrintString / Print "Monday" or "Tuesday", ...
Halt
/ -------- DayOfWeek --------------------------------------------
Day, Dec 1 / Input: For the caller to initialise
Month, Dec 1 / Input: For the caller to initialise
Year, Dec 2000 / Input: For the caller to initialise
Month2, Dec 0 / Local: adapted month number
Year2, Dec 0 / Local: adapted year number
J, Dec 0 / Local
K, Dec 0 / Local
J4, Dec 0 / Local
K4, Dec 0 / Local
WeekDay, Dec 0 / Output: 0 = Monday, 1 = Tuesday, ...
DayOfWeek, Hex 0 / For storing the subroute return address
Load Year
Store Year2
Load Month
Subt Three
Store Month2
SkipCond 000 / If Month2 is >= 0, then don't decrease year
Jump Continue
Add Twelve / Make Month positive
Store Month2
Load Year2 / And decrease Year
Subt One
Store Year2
Continue, Load Year2 / Divide Year2 by 100
Store Dividend
Load Hundred
Store Divisor
JnS DivMod
Store J / J = Year2 / 100
Load Remainder
Store K / K = Year2 % 100
Store Dividend / Divide K by 4
Load Four
Store Divisor
JnS DivMod
Store K4 / K4 = K / 4
Load J / Divide J by 4
Store Dividend
JnS DivMod
Store J4 / J4 = J / 4
Load Month2 / Lookup month in lookup array
Add LookupAdr
Store Month2 / Now Month2 is an address in Lookup array
LoadI Month2 / Sum up all terms
Add Day
Add K
Add K4
Add J4
Add J
Add J
Add J
Add J
Add J
Store Dividend / Apply modulo 7 to the sum
Load Seven
Store Divisor
JnS DivMod
Load Remainder
Store WeekDay / Return that mod 7 result
JumpI DayOfWeek
/ -------- DivMod --------------------------------------------
Dividend, Dec 0 / Input: For the caller to initialise
Divisor, Dec 0 / Input: For the caller to initialise
Quotient, Dec 0 / Output: For the caller to process
Remainder, Dec 0 / Output: For the caller to process
DivMod, Hex 0 / For storing the subroute return address
Load Dividend
Store Remainder
Clear
DivLoop, Store Quotient
Load Remainder
Subt Divisor
SkipCond 000 / If not negative:
Jump DivUpdate / Then continue loop
Load Quotient / If negative: Return with Quotient in AC
JumpI DivMod
DivUpdate, Store Remainder
Load Quotient
Add One
Jump DivLoop
/ -------- PrintString ---------------------------------------
StringsAdr, Hex 0 / Input: For the caller to initialise
StringIndex, Hex 0 / Input: For the caller to initialise
StringAdr, Hex 0 / Local
CharAdr, Hex 0 / Local
PrintString, Hex 0 / For storing the subroute return address
Load StringIndex / Calculate start address of string
Add StringsAdr
Store StringAdr
LoadI StringAdr / Got it
PrintLoop, Store CharAdr
LoadI CharAdr
SkipCond 400 / If character is not 0:
Jump PrintChar / Continue to print it
JumpI PrintString / Else Return
PrintChar, Output
Load CharAdr
Add One
Jump PrintLoop
/ -------- Global Constants ---------------------------------------
One, Dec 1
Three, Dec 3
Four, Dec 4
Seven, Dec 7
Twelve, Dec 12
Hundred, Dec 100
LookupAdr, Adr Lookup
Lookup, Dec 1
Dec 4
Dec 6
Dec 2
Dec 4
Dec 0
Dec 3
Dec 5
Dec 1
Dec 3
Dec 6
Dec 2
DayNamesAdr, Adr FirstDay
FirstDay, Adr Monday
Adr Tuesday
Adr Wednesday
Adr Thursday
Adr Friday
Adr Saturday
Adr Sunday
Monday, Hex 4D / M
Hex 6F / o
Hex 6E / n
Hex 64 / d
Hex 61 / a
Hex 79 / y
Hex 0A / LF
Hex 0
Tuesday, Hex 54 / T
Hex 75 / u
Hex 65 / e
Hex 73 / s
Hex 64 / d
Hex 61 / a
Hex 79 / y
Hex 0A / LF
Hex 0
Wednesday, Hex 54 / W
Hex 65 / e
Hex 64 / d
Hex 6E / n
Hex 65 / e
Hex 73 / s
Hex 64 / d
Hex 61 / a
Hex 79 / y
Hex 0A / LF
Hex 0
Thursday, Hex 54 / T
Hex 68 / h
Hex 75 / u
Hex 72 / r
Hex 73 / s
Hex 64 / d
Hex 61 / a
Hex 79 / y
Hex 0A / LF
Hex 0
Friday, Hex 46 / F
Hex 72 / r
Hex 69 / i
Hex 64 / d
Hex 61 / a
Hex 79 / y
Hex 0A / LF
Hex 0
Saturday, Hex 53 / S
Hex 61 / a
Hex 74 / t
Hex 75 / u
Hex 72 / r
Hex 64 / d
Hex 61 / a
Hex 79 / y
Hex 0A / LF
Hex 0
Sunday, Hex 53 / S
Hex 75 / u
Hex 6E / n
Hex 64 / d
Hex 61 / a
Hex 79 / y
Hex 0A / LF
Hex 0
You can copy this in the MARIE.js simulator and assemble it there, with the output mode set to "UNICODE". When you run it and get the input dialog, make sure to choose "Decimal" as input type. The three inputs are day (1-31), month (1-12), year.
Upvotes: 0
Reputation: 1
i used the algorithm zeller , share my logic in javascript
const weekdayNames = {
1:'lunes',
2:'Martes',
3:'MiΓ©rcoles',
4:'Jueves',
5:'Viernes',
6:'SΓ‘bado',
7:'Domingo',
}
function calculateDate (dd,mm,aaaa){
const day = parseInt((14 - mm) / 12);
const year = aaaa - day;
const month = parseInt(mm + (12 * day) - 2);
const dayResult = parseInt(dd + year + parseInt(year/4) - parseInt(year/100) + parseInt(year/400)+((31*month) / 12)) % 7;
return weekdayNames[dayResult];
}
console.log(calculateDate(6,3,1997));
hope help you
Upvotes: 0