Chase Burleson
Chase Burleson

Reputation: 43

For a given date, calculate which day of the week it is on

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

Answers (2)

trincot
trincot

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

formula for calculating β„Ž

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

Transation to MARIE

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

Janet gutmont
Janet gutmont

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

Related Questions