Das Problem mit der Aufgabe über den Kalender.

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
bjoy
User
Beiträge: 6
Registriert: Donnerstag 31. August 2023, 09:24

Leider löst es nicht einmal den ersten vorgegebenen Test :(

Also, die Aufgabe lautet:

Durch die Analyse von Wochenenden und Feiertagen rund um Neujahr und den 1. Mai in Russland ist der Präsident von Flatlandia zu dem Schluss gekommen, dass das übrige Volk drastisch optimiert werden kann. Das Hauptziel besteht darin, sicherzustellen, dass die Bürger nicht mehr als 6 aufeinanderfolgende Arbeitstage im Kalenderjahr haben müssen. Der Präsident hat das Arbeitsministerium angewiesen, einen Zeitplan zur Verlegung von Wochenenden (Samstagen und Sonntagen) zu erstellen, damit die Bürger möglichst viele aufeinanderfolgende freie Tage haben können.

Es ist wichtig zu beachten, dass ein flachländischer Feiertag, der auf ein Wochenende (Samstag oder Sonntag) fällt, automatisch auf den ersten Arbeitstag nach dem Feiertag verschoben wird. Gemäß dem Dekret des Präsidenten kann jedoch jedes Wochenende, unabhängig davon, ob es mit einem Feiertag zusammenfällt oder nicht, auf jeden Arbeitstag verschoben werden. Feiertage werden jedoch niemals verschoben.

Schreiben Sie ein Programm, das dem Arbeitsministerium helfen wird, den erforderlichen Zeitplan zur Verlegung von Wochenenden im kommenden Jahr zu erstellen. Feiertage und Wochenenden aus dem vorherigen und folgenden Jahr sollten nicht berücksichtigt werden. Das Ziel besteht darin, die Anzahl der aufeinanderfolgenden freien Tage in einem Jahr zu maximieren.

Eingabeformat:
Die erste Zeile der Eingabe enthält zwei Zahlen - die Jahreszahl (Y) (2012≤Y≤2050) und der Wochentag für den 1. Januar dieses Jahres (W) (1≤W≤7, von Montag bis Sonntag). In diesem Jahresbereich sind Schaltjahre durch 4 teilbar.
Die zweite Zeile enthält die Anzahl der jährlichen Feiertage (N) in Flatlandia. Jede der folgenden N Zeilen enthält das Datum des nächsten Feiertags im Format DD.MM. Die Feiertagsdaten werden in chronologischer Reihenfolge aufgelistet, und alle Daten sind für das angegebene Jahr gültig und korrekt.

Ausgabeformat:
Geben Sie eine einzelne Zahl aus - die maximal mögliche Anzahl aufeinanderfolgender freier Tage für die Bewohner von Flatlandia im angegebenen Jahr, wenn die Wochenenden so verschoben werden, dass die Anzahl der aufeinanderfolgenden Arbeitstage in diesem Jahr 6 nicht überschreitet.

Beispiel:
Eingabe:
2012 7
1
01.01
Ausgabe:
63

Mein Versuch:

Code: Alles auswählen

import datetime
 
def is_leap_year(year):
    if year % 4 == 0:
        if year % 100 == 0:
            if year % 400 == 0:
                return True
            else:
                return False
        else:
            return True
    else:
        return False
 
def get_weekday(year, month, day):
    date = datetime.date(year, month, day)
    return date.weekday()
 
def get_weekdays_in_year(year):
    weekdays = [0, 0, 0, 0, 0, 0, 0]  # Sunday to Saturday
    for month in range(1, 13):
        days_in_month = 31
        if month == 4 or month == 6 or month == 9 or month == 11:
            days_in_month = 30
        elif month == 2:
            if is_leap_year(year):
                days_in_month = 29
            else:
                days_in_month = 28
        for day in range(1, days_in_month + 1):
            weekday = get_weekday(year, month, day)
            weekdays[weekday] += 1
    return weekdays
 
def get_maximum_consecutive_holidays(year, start_weekday, holidays):
    weekdays = get_weekdays_in_year(year)
    consecutive_holidays = 0
    current_consecutive_holidays = 0
    for holiday in holidays:
        day, month = map(int, holiday.split('.'))
        weekday = get_weekday(year, month, day)
        if weekdays[weekday] == 0:  # Weekday is not already a holiday
            current_consecutive_holidays += 1
        else:
            current_consecutive_holidays = 0
        weekdays[weekday] += 1
        if current_consecutive_holidays > consecutive_holidays:
            consecutive_holidays = current_consecutive_holidays
    return consecutive_holidays
 
 
year, start_weekday = map(int, input().split())
num_holidays = int(input())
holidays = []
for _ in range(num_holidays):
    holiday = input()
    holidays.append(holiday)
 
maximum_consecutive_holidays = get_maximum_consecutive_holidays(year, start_weekday, holidays)
 
 
print(maximum_consecutive_holidays)
Aber ähm, es besteht den ersten Test nicht, bitte hilf mir. Ja, es geht um Russland, entschuldige bitte..
Sirius3
User
Beiträge: 18227
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie hast Du Dir denn den Algorithmus vorgestellt, der das Problem lösen soll?
Bisher sehe ich nur, dass es Code gibt, der die Anzahl an Wochen im Jahr zählt, sehr viel mehr macht get_weekdays_in_year nicht.

Um so eine Aufgabe anzugehen, fängst Du am besten unten an:
1. es braucht eine Funktion, die die Anzahl aufeinanderfolgender freier Tage zählt.
Was soll die Funktion als Input bekommen?
2. eine Liste aller Tage im Jahr und der Information, ob es ein freier Tag ist oder nicht
3. Hättest Du eine Liste aller Wochenenden, könntest Du eine Funktion schreiben, die die Feiertage nach den gegebenen Regeln einfügt.
4. Dafür brauchst Du eine Funktion, die die Wochenenden markiert.

Und so weiter, bis Du das gesamte Problem gelöst hast.
Wenn Du mit der Beschreibung der Lösung fertig bist, kannst Du Dir überlegen, wie Du die einzelnen Funktionen testen könntest, dass sie auch richtig funktionieren. Dafür schreibt man dann Test-Funktionen und wenn man diese hat, kann man sich an die Implementierung der eigentlichen Funktion machen.
bjoy
User
Beiträge: 6
Registriert: Donnerstag 31. August 2023, 09:24

....
Zuletzt geändert von bjoy am Donnerstag 31. August 2023, 16:36, insgesamt 1-mal geändert.
bjoy
User
Beiträge: 6
Registriert: Donnerstag 31. August 2023, 09:24

Sirius3 hat geschrieben: Donnerstag 31. August 2023, 10:15 Wie hast Du Dir denn den Algorithmus vorgestellt, der das Problem lösen soll?
Bisher sehe ich nur, dass es Code gibt, der die Anzahl an Wochen im Jahr zählt, sehr viel mehr macht get_weekdays_in_year nicht.

Um so eine Aufgabe anzugehen, fängst Du am besten unten an:
1. es braucht eine Funktion, die die Anzahl aufeinanderfolgender freier Tage zählt.
Was soll die Funktion als Input bekommen?
2. eine Liste aller Tage im Jahr und der Information, ob es ein freier Tag ist oder nicht
3. Hättest Du eine Liste aller Wochenenden, könntest Du eine Funktion schreiben, die die Feiertage nach den gegebenen Regeln einfügt.
4. Dafür brauchst Du eine Funktion, die die Wochenenden markiert.

Und so weiter, bis Du das gesamte Problem gelöst hast.
Wenn Du mit der Beschreibung der Lösung fertig bist, kannst Du Dir überlegen, wie Du die einzelnen Funktionen testen könntest, dass sie auch richtig funktionieren. Dafür schreibt man dann Test-Funktionen und wenn man diese hat, kann man sich an die Implementierung der eigentlichen Funktion machen.
Dateneingabe: Der erste Schritt besteht darin, die Eingabedaten zu lesen, also das Jahr und den Wochentag des 1. Januars sowie die Daten aller Feiertage.

Kalendererzeugung: Der nächste Schritt besteht darin, ein Wörterbuch bzw. einen Kalender für das gegebene Jahr zu erstellen und zu berücksichtigen, ob das Jahr ein Schaltjahr ist oder nicht. Wochentage sind als 0 gekennzeichnet, Sonntage und Samstage als 1.

Feiertagsangabe: Gehen Sie dann durch die Liste der Feiertage und wenn ein Feiertag auf einen Werktag fällt, kennzeichnen Sie ihn als 2 und ersetzen Sie das entsprechende Element im Kalender (nicht 1, weil es beim Erstellen der längsten Kette nicht verschoben werden kann); wenn es am Wochenende liegt, setzen Sie hier eine eins (also Sonntag oder Samstag), aber ersetzen Sie den nächsten Arbeitstag nach dem Wochenende durch einen Feiertag (also 2).

Berechnungen und Wochenendtranspositionen: Mit dieser internen Kalenderdarstellung müssen Sie nun berechnen, wie viele Wochenenden so auf Werktage verschoben werden können, um die maximale Anzahl aufeinanderfolgender Ruhetage zu erreichen, ohne die Bedingung "nicht mehr als 6 Arbeitstage hintereinander" zu verletzen. Beim Erstellen einer Kette tauschen Sie 0 und 1. Es ist zu sehen, dass unter normalem Zeitplan Werktage immer 5 hintereinander gehen, sodass alle Sonntage kühn in Werktage geändert und eine Kette davon erstellt werden kann. Da die 2 nicht verschoben werden können, sollten sie in eine Kette von 2 und 1 aufgenommen werden, und es muss sichergestellt werden, dass die Kette eine maximale Anzahl von Zweien enthält (sie können jedoch nicht verschoben werden).

Zählen des maximalen Kontinuitätswerts: Gehen Sie schließlich durch den result
Benutzeravatar
__blackjack__
User
Beiträge: 13937
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bjoy: Sind das jetzt die Gedanken die *Du* Dir dazu gemacht hast, oder willst Du von uns das wir ChatGPT korrigieren und ergänzen und Du dann so tust als hättest Du Deine Hausaufgaben selbst gelöst‽ Ich glaube nicht Tim…
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
bjoy
User
Beiträge: 6
Registriert: Donnerstag 31. August 2023, 09:24

__blackjack__ hat geschrieben: Donnerstag 31. August 2023, 19:28 @bjoy: Du von uns das wir ChatGPT
Ich übersetze ins Deutsche mit ChatGPT, ich kann es auch ohne Übersetzung versuchen, denn ich bin noch lange nicht perfekt...
Aber der Algorithmus ist komplett von mir erfunden. Wenn Sie mir nicht glauben, fragen Sie GPT selbst nach einer Lösung für dieses Problem, und er/sie wird definitiv nicht zu so etwas raten.
Ich brauche nur Hilfe bei der Implementierung des Codes, denn der Algorithmus scheint zu funktionieren
bjoy
User
Beiträge: 6
Registriert: Donnerstag 31. August 2023, 09:24

Mir ist klar geworden, woher die 63 Tage kommen. 53 von den Sonntagen (es gibt 53 Sonntage in einem Jahr, da das Jahr an einem Sonntag beginnt).
+1 Sonntag, da der Feiertag am Sonntag beginnt, so dass das Jahr mit 2 Feiertagen beginnt, fügen Sie 53 Sonntage zu dieser Kette hinzu, insgesamt 54 Tage, wir haben immer noch Samstage, jetzt 6 Arbeitstage, Samstag, usw., 54/6 = 9,0, also 54+9 = 63 freie Tage am Stück.
Benutzeravatar
__blackjack__
User
Beiträge: 13937
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bjoy: Das ist in diesem speziellen Fall so, aber man kann nicht allgemein zu irgendeinem der Feiertage die Sonntage hinzufügen, denn davon kann es ja mehr als einen geben. Und man braucht auch nicht allgemein *alle* Samstage um die maximal 6 Arbeitstage zu garantieren, es kann auch sein das man Samstage übrig hat um die Kette zu verlängern. Also einen fertigen Algorithmus hat man aus dieser Erkenntnis noch nicht.

Entweder Brute-Force oder man muss sich Gedanken um mögliche Konstellationen machen und begründen warum der jeweilige Schritt den man macht die jeweils beste Lösung garantiert. Und ich vermute es gibt keine ”greedy” Lösung, das heisst man müsste mehrere durchprobieren um die beste zu finden. Oder eben wieder gut begründen können warum es funktioniert was man da macht.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
bjoy
User
Beiträge: 6
Registriert: Donnerstag 31. August 2023, 09:24

__blackjack__ hat geschrieben: Freitag 1. September 2023, 11:16 @bjoy: Das ist in diesem speziellen Fall so, aber man kann nicht allgemein zu irgendeinem der Feiertage die Sonntage hinzufügen, denn davon kann es ja mehr als einen geben. Und man braucht auch nicht allgemein *alle* Samstage um die maximal 6 Arbeitstage zu garantieren, es kann auch sein das man Samstage übrig hat um die Kette zu verlängern. Also einen fertigen Algorithmus hat man aus dieser Erkenntnis noch nicht.

Entweder Brute-Force oder man muss sich Gedanken um mögliche Konstellationen machen und begründen warum der jeweilige Schritt den man macht die jeweils beste Lösung garantiert. Und ich vermute es gibt keine ”greedy” Lösung, das heisst man müsste mehrere durchprobieren um die beste zu finden. Oder eben wieder gut begründen können warum es funktioniert was man da macht.
Hier ist mein nächster Code, er besteht den ersten Test, aber dann schlägt er fehl:(

Code: Alles auswählen

a, b = map(int, input().split())
c = int(input())
copy_c = c
 
 
def func1(dt):
    e, f = map(int, dt.split('.'))
    g = {
        1: 31,
        2: 29 if a % 4 == 0 else 28,
        3: 31,
        4: 30,
        5: 31,
        6: 30,
        7: 31,
        8: 31,
        9: 30,
        10: 31,
        11: 30,
        12: 31
    }
    return sum(g[u] for u in range(1, f)) + e
 
 
h = [func1(input()) - 1 for _ in range(c)]
i = 366 if a % 4 == 0 else 365
 
j = 0
for _ in range(i):
    b %= 7
    if b in {0, 6}:
        j += 1
    b += 1
 
k = [0] * i
for l in h:
    k[l] = 2
 
b = 0
for l in range(i - 1, -1, -1):
    if k[l] == 0:
        b += 1
    elif k[l] == 2:
        b = 0
    if b == 7:
        k[l] = 1
        j -= 1
        b = 0
 
 
def func2(n):
    o = p = 0
    for q in n:
        if q in {1, 2}:
            p += 1
        else:
            o = max(o, p)
            p = 0
    o = max(o, p)
    return o
 
 
r = 0
for s in range(i):
    k_copy = k.copy()
    jc = j
    b = 0
    for t in range(s):
        if k_copy[t] == 0:
            b += 1
        elif k_copy[t] == 1:
            if b < 6:
                b += 1
                k_copy[t] = 0
                jc += 1
            else:
                b = 0
        elif k_copy[t] == 2:
            b = 0
    if b == 7:
        copy_t = t
        while k_copy[copy_t] == 0:
            copy_t -= 1
        k_copy[copy_t] = 1
        jc -= 1
        b = 0
    for t in range(s, i):
        if jc == 0:
            break
        if k_copy[t] == 0:
            k_copy[t] = 1
            jc -= 1
        else:
            continue
    r = max(r, func2(k_copy))
 
print(r - copy_c)
Sirius3
User
Beiträge: 18227
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich bin sicher, niemand hat Lust, sich auch nur zwei Minuten mit dem Code zu beschäftigen. Kein einziger Variablenname hat irgendeine aussagekraft. Um das verstehen zu können, müßte man den Code Zeile für Zeile ausführen und schauen, was da wirklich passiert.
Schreibe den Code nochmal neu, mit sinnvoll benannten Funktionen, mehr Funktionen und sinnvoll benannten Variablennamen.
Antworten