Doomsday rule: Difference between revisions

Add C# implementation
(Added Easylang)
(Add C# implementation)
 
(6 intermediate revisions by 6 users not shown)
Line 426:
February 12, 2077 will be on a Friday.
April 2, 2101 will be on a Saturday.</pre>
 
 
=={{header|C#}}==
{{trans|Java}}
<syntaxhighlight lang="C#">
using System;
 
class Doom {
public static void Main(string[] args) {
Date[] dates = {
new Date(1800,1,6),
new Date(1875,3,29),
new Date(1915,12,7),
new Date(1970,12,23),
new Date(2043,5,14),
new Date(2077,2,12),
new Date(2101,4,2)
};
foreach (Date d in dates)
Console.WriteLine($"{d.Format()}: {d.Weekday()}");
}
}
 
class Date {
private int year, month, day;
private static readonly int[] leapDoom = {4,1,7,4,2,6,4,1,5,3,7,5};
private static readonly int[] normDoom = {3,7,7,4,2,6,4,1,5,3,7,5};
public static readonly string[] weekdays = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public bool IsLeapYear() {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
public string Format() {
return $"{month:00}/{day:00}/{year:0000}";
}
public string Weekday() {
int c = year / 100;
int r = year % 100;
int s = r / 12;
int t = r % 12;
int cAnchor = (5 * (c % 4) + 2) % 7;
int doom = (s + t + t / 4 + cAnchor) % 7;
int anchor =
IsLeapYear() ? leapDoom[month - 1] : normDoom[month - 1];
return weekdays[(doom + day - anchor + 7) % 7];
}
}
</syntaxhighlight>
{{out}}
<pre>
01/06/1800: Monday
03/29/1875: Monday
12/07/1915: Tuesday
12/23/1970: Wednesday
05/14/2043: Thursday
02/12/2077: Friday
04/02/2101: Saturday
 
</pre>
 
=={{header|C++}}==
Line 614 ⟶ 688:
.
func weekday year month day .
leapdoom[] = [ 4 1 7 2 4 6 4 1 5 3 7 5 ]
normdoom[] = [ 3 7 7 4 2 6 4 1 5 3 7 5 ]
c = year div 100
Line 622 ⟶ 695:
c_anchor = (5 * (c mod 4) + 2) mod 7
doom = (s + t + (t div 4) + c_anchor) mod 7
anchor = normdoom[month]
if leap year = 1
if leap anchoryear = leapdoom[1 and month] <= 2
anchor = (anchor + 1) mod1 7
else
anchor = normdoom[month]
.
return (doom + day - anchor + 7) mod 7 + 1
Line 731 ⟶ 803:
M= 2 D= 12 Y= 2077 DAY=FRIDAY
M= 4 D= 2 Y= 2101 DAY=SATURDAY</pre>
 
=={{header|Fortran}}==
<syntaxhighlight lang="FORTRAN">
program someday ! Calculates the day that a week falls on
use datestuff
implicit none
!
! PARAMETER definitions
!
integer , parameter :: numdates = 7
!
! Local variable declarations
!
character(30) , dimension(numdates) , save :: date_string
integer , dimension(numdates) , save :: day
character(9) , dimension(numdates) , save :: days
integer :: j
integer :: k
integer , dimension(numdates) , save :: month
integer , dimension(numdates) , save :: year
!
data days/'Monday ' , 'Tuesday ' , 'Wednesday' , 'Thursday ' , &
&'Friday ' , 'Saturday ' , 'Sunday '/
data month/01 , 03 , 12 , 12 , 05 , 02 , 04/
data day/06 , 29 , 07 , 23 , 14 , 12 , 02/
data year/1800 , 1875 , 1915 , 1970 , 2043 , 2077 , 2101/
data date_string/'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)'/ !
!*Code
 
print *
do j = 1 , numdates
k = get_the_day(day(j) , month(j) , year(j))
print '(a, t31,1a1,1x,a)' , date_string(j) , ':' , days(k)
end do
end program someday
module datestuff
implicit none
public :: get_the_day
private :: get_anchor_day , gregorian_leap_year
!
enum , bind(c) ! Use enums to get greater clarity in the code
enumerator :: january = 1 , february , march , april , may , &
& june , july , august , september , october , november ,&
& december
end enum
enum , bind(c)
enumerator :: sunday = 0 , monday , tuesday , wednesday , &
& thursday , friday , saturday
end enum
contains
!
pure function gregorian_leap_year(year) result(answer) ! Tests if the year is a leap year
!
! Function and Dummy argument declarations
!
logical :: answer
integer , intent(in) :: year
!
answer = .false. ! Set default to not a leap year
if( mod(year , 4)==0 )answer = .true. ! Year divisible by 4 = leap year
if( mod(year , 100)==0 )then
if( mod(year , 400)==0 )then ! Year divisible by 400 = century year that is leap year
answer = .true.
else
answer = .false. ! Century years are not leap years
end if
end if
end function gregorian_leap_year
!
pure function get_anchor_day(year) result(answer) ! Returns Anchor Days in doomsday calculation
!Note: The days start as Monday = 1, Tuesday =2, etc until Sunday = 7
!The Doomsday rule, Doomsday algorithm or Doomsday method is an algorithm of determination of the day of the week for a given date.
!It provides a perpetual calendar because the Gregorian calendar moves in cycles of 400 years.
!It takes advantage of each year having a certain day of the week upon which certain easy-to-remember dates,
!called the doomsdays, fall; for example, the last day of February, 4/4, 6/6, 8/8, 10/10, and 12/12 all occur
! on the same day of the week in any year. Applying the Doomsday algorithm involves three steps: Determination of the anchor day
! for the century, calculation of the anchor day for the year from the one for the century, and selection of the closest date
! out of those that always fall on the doomsday, e.g., 4/4 and 6/6, and count of the number of days (modulo 7) between that
! date and the date in question to arrive at the day of the week. The technique applies to both the Gregorian calendar and the
! Julian calendar, although their doomsdays are usually different days of the week.
!
! Function and Dummy argument declarations
!
integer :: answer
integer , intent(in) :: year
!
! Local variable declarations
!
integer :: diffyear
integer :: div12
integer :: numyears
integer :: temp1
!
! End of declarations
!*Code
numyears = mod(year , 100) ! Get number of years greater than century
 
temp1 = year - numyears ! Turn into a century year
temp1 = mod(temp1 , 400) ! Now mod 400 to get base year for anchor day
select case(temp1) ! Select the base day
case(0)
answer = tuesday
case(100)
answer = sunday
case(200)
answer = friday
case(300)
answer = wednesday
case default ! Anything else is an error
ERROR Stop 'Bad Anchor Day' ! Finish with error
end select
!
!Calculate the doomsday of any given year
!
div12 = int(numyears/12) ! Get number of times 12 goes into year
temp1 = mod(numyears , 12) ! Get the remainer
diffyear = int(temp1/4) ! Div 4 (magic algorithm)
answer = diffyear + div12 + answer + temp1
answer = mod(answer , 7)
end function get_anchor_day ! Note: The days start as Sunday = 0, Monday = 1, Tuesday =2, etc until Saturda
!
pure function get_the_day(day , month , year) result(answer)
! Note: The days start as Sunday = 0, Monday = 1, Tuesday =2, etc until Saturday = 6
!
! Function and Dummy argument declarations
integer :: answer
integer , intent(in) :: day
integer , intent(in) :: month
integer , intent(in) :: year
!
! Local variable declarations
integer :: closest
integer :: doomsday
integer :: temp1
integer :: temp2
integer :: up_or_down
!
! End of declarations
!
! There are doomsdays in every month, so we know what month it is ...
! We need to find the doomsday in the relevant month
select case(month) ! Scratch Variables
case(january)
closest = merge(4,3,gregorian_leap_year(year)) ! Use merge as a ternary
case(february)
closest = merge(29,28,gregorian_leap_year(year)) ! Use merge as a ternary
case(march)
closest = 7
case(april)
closest = 4
case(may)
closest = 9
case(june)
closest = 6
case(july)
temp1 = abs(4 - day)
temp2 = abs(11 - day)
closest = merge(4,11,temp1<temp2) ! Use merge as a ternary
case(august)
closest = 8
case(september)
closest = 5
case(october)
temp1 = abs(10 - day)
temp2 = abs(31 - day)
closest = merge(10,31,temp1<temp2) ! Use merge as a ternary
case(november)
closest = 7
case(december)
closest = 12
case default
ERROR Stop 'Error in get the day' ! Stop on error
end select
!
! Ok now we get the doomsday in question - i.e. Monday, Tuesday for this year
doomsday = get_anchor_day(year) ! Get this years doomsday
! If closest day is less we need to count down, if it is bigger we count up
 
if( closest>day )then
up_or_down = -7
else if( closest<day )then
up_or_down = 7
else
up_or_down = 0 ! The days are equal. Set to zero so no counting needed
end if
temp1 = closest ! Set temp var to closest doomsday
if( up_or_down>0 )then
do while ( temp1<=day )
temp2 = temp1
temp1 = temp1 + up_or_down ! Count in sevens to the final
end do
temp1 = day - temp2
temp1 = (doomsday + 7) + temp1
else if( up_or_down<0 )then
do while ( temp1>=day )
temp2 = temp1
temp1 = temp1 + up_or_down ! Count in sevens to the final
end do
temp1 = temp2 - day ! See how far away I am from this day
temp1 = (doomsday + 7) - temp1 ! Subtract the difference in days from the known doomsday
else
temp1 = doomsday ! It fell on the doomsday
end if
answer = mod(temp1 , 7) ! Turn Sundays into Zeros
end function get_the_day
!
end module datestuff
!
</syntaxhighlight>
{{out}}
<pre>
1800-01-06 (January 6, 1800) : Monday
1875-03-29 (March 29, 1875) : Monday
1915-12-07 (December 7, 1915) : Tuesday
1970-12-23 (December 23, 1970): Wednesday
2043-05-14 (May 14, 2043) : Thursday
2077-02-12 (February 12, 2077): Friday
2101-04-02 (April 2, 2101) : Saturday
</pre>
 
=={{header|FreeBASIC}}==
Line 1,505 ⟶ 1,799:
→ d m y
« y DUP 100 MOD 4 400 IFTE MOD
{ 3 7 } { 4 1 } IFTE { 7 4 2 6 4 1 5 3 7 5 } + +
m GET 7 d + SWAP - 7 MOD
7 MOD 2 5 y 4 MOD * + 4 y 100 MOD * + 6 y 400 MOD * + 7 MOD
7 MOD + 7 MOD
{ "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Satursday" }
SWAP 1 + GET
» » '<span style="color:blue">WKDAY</span>' STO
 
{ 6.0118011800 29.031875 7.121915 23.12197 14.052043 12.022077 2.042101 } 1 « <span style="color:blue">WKDAY</span> » DOLIST
{{out}}
<pre>
1: { "Monday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Satursday" }
1: { 1 1 2 3 4 5 6 }
</pre>
 
Line 1,571 ⟶ 1,867:
2077-02-12: Friday
2101-04-02: Saturday
</pre>
 
=={{header|Scala}}==
{{trans|Java}}
<syntaxhighlight lang="Scala">
object Doom extends App {
val dates = Array(
new Date(1800, 1, 6),
new Date(1875, 3, 29),
new Date(1915, 12, 7),
new Date(1970, 12, 23),
new Date(2043, 5, 14),
new Date(2077, 2, 12),
new Date(2101, 4, 2)
)
 
dates.foreach(d => println(s"${d.format}: ${d.weekday}"))
}
 
class Date(val year: Int, val month: Int, val day: Int) {
import Date._
 
def isLeapYear: Boolean = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
 
def format: String = f"$month%02d/$day%02d/$year%04d"
 
def weekday: String = {
val c = year / 100
val r = year % 100
val s = r / 12
val t = r % 12
 
val cAnchor = (5 * (c % 4) + 2) % 7
val doom = (s + t + t / 4 + cAnchor) % 7
val anchor = if (isLeapYear) leapdoom(month - 1) else normdoom(month - 1)
 
weekdays((doom + day - anchor + 7) % 7)
}
}
 
object Date {
private val leapdoom = Array(4, 1, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5)
private val normdoom = Array(3, 7, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5)
val weekdays = Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
}
</syntaxhighlight>
{{out}}
<pre>
01/06/1800: Monday
03/29/1875: Monday
12/07/1915: Tuesday
12/23/1970: Wednesday
05/14/2043: Thursday
02/12/2077: Friday
04/02/2101: Saturday
 
</pre>
 
Line 1,723 ⟶ 2,075:
{{libheader|Wren-date}}
We only use the above module to check the dates of the week given by Conway's method. The latter are worked out from scratch.
<syntaxhighlight lang="ecmascriptwren">import "./date" for Date
 
var days = ["Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"]
337

edits