Problem z zadaniem SPOJ FR_15_06 - Kalendarz

0

Witam, czy mógłby ktoś podpowiedzieć gdzie w kodzie jest błąd, wydaje mi się że wyniki z programu są dobre.

#include <iostream>

void moveDay(uint8_t& week_, const int days)
{
    const uint8_t monday = 0x40,
                  sunday = 0x01;

    for (int i = 0; i < days; i++) {
        if (week_ & sunday) {
            week_ = monday;
            continue;
        }
        week_ >>= 1;
    }
}

void checkYear(const int& year_, uint8_t& week_)
{
    if (!(year_ % 400)) {
        moveDay(week_, 2);
        return;
    }
    if (!(year_ % 4)) {
        if (year_ % 100) {
            moveDay(week_, 2);
            return;
        }
    }
    moveDay(week_, 1);
}

int main()
{
    int t;

    std::cin >> t;
    for (int i = 0; i < t; i++) {
        int year_input, year = 1, count = 0;
        uint8_t week_a1 = 0x40, week_b1 = 0x40;
        uint8_t week_a2,        week_b2;

        std::cin >> year_input;
        do {
            checkYear(year, week_a1);
            checkYear(++year, week_b1);
        } while (year < year_input);
        week_a2 = week_a1;
        week_b2 = week_b1;
        do {
            count++;
            checkYear(year, week_a2);
            checkYear(++year, week_b2);
        } while (   !(week_a1 & week_a2)
                 || !(week_b1 & week_b2));
        std::cout << count << std::endl;
    }
}
0

Strasznie przekombinowane.

Masz tu funkcję, która zwraca numer dnia w tygodniu (0 = niedziela, 1 = poniedziałek, ..., 6 = sobota).
Najpierw obliczasz pierwszy i ostatni dzień dla wprowadzonego roku, a później w pętli dla każdego kolejnego roku sprawdzasz pierwszy i ostatni dzień tego roku i porównujesz do tego wprowadzonego. Jeśli obydwie pary dni odpowiednio pasują do siebie, to wyświetlasz obliczoną różnicę w latach.

int weekDay(int d, int m, int y)
{
    return (d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 - y / 100 + y / 400) % 7;
}
1

https://godbolt.org/z/WxEoMv4v7 - dane testowe weryfikowałem w kalendarzu komputera i jeszce std::mktime

constexpr bool isLeapYear(int year)
{
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

constexpr int YearSize = 365;
constexpr int LeapYearSize = YearSize + 1;
constexpr int DaysInWeek = 7;

constexpr int nextYearWeekDayCorrection(int year)
{
    if (isLeapYear(year)) {
        return LeapYearSize % DaysInWeek;
    }
    return YearSize % DaysInWeek;
}

constexpr int nextMatchingYear(const int initialYear)
{
    auto year = initialYear;
    const auto findNextLeap = isLeapYear(year);
    auto diff = nextYearWeekDayCorrection(year);
    ++year;
    while (findNextLeap != isLeapYear(year) || diff != 0) {
        diff = (diff + nextYearWeekDayCorrection(year)) % DaysInWeek;
        ++year;
    }
    return year;
}

Można stabilizować wszystkie możliwe wyniki za pomocą constexpr (400 możliwości), ale nie bedę mącił za bardzo.

Disclaimer: kod korzysta z C++17, a z tego co pamiętam SPOJ pozwala na C++14.

1 użytkowników online, w tym zalogowanych: 0, gości: 1