Hilfe bei Python Programm

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.
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

Guten Tag!

Ich habe folgendes Programm:

Code: Alles auswählen

from datetime import datetime
import locale

locale.setlocale(locale.LC_ALL, "de_DE")

print("Bitte geben Sie die Namen oder Bezeichnungen der Mitglieder ein, die zum Treffen kommen sollen")
mitglieder = [name.strip() for name in input().split(",")]


print("Bitte geben Sie die mögliche Termine ein")
termine = [[datetime.strptime(datum.strip(),"%d.%m.%Y"),0] for datum in input().split(",")]

for mitglied in mitglieder:
    for termin in termine:
        termin[1] += int(input(f"Wie gut passt {termin[0]:%A, der %d.%m.%Y} für {mitglied}? (0 = passt gut, 1= passt mäßig, 2 = passt schlecht oder beispielsweise in Noten): "))
    print()
        
                                    

print("Durchschnitt pro Termin:")
for termin in termine:
    print(f"{termin[0]:%A, der %d.%m.%Y}: {termin[1]/len(mitglieder):.2f}")        

bester_termin = min(termine, key=lambda termin:termin[1])

print()
print(f"Am besten passt {bester_termin[0]:%A, der %d.%m.%Y}.")
Beispiel Ausgabe in der Shell:

Code: Alles auswählen

Bitte geben Sie die Namen oder Bezeichnungen der Mitglieder ein, die zum Treffen kommen sollen
Jan, Paul, Peter
Bitte geben Sie die mögliche Termine ein
11.10.2021, 12.10.2021
Wie gut passt Montag, der 11.10.2021 für Jan? (0 = passt gut, 1= passt mäßig, 2 = passt schlecht oder beispielsweise in Noten): 3
Wie gut passt Dienstag, der 12.10.2021 für Jan? (0 = passt gut, 1= passt mäßig, 2 = passt schlecht oder beispielsweise in Noten): 1

Wie gut passt Montag, der 11.10.2021 für Paul? (0 = passt gut, 1= passt mäßig, 2 = passt schlecht oder beispielsweise in Noten): 1
Wie gut passt Dienstag, der 12.10.2021 für Paul? (0 = passt gut, 1= passt mäßig, 2 = passt schlecht oder beispielsweise in Noten): 2

Wie gut passt Montag, der 11.10.2021 für Peter? (0 = passt gut, 1= passt mäßig, 2 = passt schlecht oder beispielsweise in Noten): 1
Wie gut passt Dienstag, der 12.10.2021 für Peter? (0 = passt gut, 1= passt mäßig, 2 = passt schlecht oder beispielsweise in Noten): 4

Durchschnitt pro Termin:
Montag, der 11.10.2021: 1.67
Dienstag, der 12.10.2021: 2.33

Am besten passt Montag, der 11.10.2021.

Nun, da der passendste Termin ausgewählt wurde, möchte ich zusätzlich, dass das Programm erkennt, dass ein Wechsel der Bewertung möglich ist, in diesem Beispiel bei Jan.
Wenn man nun bei Jan die Wertung (hier die 3 mit der 1) wechselt, so wäre der 1. Termin mit einem Schnitt von 1.00 der best-möglichste.

Wunschprint wäre hier also noch:
"Ein Wechsel ist bei Jan möglich, der neue Durchschnitt wäre: 1.00"

Anmerkung: Das müsste allgemein anwendbar sein, da man ja beliebig viele Termine, sowie Personen eintragen kann.

Meine Ideen:
Man müsste also Bewertungen jeder Person in eine Liste packen richtig? In diesem Beispiel: bewertung_person1 = [3, 1] usw.
Bisher wird die Bewertung allerdings gar nicht gespeichert, sondern es wird sich nur die Summer aller Bewertungen pro Datum gemerkt, oder?

Wie könnte man nun das nun also umsetzen und anschließend zu diesem print kommen? :|
Bin für jede Hilfe extrem dankbar!!
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Paulus145: Die verschachtelte Liste ist ja eher nicht so schön als Datenstruktur. Lesbarer wäre es ein Wörterbuch aufzubauen, dass Datum auf Bewertung abbildet.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import locale
from datetime import datetime


def main():
    locale.setlocale(locale.LC_ALL, "de_DE")

    print(
        "Bitte geben Sie die Namen oder Bezeichnungen der Mitglieder ein, die"
        " zum Treffen kommen sollen"
    )
    mitglieder = [name.strip() for name in input().split(",")]

    print("Bitte geben Sie die mögliche Termine ein")
    termine = [
        datetime.strptime(datum.strip(), "%d.%m.%Y")
        for datum in input().split(",")
    ]
    datum_zu_bewertung = dict.fromkeys(termine, 0)

    for mitglied in mitglieder:
        for datum in termine:
            datum_zu_bewertung[datum] += int(
                input(
                    f"Wie gut passt {datum:%A, der %d.%m.%Y} für"
                    f" {mitglied}? (0 = passt gut, 1= passt mäßig,"
                    f" 2 = passt schlecht oder beispielsweise in Noten): "
                )
            )
        print()

    print("Durchschnitt pro Termin:")
    for datum, bewertung in datum_zu_bewertung.items():
        print(f"{datum:%A, der %d.%m.%Y}: {bewertung / len(mitglieder):.2f}")

    _, bestes_datum = min(
        (bewertung, datum) for datum, bewertung in datum_zu_bewertung.items()
    )

    print()
    print(f"Am besten passt {bestes_datum:%A, der %d.%m.%Y}.")


if __name__ == "__main__":
    main()
Woran erkennt man denn ob ein Wechsel möglich ist? Warum können Paul und/oder Peter nicht wechseln?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

Ein Wechsel ist möglich, wenn an einem anderen Termin eine bessere Note vergeben wurde. In diesem Fall haben Paul und Peter bei allen anderen Terminen (hier nur einer) eine schlechtere Bewertung abgegeben, weshalb beim passendsten Termin bereits die beste Wertung vorhanden ist.
Ein Wechsel ist bei Jan hingegen möglich, da dieser bei einem anderen Termin eine bessere Wertung (hier: 1 für den 12.10.2021) vergeben hat. Da ist es möglich diese "1" für den 12.10.2021 mit der "3" für den 11.10.2021 zu tauschen, somit wäre der 11.10.2021 der "allseits-beste" Termin. Der neue Durchschnitt wäre hier dann genau 1.00.
Ich hoffe es ist einigermaßen klar geworden :) Ansonsten stehe ich gerne für weitere Rückfragen bereit.

Danke auch für die strukturiertere Darstellung! Wie ich das sehe, wurde das alles in eine Methode gepackt? Hat das einen bestimmten Grund? Denn zwingend notwendig ist diese ja nicht?
Liebe Grüße
Paulus
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Paulus145: Für diesen Fall okay, aber wie würde man diese Bedingungen denn allgemein formulieren? Und rein praktisch finde ich das mit dem *tauschen* komisch, denn wenn Jan die 1 und die 3 vergeben hat, dann ändert der ja nicht tatsächlich seine Meinung auf diese Weise (es sei denn er wird mit genug Geld oder Gewalt bedroht. ;-)) Und womit (und warum) würde man denn tauschen wenn es drei Termine gäbe und Jan dann ja zwei Tauschmöglichkeiten hätte?

Es ist eine Funktion, keine Methode. Und das mache ich grundsätzlich, weil so etwas selten wirklich so klein bleibt, dass man das alles einfach so runterschreiben sollte. Und spätestens wenn man Code dann auf mehrere Funktionen oder gar Klassen und Methoden aufteilt, sollte nichts mehr auf Modulebene stehen was man dann aus versehen verwenden könnte, ohne es sauber und nachvollziehbar als Argument(e) zu übergeben.

Momentan ist die Grösse der Funktion für meinen Geschmack gerade so an der Grenze. Mit dem zusätzlichen Schritt das Ergebnis noch anzupassen, oder zumindest einen entsprechenden Vorschlag zu ermitteln, kommt noch hinzu, dass man so etwas vielleicht auch testbar schreiben möchte, und dazu müsste dann ja mindestens dieser Teil in eine Funktion ausgelagert werden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

@_blackjack_
Ich finde das auch komisch mit dem tauschen haha, aber so ist die Aufgabe...

Allgemein muss man jede Bewertung die eine Person eingibt in eine Liste packen, hier brauch es also irgendwie eine Liste mitglieder [ ] -> was hier ja leider noch nicht erfolgt, da aber die Werte die in die Liste sollen ja nicht in einem Input, sondern in mehreren eingegeben werden, weiß ich nicht, wie man so eine Liste zustande bekommt :)

Und dann hat man mitglieder[0], mitglieder[1] und mitglieder[2] (in diesem Beispiel mit 3 Personen), wobei in mitglieder [0] dann [3, 1] ist (Jan) usw.

Alleine am Ende auszugeben: Jans overall Bewertungen waren: 3, 1 oder [3,1]. Die von Paul waren.... Von Peter...
würde schon sehr helfen.

Ich habe mir überlegt, ob man nicht mit:
mitglieder[min], mitglieder[min] = mitglieder[min], mitglieder[min]

...arbeiten könnte, wobei dann ja auch nicht klar ist, dass jz der größte Termin derjenige ist, der als Wertung für den passendsten Termin eingegeben wurde, weshalb das auch eig. quatsch ist.

Da mir keine Möglichkeit bekannt ist, Positionen innerhalb einer Liste festzulegen, ist mir sonst auch nichts eingefallen, da man sowas in der Art ja hier bräuchte... Wenn nun z.B. der dritte Termin der passendste ist, müsste man die dritte eingegebene Wertung einer Person mit der sonst kleinsten eingegebenen Wertung tauschen. Doch wie weiß das Programm, dass jetzt die dritte Position der Liste gemeint ist?

Naja, wenn mir jemand helfen könnte, eine Liste für alle eingebenen Werte einer Person -wie oben beschrieben- einzubauen, sodass alles noch genauso gut funktioniert und man diese Liste dann wie oben genannt ausgeben kann, würde mir das schon enorm weiterhelfen!

Vielen Dank für die Antwort übrigens!
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Paulus145: Wie lautet denn die Aufgabenstellung ganz konkret, denn das eine Beispiel sagt ja nicht wirklich genug aus. Es ergeben sich Unmengen an „was wäre wenn“-Folgefragen. Zum Beispiel wenn es mehr als einen Tag gibt bei denen der gleiche beste Wert zustande kommt. Welchen nimmt man dann? Sinnvoll wäre ja den, wo am wenigsten Leute am wenigsten ”weit” von ihrem Wunsch abweichen müssten.

Man müsste sich in der Tat pro Person und Datum die jeweilige Eingabe merken. Ich denke immer noch das Listen nicht so gut sind, weil das dann zu Indexgehampel führt. Wörterbücher würden da IMHO mehr Sinn machen. Also Person abbilden auf eine Abbildung von Datum auf Bewertung beispielsweise. Oder Datum auf eine Abbildung von Person auf Bewertung. Je nach dem was am Ende besser zu verarbeiten ist.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

Okay eigentlich soll man ein Textdokument einlesen vermute ich, jedenfalls sind als Beispiellösung solche angegeben:

Ein Textdokument sieht ungefähr so aus:
6 7
0 0 0 0 0 0 0
1 0 0 1 1 0 0
2 2 2 1 2 2 2
2 1 1 1 2 1 2
0 1 2 2 1 0 0
1 2 1 2 0 1 1

Dabei steht "in der ersten Zeile die Anzahl n der Mitglieder der Clique und die Anzahl m der Termine"
In den weiteren n Zeilen jeweils die Präferenzen des Mitglied i bestehend aus m Zahlen:
0 steht für „sehr gut“ ,
1 steht für „mäßig“ und
2 steht für „überhaupt nicht“

Also stehen die Zeilen für die Termine und die Spalten für die Bewertungen.
Die genaue Aufgabenstellung ist nun:
Schreibe ein Programm, das eine Präferenztabelle einliest und anschließend berechnet und ausgibt, wie viele Einträge verändert werden müssten, damit ein allseits beliebter Termin entsteht. Lass auch diesen Termin ausgeben.

Das ist erstmal etwas anders, das ist mir klar, ich fand die Idee mit Datetime nur gut und habe keine zufriedenstellende Möglichkeit gefunden, mit dem Textdokument einscannen. Deshalb dachte ich, ich mache es mit Inputs und Listen (arbeite noch nicht allzu lange mit Python und muss alles nachgucken und irgendwie einbauen).
Volle Punktzahl ist hier also definitiv nicht mein Ziel. Nur die Frage in etwa beantworten :)
Hoffe man kann damit was anfangen...

P.S. wenn die Bewertung in Schulnoten einfacher ist, als diese komische 0-1-2 Konstruktion, kann man auch damit arbeiten.

Vielen Dank!
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

Anmerkung: Meine Frage ging immernoch über mein Programm... ich erwarte jz nicht, dass man komplett umdenkt für mich (nur weil die Fragestellung etwas anders ist) so und ich nichts beitragen kann, falls das so rübergekommen ist :3
Außer die "richtige Antwort" ist auf einmal deutlich einfach, was ich nach längerem Beschäftigen mit der Sache nicht so empfunden habe :)
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Paulus145: Was meinst Du mit ”Textdokument einscannen”? Da steht ”einlesen” in der Aufgabe, nichts von Scannen. Das ist soweit ich das sehe eine einfache Textdatei und auch in einem sehr üblichen Format für solche Aufgaben, beziehungsweise sogar in einem Format für Aufgaben die in mehr oder weniger beliebigen Programmiersprachen zu lösen sind. Denn dafür werden die Eingabedaten in der Regel so präsentiert, dass zuerst eigentlich redundante Informationenen über die Datenmenge kommen, bevor die eigentlichen Daten kommen; für Programmiersprachen wo das mit dem Speicher/den Datenstrukturen weniger dynamisch abläuft und man vor dem Einlesen von Daten wissen sollte wieviel Speicher dafür reserviert werden muss.

Die Informationen der ersten Zeile braucht man in Python nicht zwingend. Ich würde sie zum kontrollieren der Eingabe verwenden, auch wenn man bei solchen Aufgaben in der Regel nur valide Eingabedaten bekommt. Im Gegensatz zu realen Eingabedaten. 😎

Erster Schritt ist bei so etwas in der Regel das einlesen der Daten, entweder in eine Datenstruktur, die der Struktur der Eingabedaten entspricht, oder eventuell schon etwas umgeformt wie sie für die Weiterverarbeitung praktisch(er) sind. Sofern man das schon weiss, und sofern das nicht so komplex ist, dass man das besser in eine eigene, testbare Funktion auslagert.

Stichwort Funktion: Das einlesen/parsen gehört in eine Funktion, die beispielsweise ein iterierbares Objekt mit Zeichenketten die Zeilen der Eingabe repräsentieren erwartet. Die kann man dann zum Testen beispielsweise mit Listen mit Zeilendaten füttern, aber auch mit einem Dateiobjekt.

Code: Alles auswählen

#!/usr/bin/env python3
from pprint import pprint

EXAMPLE_INPUT = """\
6 7
0 0 0 0 0 0 0
1 0 0 1 1 0 0
2 2 2 1 2 2 2
2 1 1 1 2 1 2
0 1 2 2 1 0 0
1 2 1 2 0 1 1
""".splitlines()


def parse_lines(lines):
    ...
    return preference_table


def main():
    preference_table = parse_lines(EXAMPLE_INPUT)
    pprint(preference_table)



if __name__ == "__main__":
    main()
Ausgabe:

Code: Alles auswählen

[[0, 0, 0, 0, 0, 0, 0],
 [1, 0, 0, 1, 1, 0, 0],
 [2, 2, 2, 1, 2, 2, 2],
 [2, 1, 1, 1, 2, 1, 2],
 [0, 1, 2, 2, 1, 0, 0],
 [1, 2, 1, 2, 0, 1, 1]]
Und auch wenn Du das Format änderst, zum Beispiel mit echten Datumsangaben verkomplizierst, solltest Du diesen Schritt gehen, damit Du nicht für jeden Testlauf tatsächlich per Hand Namen und Datumsangeben eintippen musst, immer mit der Gefahr Dich dabei zu vertippen. Das kostet unnötig Zeit und frustriert sicher auch irgendwann ziemlich.

Zur Aufgabe selbst musst Du Dir noch gut überlegen ob man erst den bisher besten Termin finden kann und dann die Schritte den zum beliebtesten für alle zu machen berechnen kann, oder ob es nicht auch sein kann, dass man mit weniger Schritten zu einem beliebtesten Termin für alle zu kommen, der nicht der ursprüngliche Gewinner war. Falls das nicht möglich ist, hätte zumindest unser Inf-Lehrer dafür eine kurze Erklärung erwartet warum das nicht möglich ist.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

Noch nie gelesen, dass man pprint importieren kann, obwohl ich da echt viel nachgeguckt habe, danke!
Nun habe ich als Ausgabe ja eine Liste, worin mehrere Listen enthalten sind, richtig?
Jedoch sind die Wertungen für jeden Termin ja nun in den Spalten, wie kriege ich es denn dann hin "vertikal" quasi die Zahlen zu lesen und da den besten Termin rauszusuchen? Selbst wenn ich das habe, kann ich ja immernoch keine richtigen "Positionen" festlegen, welche Zahl denn nun mit einer kleineren getauscht wird... also stehe ich genau vor dem gleichen Problem wie auch zu vor, oder nicht?

Das mit den Schritten ist ein guter Punkt, jedoch wenn man zuerst den besten Termin raussucht, muss das Program ja am wenigsten Änderungen vornehmen. Oder ist es leichter einfach, sagen wir, Position 1 in jeder Liste als Termin auszuwählen, und den einfach zum allseits-besten zu machen. Dann tauscht man einfach die Zahl an Position 1, mit der kleinsten von allen Wertungen?

Wenn so ein Programm schnell umsetzbar ist, könnte ich ja auch einfach beide Programme abegeben, eines zum Berechnen des besten Termins so und das andere, um zu berechnen wie gut die Wertung des besten Termins maximal sein kann. Wäre das eine leicht-umsetzbare Möglichkeit?

Denn ich habe jetzt schon echt viel Zeit damit verbracht und so langsam komme ich zu dem Punkt, wo es einfach keinen Progress gibt und es einen einfach NUR frustriert... Also, wenn die Lösung in 2 Programmen am einfachsten ist, würde ich diesen Weg jz einfach gehen, auch wenn dann eins mit Input und eines mit einlesen ist oder so.

Zu den Gedanken bzw. dieser Art von Umsetzung noch Ideen und Lösungsvorschläge? Hilfst mir echt extrem!

Vielen Dank auf jeden Fall!
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Paulus145: Das `pprint`-Modul aus der Standardbibliothek ist ganz praktisch um Datenstrukturen aus Grunddatentypen übersichtlich(er) auszugeben. Empfehlenswert ist auch das externe `prettyprinter`-Modul. Das ”kennt” mehr von der Standardbibliothek und kann auch einfach für Klassen verwendet werden, die mit dem `attrs`-Package geschrieben wurden. Und man kann auch eigene Typen/Klassen registrieren und relativ einfach festlegen, wie deren Struktur dann ”schön” ausgegeben werden soll. In Terminals gibt das auch farbig aus.

Ich denke das Problem ist einfacher, weil Du vorher das gleiche Problem hattest *plus* Namen und konkrete Datumsangaben den Positionen zuordnen.

Wie im letzten Beitrag geschrieben: Es könnte sinnvoll sein die eingelesene Struktur so umzuformen, dass man damit leichter arbeiten kann. Zum Beispiel lassen sich Zeilen besser aufaddieren als Spalten. *Aber* man wird ja auch die Spalten auswerten müssen, wenn man schaut welche Werte in einer Zeile vertauscht werden müssten, und dafür ist die Struktur so wie sie ist besser.

Man kann natürlich versuchen ob man das ganze so aufzuteilen kann, dass man die Verarbeitung in zwei Phasen trennen kann, in der jeweils die Tabelle so wie sie eingelesen wurde am praktischsten ist, oder mit Zeilen und Spalten vertauscht (= transponiert). Nachteil: man hat dann die gleichen Daten redundant in zwei Strukturen, die man nicht wirklich gut/leicht auseinanderhalten kann, weil beides 2D-Listen mit Zahlen sind. Ich persönlich fände es übersichtlicher die Datenstruktur in *ein* Format zu bringen und damit durchgehend zu arbeiten.

Und wie gesagt, wenn Du von dem bisher besten Termin ausgehst, müsstest Du begründen können, warum man das tun darf. Weil es ja nicht nur ja/nein gibt, sondern drei Stufen. Eine 3 mit einer 0 zu tauschen ist ja das gleiche wie 3 Tauschvorgänge von 1 zu 0. Warum kann es also nicht sein, dass beim zweitbesten Tag ein Tauschvorgang reicht, während beim besten Tag mehrere nötig sind, um auf die gleiche Verbesserung zu kommen? Oder kann das halt doch sein‽

Mal als simples Beispiel 4 Mitglieder und zwei Termine:

Code: Alles auswählen

4 2
0 3
1 0
1 0
1 0
Beide Tage sind in diesem Fall gleich gut. Aber beim ersten muss man 3 Wechsel vornehmen, und beim zweiten nur einen Wechsel, um den “allseits beliebt“ zu machen.

Zum Thema Wert in einer Spalte addieren: Indexzugriff. Beziehungsweise wenn man alle Werte in der Tabelle pro Spalte aufaddieren will, mit einer Schleife die jeweils die bisherige Summe pro Spalte auf den aktuellen Spaltenwert addiert. Da kommt man mit der `zip()`-Funktion um die Indizes herum.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

In dem Fall würde ich einfach sagen, man nimmt den früheren Termin? Falls das leichter ist...

Nochmal zu deinem Beispiel mit dem Einlesen, "preference_table" ist da gar nicht definiert oder? Müsste dann doch einen Fehler ausspucken dachte ich mir, was es auch macht.

Auch noch nie von .zip() gehört ;/ Gibt es ein leicht zu verstehendes Beispiel dazu? Teilt das quasi in Zeilen-Listen und Spalten-Listen auf?

Man ey wieso ist das alles so schwer... echt...

Eigentlich finde ich Informatik echt cool, aber sowas ist echt nicht mein Fall...
Danke nochmal! Gefühlt brauche ich das ganze fertige Programm, um das alles neu zu verstehen...
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Paulus145: Was meinst Du mit leichter? Es wäre halt *falsch* immer den früheren Termin zu nehmen. Insbesondere in diesem Beispiel ist es ja sogar falsch, weil der frühere Termin 3 Wechsel braucht und der spätere nur einen, denn ich interpretiere die Aufgabe schon so, dass die oder eine beste Lösung gefunden werden soll, wo am wenigsten Leute ihre Pläne ändern müssen.

Der Code wäre halt einfacher, wenn man einfach für jeden Tag die Anzahl der Wechsel berechnen würde, und dann den ersten mit den wenigsten nötigen Wechseln wählen würde. Die Alternative wäre zusätzlich vorher noch die besten auszusuchen und das dann nur mit denen zu machen. *Und* da würde sich immer noch die Frage stellen, ob man das überhaupt so machen darf, und wenn ja warum das okay ist. Bist Du Dir da denn sicher? Und wenn ja, warum?

Weiteres Beispiel:

Code: Alles auswählen

3 2
3 0
1 2
0 1
Der zweite Termin ist Anfangs der bessere, aber beide können auf den selben Wert verbessert werden, der vorher schlechtere aber mit *weniger* Wechseln!
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

Ich denke beide Möglichkeiten wären nachvollziehbar, also ich kann in einer Dokumentation dann erläutern, wieso ich den einen Weg jetzt gewählt habe. Da würde ich dann mit dem gehen, der leichter umzusetzen ist :)

Also die Gedanken sind eindeutig berechtigt, aber nicht so wichtig, dass man sich jetzt zwingend entscheiden muss. Wie oben genannt würde ich einfach mit dem leichteren gehen, da finde ich die Idee mit den Wechsel berechnen für jeden Tag gar nicht schlecht!
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Hier mal meine Ergebnisse für die 6 Eingabedateien:

Code: Alles auswählen

0: An Termin Nummer 6 war(en) 2 Wechsel notwendig.
1: An Termin Nummer 2 war(en) 1 Wechsel notwendig.
2: An Termin Nummer 4 war(en) 0 Wechsel notwendig.
3: An Termin Nummer 18 war(en) 7 Wechsel notwendig.
4: An Termin Nummer 22 war(en) 14 Wechsel notwendig.
5: An Termin Nummer 31 wa(ren) 34 Wechsel notwendig.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

Wie kommt es zu diesen Termin Nummern? Also bis zur 31 hoch 😅

Ansonsten sieht es nach ner guten Möglichkeit aus!
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Paulus145: Der Beispieldatensatz 5 hat 50 Mitglieder und 80 Termine. Hast Du Dir die noch nicht angeschaut/heruntergeladen?

Mein(e) Progamm(e) geben den Index + 1 aus, weil Menschen ja in der Regel bei Termin 1 anfangen und nicht bei Termin 0. Macht das Beispiel mit den originalen Bedingungen für einen „allseits beliebten“ Termin ja auch so.

Programme, Mehrzahl, weil ich das jetzt auch mal in BASIC auf meinem C64 umgesetzt habe. Hier der Testlauf aller Beispieldatensätze wo in der Zeile vor dem jeweiligen Ergebnis die Anzahmen der Mitglieder und Termine ausgegeben sind, und in der Zeile danach die Laufzeit in der Form HHMMSS. Das grösste Beispiel hat also, inklusive Datei einlesen (auf dem C64 notorisch langsam) fast 6 Minuten gebraucht:

Code: Alles auswählen

RUN
EINGABEDATENSATZ 0-5? 0
 6  7
AN TERMIN 6 SIND 2 WECHSEL.
000004

READY.
RUN
EINGABEDATENSATZ 0-5? 1
 5  5
AN TERMIN 2 SIND 1 WECHSEL.
000002

READY.
RUN
EINGABEDATENSATZ 0-5? 2
 8  10
AN TERMIN 4 SIND 0 WECHSEL.
000007

READY.
RUN
EINGABEDATENSATZ 0-5? 3
 14  20
AN TERMIN 18 SIND 7 WECHSEL.
000026

READY.
RUN
EINGABEDATENSATZ 0-5? 4
 26  40
AN TERMIN 22 SIND 14 WECHSEL.
000134

READY.
RUN
EINGABEDATENSATZ 0-5? 5
 50  80
AN TERMIN 31 SIND 34 WECHSEL.
000556

READY.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

Habe eine Lösung mithilfe des Lehrers mit numpy und argv gefunden... trotzdem vielen Dank für die ganze Hilfe, konnte ich auch mit einbauen... riesen Dankeschön!
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Hast Du denn die gleichen Ergebnisse?

Das CBM BASIC-Programm sieht so aus:

Code: Alles auswählen

   10 INPUT"EINGABEDATENSATZ 0-5";F$:TI$="000000":GOSUB 500
  100 REM CALCULATE HOW MANY DATES HAVE
  110 REM A BETTER RANKING THAN EACH
  120 REM POSSIBLE RANKING FOR EACH MEMBER
  130 DIM H%(N,3)
  140 FOR I=1 TO N:FOR J=1 TO M:K=T%(I,J)+1:H%(I,K)=H%(I,K)+1:NEXT:NEXT
  150 FOR I=1 TO N:FOR J=0 TO 2:H%(I,J+1)=H%(I,J)+H%(I,J+1):NEXT:NEXT
  200 REM CALCULATE SWAP COUNTS FOR DATES
  210 DIM SC%(M)
  220 FOR I=1 TO N:FOR J=1 TO M:IF H%(I,T%(I,J))>0 THEN SC%(J)=SC%(J)+1
  230 NEXT:NEXT
  300 REM FIND SMALLEST SWAP COUNT AND DATE
  310 SC=SC%(1):D=1
  320 FOR I=1 TO M:IF SC%(I)<SC THEN SC=SC%(I):D=I
  330 NEXT:PRINT"AN TERMIN";D;"SIND";SC;"WECHSEL.":PRINT TI$:END
  500 REM LOAD PREFERENCE TABLE
  510 OPEN 1,8,2,"J2 INPUT "+F$+",S,R"
  520 GOSUB 600:N=X:GOSUB 600:M=X:DIM T%(N,M):PRINT N;M
  530 FOR I=1 TO N:FOR J=1 TO M:GOSUB 600:T%(I,J)=X:NEXT:NEXT:CLOSE 1:RETURN
  600 GET#1,C$:IF C$<"0" AND C$>"9" THEN 600
  610 X=0
  620 X=X*10+VAL(C$)
  630 GET#1,C$:IF C$<"0" OR C$>"9" THEN RETURN
  640 GOTO 620
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Paulus145
User
Beiträge: 11
Registriert: Samstag 23. Oktober 2021, 12:10

Habe für das letzte Beispiel als besten Termin Nr. 31 mit 34 Veränderten Beiträgen. Es wurde erst der beste Termin berechnet und dann die Anzahl an Wechsel der Bewertungen, kann gut sein, dass es mit einer anderen Reihenfolge etwas anders ausfällt :)
Antworten