Wzór Gaussa bez pętli
Kalendarz krok po kroku: święta - Podstawy C++ (C++)
Gauss zamienił szukanie niedzieli na rachunek. e = (2 * b + 4 * c + 6 * d + 5) % 7 (b = y % 4, c = y % 7) to liczba dni od pełni plus jeden do niedzieli, więc Wielkanoc to 22 + d + e marca albo d + e - 9 kwietnia. Dwa wyjątki są tu zapisane wprost jako gotowe daty (19 i 18 kwietnia). Program porównuje wynik pętli i wzoru: są takie same.
#include <iostream>
using namespace std;
// swieta stale: dzien, miesiac i nazwa (bez polskich liter - konsola)
const int FIXED = 10;
int fixedDay[FIXED] = {1, 6, 1, 3, 15, 1, 11, 24, 25, 26};
int fixedMonth[FIXED] = {1, 1, 5, 5, 8, 11, 11, 12, 12, 12};
char fixedName[FIXED][28] = {"Nowy Rok", "Trzech Kroli", "Swieto Pracy",
"Swieto Konstytucji", "Wniebowziecie NMP",
"Wszystkich Swietych", "Swieto Niepodleglosci",
"Wigilia", "Boze Narodzenie", "Drugi dzien Swiat"};
// data jako 5.04 (miesiac zawsze dwiema cyframi)
void printDate(int d, int m) {
cout << d << "." << (m < 10 ? "0" : "") << m;
}
// numer swieta stalego w tablicy albo -1, gdy to zwykly dzien
int fixedHoliday(int d, int m, int y) {
for (int i = 0; i < FIXED; i++) {
if (fixedDay[i] == d && fixedMonth[i] == m) {
if (i == 7 && y < 2025) {
return -1; // Wigilia jest wolna od 2025 roku
}
return i;
}
}
return -1;
}
bool isLeap(int y) {
return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
}
int daysInMonth(int m, int y) {
int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (m == 2 && isLeap(y)) {
return 29;
}
return days[m - 1];
}
// dzien tygodnia: 0 = poniedzialek, ..., 6 = niedziela
// liczymy dni od 1 stycznia 1900 (to byl poniedzialek)
int weekday(int d, int m, int y) {
int total = 0;
for (int year = 1900; year < y; year++) {
total += isLeap(year) ? 366 : 365;
}
for (int month = 1; month < m; month++) {
total += daysInMonth(month, y);
}
total += d - 1;
return total % 7;
}
// liczba zlota: miejsce roku w 19-letnim cyklu Ksiezyca (0..18)
int golden(int y) {
return y % 19;
}
// o ile dni po 21 marca wypada wiosenna pelnia (lata 1900-2099)
int moonOffset(int y) {
return (19 * golden(y) + 24) % 30;
}
// Wielkanoc: pierwsza niedziela PO wiosennej pelni
// wynik jako jedna liczba: miesiac * 100 + dzien (405 = 5 kwietnia)
int easterLoop(int y) {
int offset = moonOffset(y);
// dwa wyjatki: pelnia cyklu nie moze wypasc za pozno
if (offset == 29) {
offset = 28;
} else if (offset == 28 && golden(y) > 10) {
offset = 27;
}
int d = 21 + offset;
int m = 3;
if (d > 31) {
d -= 31;
m = 4;
}
int w = weekday(d, m, y);
do {
d++;
if (m == 3 && d > 31) {
d = 1;
m = 4;
}
w = (w + 1) % 7;
} while (w != 6);
return m * 100 + d;
}
// wzor Gaussa (lata 1900-2099): same dzielenia, bez petli
int easterGauss(int y) {
int a = y % 19;
int b = y % 4;
int c = y % 7;
int d = (19 * a + 24) % 30;
int e = (2 * b + 4 * c + 6 * d + 5) % 7;
if (d == 29 && e == 6) {
return 419;
}
if (d == 28 && e == 6 && a > 10) {
return 418;
}
if (22 + d + e <= 31) {
return 300 + 22 + d + e;
}
return 400 + d + e - 9;
}
void printEaster(int e) {
printDate(e % 100, e / 100);
}
int main() {
for (int y = 2024; y <= 2030; y++) {
cout << y << ": petla ";
printEaster(easterLoop(y));
cout << ", Gauss ";
printEaster(easterGauss(y));
cout << endl;
}
return 0;
}Ładowanie interaktywnego edytora... Jeśli się nie pojawi, włącz JavaScript.
Wszystkie lekcje kursu Podstawy C++·Zaloguj się, aby zapisać postęp na koncie.