Choinka programisty Ruby
Czy programiści Ruby 💎 programują swoje choinki 🎄 święteczne?
Słowo się rzekło, czas go dotrzymać… ⏰
Powracamy do tematu wyliczania daty Świąt Wielkanocnych. Zgodnie z obietnicą daną w artykule Ruby Easter date, gdzie pisaliśmy o rozwiązaniu Gaussa, tym razem wykorzystamy metodę Meeusa/Jonesa/Butchera. Przyjrzyjmy się więc jej bliżej. Została przedstawiona przez Jeana Meeusa w 1991 roku. W książce, swojego autorstwa “Astronomical Algorithms”, zawarł sposób na wyliczenie daty Niedzieli Wielkanocnej. Uwzględnił zarówno algorytm dla kalendarza gregoriańskiego, jak i juliańskiego.
Metody opisane przez Meeusa są uniwersalne. Nie wymagają od nas żadnych założeń czy wyjątków. Jednakże, jak się przekonacie, wymagają więcej obliczeń.
Dla każdego kalendarza w pierwszej kolejności opiszemy poszczególne kroki metody. Następnie zaproponujemy przykładowy program w języku Ruby.
Nasz algorytm polega na wyliczeniu pewnej grupy wartości: a, b, c, d, e, f, g, h, i, k, l, m, p. Z ich pomocą wyznaczymy dzień i miesiąc święta.
Jak policzyć potrzebne wielkości? Poniżej mała pomoc:
Wybierzmy rok dla którego chcemy poznać datę. 😉
Nie pozostaje nam nic innego jak policzyć odpowiednio:
Program w Ruby może wyglądać:
require 'date'
def gregorian_easter_date(year)
a = year % 19
b = (year / 100).floor
c = year % 100
d = (b / 4).floor
e = b % 4
f = ((b + 8) / 25).floor
g = ((b - f + 1) / 3).floor
h = (19 * a + b - d - g + 15) % 30
i = (c / 4).floor
k = c % 4
l = (32 + 2 * e + 2 * i - h - k) % 7
m = ((a + 11 * h + 22 * l) / 451).floor
q = (h + l - 7 * m + 114)
day = q % 31 + 1
month = (q / 31).floor
Date.new(year, month, day)
end
Jak działa powyższa metoda? Przekonajmy się i wyliczmy kilka dat.
3.1.0 :020 > gregorian_easter_date(2022)
=> #<Date: 2022-04-17 ((2459687j,0s,0n),+0s,2299161j)>
3.1.0 :021 > gregorian_easter_date(2021)
=> #<Date: 2021-04-04 ((2459309j,0s,0n),+0s,2299161j)>
3.1.0 :022 > gregorian_easter_date(2023)
=> #<Date: 2023-04-09 ((2460044j,0s,0n),+0s,2299161j)>
3.1.0 :023 > gregorian_easter_date(1900)
=> #<Date: 1900-04-15 ((2415125j,0s,0n),+0s,2299161j)>
3.1.0 :024 > gregorian_easter_date(1967)
=> #<Date: 1967-03-26 ((2439576j,0s,0n),+0s,2299161j)>
Daty te łatwo będziemy mogli sprawdzić.
Ten algorytm jest zdecydowanie krótszy. Wyliczamy tylko pięć wielkości: a, b, c, d, e za pomocą, których wyznaczymy dzień i miesiąc. Szczegóły poniżej:
Teraz już możemy policzyć:
require 'date'
def julian_easter_date(year)
a = year % 4
b = year % 7
c = year % 19
d = (19 * c + 15) % 30
e = (2 * a + 4 * b - d + 34) % 7
day = (d + e + 114) % 31 + 1
month = ((d + e + 114) / 31).floor
Date.new(year, month, day)
end
Jako ciekawostka! Kalendarz juliański obowiązuje w Kościele Prawosławnym. Znając już datę świąt w obrządku prawosławnym możemy dowiedzieć się na jaki dzień i miesiąc kalendarza gregoriańskiego przypada uroczystość. Wystarczy, do uzyskanego wyniku, dodać 13. Zasada ta działa tylko dla lat 1900 - 2100.
Wyniki przedstawiają się następująco:
3.1.0 :035 > julian_easter_date(2022)
=> #<Date: 2022-04-11 ((2459681j,0s,0n),+0s,2299161j)>
3.1.0 :036 > julian_easter_date(2021)
=> #<Date: 2021-04-19 ((2459324j,0s,0n),+0s,2299161j)>
3.1.0 :037 > julian_easter_date(2023)
=> #<Date: 2023-04-03 ((2460038j,0s,0n),+0s,2299161j)>
3.1.0 :038 > julian_easter_date(1900)
=> #<Date: 1900-04-09 ((2415119j,0s,0n),+0s,2299161j)>
3.1.0 :039 > julian_easter_date(1967)
=> #<Date: 1967-04-17 ((2439598j,0s,0n),+0s,2299161j)>
Życzymy Wam miłej zabawy z programowaniem.
🐏 🐰 🐇 🥚 🐤 🐣 🐥
Zostaw komentarz