#!/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 # enemies # enemies_c # friends_h # fc # fh # 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')