Skip to content

Instantly share code, notes, and snippets.

@raphaelm
Forked from P3nny/wichteln.py
Last active November 6, 2022 15:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raphaelm/3e91e2bfb529e2c6252b to your computer and use it in GitHub Desktop.
Save raphaelm/3e91e2bfb529e2c6252b to your computer and use it in GitHub Desktop.
Wichtel-Programm für die Familienweihnachtsfeier
# -*- 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