garten-subtraktiv.py
von chrbr- SNIPPET_DESC:
- garten-subtraktiv.py
- SNIPPET_CREATION_TIME:
- 11.05.2023 19:28:01
- SNIPPET_PRUNE_TIME:
- Unendlich
- SNIPPET_TEXT:
-
- #!/usr/bin/env python3
- #======================================================================
- # Basierend auf der Arbeit von Huo
- # Der Graphentheorethische Teil ist per Hand gemacht.
- # Beginnend mit der Hauptpflanze werden zusätzliche Pflanzen
- # hinzu gefügt. Bei Unverträglichkeit wird diese Gruppe verworfen.
- # Ansonsten wird weiter gemacht bis man in keiner der Gruppen noch
- # eine Pflanze hinzufügen kann.
- #
- # Gute und schlechte Pflanzennachbarn müssen in zwei getrennten csv-Dateien
- # friends.csv und enemies.csv
- # in der Form PFLANZE1,PFLANZE2 hinterlegt sein (ein Paar pro Zeile)
- #
- # Die Pfade in den Zeilen 24 und 25 sind bei Bedarf anzupassen!
- #
- # Aufruf:
- # garten_dazu.py HAUPTPFLANZE
- # wobei HAUPTPFLANZE ein einzelner Name aus der Datei friends.csv ist
- #======================================================================
- import csv
- import itertools
- import os
- import sys
- # Einlesen der beiden csv-Dateien (Pfade bei Bedarf anpassen!) als Listen zwei-elementiger Mengen
- friends = list(set(line) for line in csv.reader(open(os.path.expanduser("./friends.csv"))))
- enemies = list(set(line) for line in csv.reader(open(os.path.expanduser("./enemies.csv"))))
- # Plausibilitätsprüfung der Listen auf widersprüchliche Nachbarbeziehungen
- if [s for s in friends if s in enemies] != []:
- print("Pflanzenpaar darf nicht zugleich in friends.csv und enemies.csv liegen")
- print("Dubletten:", [s for s in friends if s in enemies])
- sys.exit(1)
- # Check Parameter
- if not [i for i in friends if sys.argv[-1] in i] or len(sys.argv) != 2:
- print("Script muss mit einer Einzelpflanze aus friends.csv als einzigem Parameter aufgerufen werden!")
- sys.exit(1) # Abbruch bei Aufruf ohne Parameter oder mit falschem Parameter
- hauptpflanze = sys.argv[1]
- # Gute Nachbarn der Hauptpflanze (Liste der Paare {Hauptpflanze, Guter Nachbar})
- friends_h = list(s for s in friends if hauptpflanze in s)
- # Menge der guten Nachbarn der Hauptpflanze
- fh = set().union(*friends_h)
- # Kombinationen dieser guten Nachbarn als Liste zwei-elementiger Mengen
- fc = list(set(s) for s in itertools.combinations(fh, 2))
- # darunter schlechte Nachbarn
- enemies_c = list(frozenset(s) for s in fc if s in enemies)
- # Typen
- # friends <class 'list'>
- # enemies <class 'list'>
- # enemies_c <class 'list'>
- # friends_h <class 'list'>
- # fc <class 'list'>
- # fh <class 'set'>
- # Ausgabe der Guten Nachbarn der Hauptpflanze
- print ("-------------------------------------")
- print ("Gute Nachbarn von", hauptpflanze, ":")
- fh_d = fh
- fh_d.discard(hauptpflanze)
- print (*sorted(fh_d), sep=", ")
- print ()
- # Ausgabe der Paare schlechter Nachbarn:
- ltmp = []
- for item in enemies_c:
- ltmp.append(sorted(item))
- #ltmp.sort()
- print ("Darunter harmonieren nicht:")
- print (*sorted(ltmp), sep="\n")
- print ()
- # Schleife über Gruppen von Pflanzen. Es wird mit der Liste
- # mit einem sets der Hauptfrucht und alles Friends angefangen.
- sgroups = set()
- fh.add(hauptpflanze)
- sgroups.add(frozenset(fh))
- while enemies_c:
- newgroups = set()
- senemie = enemies_c.pop(0)
- for group in sgroups:
- # Falls die if Abfrage true ergibt ist es ein Konflikt.
- # Dann werden group ohne enemie1 und group ohne enemie2
- # an newgroups angehängt.
- # Falls es kein Konfliktfall gibt wird nur groups kopiert.
- if senemie.issubset(group):
- for enemie in senemie:
- stmp = set(group)
- stmp.discard(enemie)
- newgroups.add(frozenset(stmp))
- else:
- newgroups.add(group)
- sgroups = newgroups.copy()
- minlen = len(fh)
- maxlen = 0
- for i in sgroups:
- minlen = min(minlen, len(i))
- maxlen = max(maxlen, len(i))
- # Erzeuge eine neue Liste aus Elementen mit der kleinsten Anzahl von Pflanzen.
- # Entferne diese Gruppen kleinster Länge aus dem Set aller Gruppen.
- # Für die Kandidaten aus der Gruppe kleinster Länge überprüfe,
- # ob die Kandidaten eine Teilmenge der grösseren Gruppen sind.
- # Die Kandidaten, die keine Teilmenge einer der grösseren Gruppen sind
- # sind Element einer Clique und nicht erweiterbar.
- # Die anderen Kandidaten werden nicht weiter behandelt, weil sie
- # Teilmenge einer grösseren Menge sind.
- sreduced = set()
- while minlen < maxlen:
- lmin = [group for group in sgroups if len(group) == minlen]
- sgroups = sgroups.difference(lmin)
- while len(lmin) > 0:
- kandidat = lmin.pop()
- if not [group for group in sgroups if kandidat.issubset(group)]:
- sreduced.add(kandidat)
- minlen = minlen+1
- # Die längsten Gruppen werden nicht in einer Schleife untersucht,
- # weil es dazu keine grösseren Gruppen gibt, deren Teilmenge sie
- # sein könnten. Sie werden als nicht erweiterbare Elemente einer
- # Clique einfach angehängt.
- sreduced.update(sgroups)
- lreduced = []
- for group in sreduced:
- lreduced.append(sorted(group))
- lreduced.sort()
- print ("Mögliche Mischkulturen:")
- print(*sorted(lreduced, key=len), sep='\n')
Quellcode
Hier kannst du den Code kopieren und ihn in deinen bevorzugten Editor einfügen. PASTEBIN_DOWNLOAD_SNIPPET_EXPLAIN