-
-
Save raphaelm/3e91e2bfb529e2c6252b to your computer and use it in GitHub Desktop.
Wichtel-Programm für die Familienweihnachtsfeier
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: UTF-8 -*- | |
# Patricia Ennenbach - 15-12-21 - Wichteln | |
# Aufgaben: | |
# - Jedes Kind soll einem Kind etwas schenken | |
# - Kinder sollen sich nicht selbst beschenken | |
# - Kinder sollen nicht ihre Geschwister beschenken | |
# - Jedes Kind soll nur einmal beschenkt werden | |
# Ich habe den Hauptteil relativ stark verändert, aus zwei Gründen: | |
# * Du hast die Liste "kinder" bearbeitet, während du in einer Schleife | |
# über sie iteriert hast. Das führt zu ziemlich kompliziert zu lesendem | |
# Code. | |
# * Ich glaube, es hätte in deinem Skript vorkommen können, dass ein Kind | |
# sein Geschwisterkind beschenkt, wenn es eine Familie mit drei Kindern | |
# gegeben hätte. | |
import random | |
import copy | |
random.seed() | |
familiendict = { | |
'nina': ['Erik', 'Mira'], | |
'haupi': ['Helena', 'Clara'], | |
'philipp': ['Romy', 'Simon'], | |
'frick': ['Melina', 'Manuel'], | |
'tim': ['Hannah', 'Leah'], | |
'verena': ['Judith'] | |
} | |
##kinder = ['Erik', 'Mira', 'Helena', 'Clara', 'Romy', 'Simon', 'Melina', 'Manuel', 'Hannah', 'Leah', 'Judith'] | |
# Finde ich nicht so schön, weil du dann die Namen doppelt konfigurieren | |
# musst. Lässt sich über Magie mit Listen lösen, das ist immer nicht sehr | |
# offensichtlich, was man mit Listen so an Magie machen kann... Leider gibt | |
# es hier keinen wirklich eleganten Weg das zu tun. Ich habe ein bisschen | |
# recherchiert und einen gefunden, der zwar clever, aber auch etwas tricky | |
# ist. Er basiert darauf, dass man Listen addieren kann, also | |
# [1, 2] + [3, 4] == [1, 2, 3, 4] | |
# familiendict.values() gibt uns eine Art Liste von Listen, und dann können | |
# wir die sum()-Funktion nutzen | |
kinder = sum(familiendict.values(), []) | |
# Das zweite Argument für sum, die leere Liste, ist quasi nur dazu da zu | |
# sagen, was das für ein Datentyp ist, den wir summieren | |
print(len(familiendict)) | |
print(kinder) | |
wichteldict = {} | |
# Zuerst lagere ich mal den Test, ob zwei Kinder Geschwister sind, in | |
# eine Funktion aus, der Übersichtlichkeit halber | |
def sind_geschwister(k1, k2): | |
# Wir schauen uns jede Familie einzeln an | |
for familie in familiendict.values(): | |
# Wir wandeln die Liste der beiden Kinder sowie die Liste der | |
# Kinder in Sets um. Sets haben den Vorteil, dass in Sets die | |
# Reihenfolge völlig egal ist und wir coole Funktionen zur | |
# Verfügung haben um zu testen, ob ein Set eine Teilmenge von | |
# einem anderen Set ist. | |
if set([k1, k2]).issubset(set(familie)): | |
return True | |
return False | |
# Aktuell kann sich dein Skript in eine Endlosschleife verrennen, wenn es | |
# in eine Situation kommt, in der Wichtel=Kind gilt, es aber keine andere | |
# Möglichkeit mehr gibt. Meine Version erkennt das und probiert dann das | |
# ganze nochmal. Dafür benutze ich eine Endlosschleife, aus der dann aus- | |
# gebrochen wird (mit break), wenn es geklappt hat | |
while True: | |
# Lege eine Liste aller Kinder an, die noch "verfügbar" sind um | |
# beschenkt zu werden. Zu Beginn sind das natürlich alle. Aber wir | |
# dürfen nicht einfach | |
# unbeschenkt = kinder | |
# sagen, weil das sonst die SELBE Liste ist und wenn wir aus der | |
# einen ein Element entfernen, verschwindet es aus der anderen auch. | |
# Daran muss man sich echt gewöhnen... daher kopieren wir es. | |
unbeschenkt = copy.copy(kinder) | |
fehlgeschlagen = False | |
# Jetzt gehen wir alle Kinder durch und entscheidem, wem das Kind | |
# etwas schenkt. | |
for kind in kinder: | |
# Wir stellen zunächst eine Liste der in Frage kommenden Kinder auf. | |
# Das sind alle außer dem Kind selbst und seinen Geschwistern, die | |
# noch unbeschenkt sind. Ich verwende hierzu eine sogenannte List | |
# Comprehension, in meinen Augen eines der coolsten Dinge an Python. | |
# Wenn man sich einmal reingedacht hat, wie die funktionieren, | |
# kann man damit tolle Dingen tun. | |
moeglich = [ | |
k for k in unbeschenkt if k != kind and not sind_geschwister(k, kind) | |
] | |
if not moeglich: | |
print("Klappt nicht. Und nochmal...") | |
# Die Liste der möglichen Kinder ist leer, wir haben uns verrant. | |
# Nochmal von vorne! Das ist nicht ganz einfach, weil wir hier | |
# zwei verschachtelte Schleifen haben. Wir setzten eine Variable, | |
# damit die äußere Schleife weiß, wo wir gelandet sind und sich | |
# entsprechend verhalten kann. | |
fehlgeschlagen = True | |
# Dann brechen wir aus der inneren Schleife aus. | |
break | |
wichtel = random.choice(moeglich) | |
wichteldict[kind] = wichtel | |
unbeschenkt.remove(wichtel) | |
print(kind, "schenkt", wichtel) | |
# So, die innere Schleife ist fertig. Hat es geklappt? | |
if not fehlgeschlagen: | |
# Ja? Dann sind wir fertig für heute. | |
break | |
# Nein? dann geht unsere Endlosschleife von vorne los. | |
print(wichteldict) | |
print(len(wichteldict)) | |
print(len(kinder)) | |
# Test | |
list1 = [] | |
for value in wichteldict.values(): | |
if value not in list1: | |
list1.append(value) | |
elif value in list1: | |
print("Doppelt:", value) | |
print(len(list1)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment