Doomsday rule: Difference between revisions

From Rosetta Code
Content added Content deleted
mNo edit summary
No edit summary
Line 57: Line 57:
*   [[wp:Doomsday rule|Doomsday rule]]
*   [[wp:Doomsday rule|Doomsday rule]]
*   [https://www.archim.org.uk/eureka/archive/Eureka-36.pdf Tomorrow is the Day After Doomsday (p.28)]
*   [https://www.archim.org.uk/eureka/archive/Eureka-36.pdf Tomorrow is the Day After Doomsday (p.28)]




=={{header|Julia}}==
<lang julia>module DoomsdayRule
export get_weekday

const weekdaynames = ["Sunday", "Monday","Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
# For months 1 through 12, the date of the first doomsday that month.
const leapyear_firstdoomsdays = [4, 1, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5]
const nonleapyear_firstdoomsdays = [3, 7, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5]

"""
get_weekday(year::Int, month::Int, day::Int)::String

Return the weekday of a given date in past or future.
Uses Conway's doomsday rule (see also https://en.wikipedia.org/wiki/Doomsday_rule)
"""
function get_weekday(year::Int, month::Int, day::Int)::String
# sanity checks
@assert 1582 <= year <= 9999 "Invalid year (should be after 1581 and 4 digits)"
@assert 1 <= month <= 12 "Invalid month, should be between 1 and 12"
@assert 1 <= day <= 31 "Invalid day, should be between 1 and 31"

# Conway's doomsday algorithm
c, r = divrem(year, 100)
canchor = (5 * (c % 4) + 2) % 7 # anchor for centiry
doomsday = ((r ÷ 12) + (r % 12) + ((r % 12) ÷ 4) + canchor) % 7
anchorday = (year % 4 != 0) || (r == 0 && year % 400 == 0) ? # leap year determination
nonleapyear_firstdoomsdays[month] : leapyear_firstdoomsdays[month]
weekday = (doomsday + day - anchorday + 7) % 7 + 1
return weekdaynames[weekday]
end

end # module

using .DoomsdayRule

println("January 6, 1800 was on a ", get_weekday(1800, 1, 6))
println("March 29, 1875 was on a ", get_weekday(1875, 3, 29))
println("December 7, 1915 was on a ", get_weekday(1915, 12, 7))
println("December 23, 1970 was on a ", get_weekday(1970, 12, 23))
println("May 14, 2043 will be on a ", get_weekday(2043, 5, 14))
println("February 12, 2077 will be on a ", get_weekday(2077, 2, 12))
println("April 2, 2101 will be on a ", get_weekday(2101, 4, 2))
</lang>{{out}}
<pre>
January 6, 1800 was on a Sunday
March 29, 1875 was on a Monday
December 7, 1915 was on a Tuesday
December 23, 1970 was on a Wednesday
May 14, 2043 will be on a Thursday
February 12, 2077 will be on a Friday
April 2, 2101 will be on a Saturday
</pre>

Revision as of 09:37, 1 June 2021

Doomsday rule is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
About the task

John Conway (1937-2020), was a mathemetician who also invented several mathematically oriented computer pastimes, such as the famous Game of Life cellular automaton program. Dr. Conway invented a simple algorithm for finding the day of the week, given any date. The algorithm was based opon calculating the distance of a given date from certain "anchor days" which follow a pattern for the day of the week upon which they fall.

Algorithm

The formula is calculated assuming that Sunday is 0, Monday 1, and so forth with Saturday 7, and

   anchorday = (Tuesday(or 2) + 5(y mod 4) + 4(y mod 100) + 6(y mod 400)) % 7

which, for 2021, is 0 (Sunday).

To calculate the day of the week, we then count days from a close doomsday, with these as charted here by month, then add the doomsday for the year, then get the remainder after divding by 7. This should give us the number corresponding to the day of the week for that date.

   Month	        Doomsday Dates for Month
   --------------------------------------------
   January (common years)   3, 10, 17, 24, 31
   January (leap years)     4, 11, 18, 25
   February (common years)  7, 14, 21, 28
   February (leap years)    1, 8, 15, 22, 29
   March                    7, 14, 21, 28
   April                    4, 11, 18, 25
   May                      2, 9, 16, 23, 30
   June                     6, 13, 20, 27
   July                     4, 11, 18, 25
   August                   1, 8, 15, 22, 29
   September                5, 12, 19, 26
   October                  3, 10, 17, 24, 31
   November                 7, 14, 21, 28
   December                 5, 12, 19, 26
Task

Given the following dates:

  •   1800-01-06 (January 6, 1800)
  •   1875-03-29 (March 29, 1875)
  •   1915-12-07 (December 7, 1915)
  •   1970-12-23 (December 23, 1970)
  •   2043-05-14 (May 14, 2043)
  •   2077-02-12 (February 12, 2077)
  •   2101-04-02 (April 2, 2101)


Use Conway's Doomsday rule to calculate the day of the week for each date.

see also



Julia

<lang julia>module DoomsdayRule export get_weekday

const weekdaynames = ["Sunday", "Monday","Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

  1. For months 1 through 12, the date of the first doomsday that month.

const leapyear_firstdoomsdays = [4, 1, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5] const nonleapyear_firstdoomsdays = [3, 7, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5]

"""

   get_weekday(year::Int, month::Int, day::Int)::String

Return the weekday of a given date in past or future. Uses Conway's doomsday rule (see also https://en.wikipedia.org/wiki/Doomsday_rule) """ function get_weekday(year::Int, month::Int, day::Int)::String

   # sanity checks
   @assert 1582 <= year <= 9999 "Invalid year (should be after 1581 and 4 digits)"
   @assert 1 <= month <= 12 "Invalid month, should be between 1 and 12"
   @assert 1 <= day <= 31 "Invalid day, should be between 1 and 31"
   # Conway's doomsday algorithm
   c, r = divrem(year, 100)
   canchor = (5 * (c % 4) + 2) % 7  # anchor for centiry
   doomsday = ((r ÷ 12) + (r % 12) + ((r % 12) ÷ 4) + canchor) % 7
   anchorday = (year % 4 != 0) || (r == 0 && year % 400 == 0) ?  # leap year determination
                nonleapyear_firstdoomsdays[month] : leapyear_firstdoomsdays[month]
   weekday = (doomsday + day - anchorday + 7) % 7 + 1
   return weekdaynames[weekday]

end

end # module

using .DoomsdayRule

println("January 6, 1800 was on a ", get_weekday(1800, 1, 6)) println("March 29, 1875 was on a ", get_weekday(1875, 3, 29)) println("December 7, 1915 was on a ", get_weekday(1915, 12, 7)) println("December 23, 1970 was on a ", get_weekday(1970, 12, 23)) println("May 14, 2043 will be on a ", get_weekday(2043, 5, 14)) println("February 12, 2077 will be on a ", get_weekday(2077, 2, 12)) println("April 2, 2101 will be on a ", get_weekday(2101, 4, 2))

</lang>

Output:
January 6, 1800 was on a Sunday
March 29, 1875 was on a Monday
December 7, 1915 was on a Tuesday
December 23, 1970 was on a Wednesday
May 14, 2043 will be on a Thursday
February 12, 2077 will be on a Friday
April 2, 2101 will be on a Saturday