Grundlagen, Runde 2#

Über diese Aufgaben#

Die Aufgaben vermitteln einen Eindruck, wie typische praktische kleine Problemstellungen aussehen, die man am Ende von Runde 2 (etwa nach den ersten 10 Wochen) lösen können sollte.

Diese Seite liegt in zwei Versionen vor (die man nur im Detail unterscheiden kann – genaues Hinschauen erforderlich):

Aufgaben:

Loesung:

Die Aufgaben sind so gestellt, dass sie sich auf Skript-Ebene zunächst mit minimalem technischen Aufwand lösen lassen. Gleichzeitig sind sie offen genug, auch fortgeschrittenere – insbesondere generischere – Lösungsmöglichkeiten zuzulassen. Damit lassenn sie sich auch in Programmier-Praktika einsetzen, bei denen Studierende mit sehr heterogenen Vorkenntnissen teilnehmen: Es gibt kein abschließendes “fertig”, fast immer kann man es auch noch etwas eleganter oder schöner machen.

“Verschachtelte” Listen und Dicts#

Liste von Dicts durchsuchen#

gegeben: eine Liste von Dicts, Beispiel:

hobbies = [
    {'Alice': ['Lesen', 'Reisen'], 'Bob': ['Schwimmen', 'Fotografie']},
    {'Alice': ['Kochen'], 'Charlie': ['Lesen', 'Tanzen']},
    {'Bob': ['Skifahren'], 'David': ['Gitarre']}  
    ]

gesucht:

  • Wer hat ein bestimmtes Hobby, z.b. Lesen?

Aufgabe: Schreiben Sie eine Funktion hobby_person(), die zu einem gegebenen Hobby alle zugehörigen Personen aus hobbies zurückgibt.

def hobby_person(gesucht, dictliste):
    to_return = set()
    for d in dictliste:
        ... # 
            ... # 
                ... # 
    return to_return
# hobby_person("Lesen", hobbies) == {'Alice', 'Charlie'}
  Cell In[2], line 5
    ... #
    ^
IndentationError: unexpected indent

Vereinigungsmenge von Dicts#

gegeben: eine Liste von Dicts, Beispiel:

  • z.B. dlist = [ {'a': 1, 'b': 2, 'c': 3};  d2 = {'b': 2, 'c': 99} ]

d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'b': 2, 'c': 99}
dlist = [d1, d2 ]
print(f"{dlist=}")
dlist=[{'a': 1, 'b': 2, 'c': 3}, {'b': 2, 'c': 99}]

gesucht: ein Dict dlist_union, das für jeden Key alle Values enthält, die es in den dicts dazu gibt!

  • z.B. dlist_union = {'c': {3, 99}, 'a': {1}, 'b': {2}}

Vorgehen:

  • (a) erzeugen Sie ein Set, das alle keys enthält

  • (b) initialisieren Sie dlist_union, dass es etwa so aussieht: { 'a': set(), 'b': set(), ...: ...}

  • (c) füllen Sie dann dlist_union geeignet auf

# a)
allkeys = set()
... # 
# allkeys == {'a', 'b', 'c'}
Ellipsis
# b)
dlist_union = {}
... # 
# dlist_union == {'c': set(), 'a': set(), 'b': set()}
Ellipsis
# c)
for d in dlist:
    ... # 
        ... # 
# dlist_union == {'c': {3, 99}, 'a': {1}, 'b': {2}}
  Cell In[6], line 4
    ... #
    ^
IndentationError: unexpected indent

Aufgabe: In welchen Monaten gibt es (k)einen Feiertag?#

Gegeben: ein Dict Feiertage:

Feiertage = { 'Weihnachten': '24.12', 'Silvester': '31.12', 'Neujahr': '01.01', 
             'Erster Mai': '01.05', 'Tag der Deutschen Einheit': '03.10' } 

gesucht:

  • eine Menge Monate_mit_Feiertag: In welchen Monaten gibt es einen Feiertag?

  • eine Menge Monate_OHNE_Feiertag: In welchen Monaten gibt es keinen Feiertag?

Hinweis: Sie dürfen bei Bedarf gerne die folgende Liste M benutzen.

M = ['01', '02', '03', '04', '05', '06', 
     '07', '08', '09', '10', '11', '12']

Monate_mit_Feiertag = ...
... # 




Monate_mit_Feiertag == {'01', '05', '10', '12'}
False
Monate_OHNE_Feiertag = ...
... # 




Monate_OHNE_Feiertag == {'02', '03', '04', '06', '07', '08', '09', '11'}
False

Aufgabe: Familienmitglieder und Rollen#

Gegeben ist ein Dict von Dicts, das zu Familien die Familienmitglieder und ihre Rollen angibt:

Familien = { 'Maier' : { 'Martin': 'Vater', 'Monika': 'Mutter', 
                        'Maria': 'Tochter', 'Merle': 'Tochter' },
            'Schulz': { 'Sabine': 'Mutter', 'Sarah': 'Tochter', 'Sieglinde': 'Oma' }}

gesucht:

  • ein Dict Familie_Groesse : Wie viele Familienmitglieder hat jede Familie?

  • eine Menge Alle_Rollen: Welche Rollen gibt es in diesen Familien?

  • eine Liste Alle_Toechter: Wie heißen die Töchter?

Familie_Groesse = ...
... # 




Familie_Groesse == {'Maier': 4, 'Schulz': 3}
False
Alle_Rollen = ...
... # 




Alle_Rollen == {'Mutter', 'Oma', 'Tochter', 'Vater'}
False
Alle_Toechter = ...
... # 




Alle_Toechter == ['Maria', 'Merle', 'Sarah']
False

Dictionary invertieren#

gegeben:

  • ein Dictionary von Postleitzahlen, Beispiel:

d = { "Landshut": [ 84030, 84032, 84028 ], "Dingolfing": [ 84130 ] }

gesucht:

  • ein inverses Dictionary, mit dem man bei einer gegebenen Postleitzahl den zugehörigen Ort nachschlagen kann.

d_invers = ...
... # 
d_invers == {84028: 'Landshut', 84130: 'Dingolfing', 84030: 'Landshut', 84032: 'Landshut'} # Reihenfolge ist egal
False

Aufgabe: Auswahl von Zahlen aus Liste#

Gegeben:

  • eine Liste von Zahlen, z.B. l = [ 1, 1, 2, 3, 5, 8, 13, ... ].

Gesucht:

  • eine Auswahl-Liste l2 aller geraden Zahlen aus der Liste l.

Lösen Sie mit List Comprehension!

# Kontext
l = [ 1, 1, 2, 3, 5, 8, 13 ]
l2 = []
# Ihre Lösung

... # 

print(l2)
[]
# Test
l2 == [2, 8]
False

Aufgabe: Auswahl aus Liste mit Varianten#

Gegeben:

  • eine Liste von Strings, z.B.

      l = [ 1, 1, 2, 3, "Hallo" ]
    

Gesucht:

  • eine Auswahl-Liste l2 aller Werte aus der Liste l:

    • falls das Listenelement eine Zahl ist, ist der Wert die Zahl selbst

    • falls das Listenelement ein String ist, ist der Wert die Länge des Strings.

# Kontext
l = [ 1, 2, 3.14, "Hallo" ]
# Ihre Lösung

l2 = []

for  x in l:
    ... # 
    ... # 
    ... # 

l2
[]
# test
l2 == [1, 2, 3.14, 5]
False

Aufgabe: Würfelsummen#

Mit 2 Würfeln können wir alle Würfelsummen zwischen 2 und 12 würfeln.

gegeben:

  • Wir würfeln 100 mal mit 2 Würfeln, addieren die Würfel, und zählen, wie oft jede Würfelsumme auftaucht:

    w = {4:4, 7:16, 6:17, 8:15, 12:3, 9:19, 11:9, 10:9, 5:8}
    

Gesucht:

  • Menge pech_gehabt: Welche Würfelsummen kommen trotz 100 mal würfeln nicht vor?

Lösen Sie mit Mengen-Operatoren und mit Set-Comprehension!

# Kontext
w = {4:4, 7:16, 6:17, 8:15, 12:3, 9:19, 11:9, 10:9, 5:8}
pech_gehabt = set()
# hier Ihre Lösung
# Mengen
... # 


print(pech_gehabt)
set()
# hierIhre Lösung
# Comprehension
... # 

print(pech_gehabt)
set()
# Test
pech_gehabt == {2, 3}
False

Aufgabe: häufigste Würfelsummen#

gegeben:

  • Ein Dict aus Aufgabe 3a: Gewürfelt wird sehr oft mit 2 Würfeln; für jede Würfelsummen wird gezählt, wie oft sie auftritt.

gesucht:

  • w_max: Welche Würfelsumme fällt am häufigsten und wie oft?

Hinweis: Falls mehrere Würfelsummen am häufigsten auftreten ist die Lösung nicht eindeutig. Es darf dann eine beliebige dieser Würfelsummen genannt werden.

# Kontext
w = {4: 4, 7: 16, 6: 17, 8: 15, 12: 3, 9: 19, 11: 9, 10: 9, 5: 8}
# hier Ihre Lösung:
# ergänzen Sie den Code!

w_max = 0
max = 0

for k,v in w.items():
    if v > max:
        ... # 
        ... # 

print( f"{w_max=}, {max=}")
w_max=0, max=0
# Test
w_max == 9, max == 19
(False, False)

Zusatzfrage (2 Zusatzpunkte):

  • Welche Würfelsumme erwarten Sie häufiger: die 3 oder die 7? Wie viel mal häufiger? (mit kurzer Begründung)

  • Welche Verteilung von Würfelsummen erwarten Sie?

Aufgabe: Funktionstabelle#

Sei fib(x) der der x-te Wert der Fibonacci-Folge [ 1, 1, 2, 3, 5, 8, 13, ... ] also z.B. fib(6) == 13. (Wie in Python üblich hat das erste Element den Index 0)

Wenn man sehr häufig auf diese Werte zugreifen will bietet es sich an, für diese Funktion eine Funktionstabelle zu erstellen, d.h. technisch ein Dict zu erstellen:

 fib_dict = {0: 1, # entsprict fib(0) == 1
             1: 1, 
             2: 2, 
             3: 3, 
             4: 5, 
             5: 8, 
             6: 13, # entspricht fib(6) == 13
             # usw
             }

Dieses Dict kann man dann statt einer Funktion verwenden, Beispiel: fib_dict[6] == 13.

Aufgabe:

  • Vervollständigen Sie die folgende Funktion generate_fib_dict(n), die für ein gegebenes n solch ein fib_dict erzeugt.

# hier Ihre Lösung:
# ergänzen Sie den Code!

def generate_fib_dict(n):
    ergebnis = { 0:1, 1:1 }
    for x in range(2, n+1):
    ... # 
        
    return ergebnis
  Cell In[30], line 7
    ... #
    ^
IndentationError: expected an indented block after 'for' statement on line 6
# exemplarische Aufrufe
for i in range(7):
    print(generate_fib_dict(i))
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[31], line 3
      1 # exemplarische Aufrufe
      2 for i in range(7):
----> 3     print(generate_fib_dict(i))

NameError: name 'generate_fib_dict' is not defined
# Test für n==6:
generate_fib_dict(6) == {0: 1, 1: 1, 2: 2, 3: 3, 4: 5, 5: 8, 6: 13}
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[32], line 2
      1 # Test für n==6:
----> 2 generate_fib_dict(6) == {0: 1, 1: 1, 2: 2, 3: 3, 4: 5, 5: 8, 6: 13}

NameError: name 'generate_fib_dict' is not defined

Aufgabe: Sportarten von Menschen#

gegeben:

  • ein Dict sport2, das über die Sportarten von Menschen Auskunft gibt.

gesucht:

  • ein Dict mensch_sport, das für jede Sportart angibt, von wem sie ausgeübt wird.

# Kontext
sport2 = {'Anna':    ['Lesen', 'Joggen', 'Musik'],
          'Ben':     ['Musik', 'Joggen', 'Schwimmen'],
          'Charlie': ['Lesen', 'Musik']}
# hier Ihre Lösung:
# ergänzen Sie den Code!

mensch_sport = {}

for mensch, sportarten in sport2.items():
    ... # 
        ... # 
            ... # 
        ... # 

# was kommt 'raus?
mensch_sport
  Cell In[34], line 8
    ... #
    ^
IndentationError: unexpected indent
# Test
mensch_sport == {'Lesen': ['Anna', 'Charlie'],
 'Joggen': ['Anna', 'Ben'],
 'Musik': ['Anna', 'Ben', 'Charlie'],
 'Schwimmen': ['Ben']}
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[35], line 2
      1 # Test
----> 2 mensch_sport == {'Lesen': ['Anna', 'Charlie'],
      3  'Joggen': ['Anna', 'Ben'],
      4  'Musik': ['Anna', 'Ben', 'Charlie'],
      5  'Schwimmen': ['Ben']}

NameError: name 'mensch_sport' is not defined

Aufgabe: zu Dict einen reverted Index bilden#

gegeben:

  • ein Dict d, das für die Tage einer Woche die Maximaltemperatur zeigt:

    d = { "Mo": 17, "Di": 18, "Mi": 16, "Do": 15, "Fr": 16, "Sa": 17, "So": 17 }

gesucht:

  • ein Dict d2, das für jede Maximaltemperatur eine Liste von Tagen hat, die diese Temperatur hatten. (Man benötigt so etwas regelmäßig für Such-Anwendungen).

# Kontext
d = { "Mo": 17, "Di": 18, "Mi": 16, "Do": 15, "Fr": 16, "Sa": 17, "So": 17 }

# Ihre Lösung
d2 = {}

# Lösung 1 aus der Vl, "Grundstruktur Listenbearbeitung"
for tag, temperatur in d.items():
    if not temperatur in d2: # d2.keys()
        d2[temperatur] = []
    d2[temperatur].append(tag)
    
# andere Lösung: vorher schon initialisieren
d2 = {temperatur: [] for temperatur in set(d.values()) }
# jetzt gibt es schon alle keys, mit leeren Listen initialisiert
for tag, temperatur in d.items():
    d2[temperatur].append(tag)

# ganz böse, schlechte Comprehension
# wegen Nebeneffekt!
# wegwerfen = [ d2[temperatur].append(tag) for tag, temperatur in d.items()  ]

# Ihr Ergebnis
d2
# Test
d2 == {17: ['Mo', 'Sa', 'So'], 18: ['Di'], 16: ['Mi', 'Fr'], 15: ['Do']}

Aufgabe: zip() simuieren#

gegeben:

  • zwei gleich lange Listen Wörter und Ziffern; in Liste Wörter kommt kein Wert doppelt vor.

gesucht:

  • ein Dict wort_zip, das zu jedem Wort die zugehörige Zahl angibt

Gesucht sind zwei verschiedene Lösungen, mit und ohne zip()

# Lösung 1, mit zip()
# Kontext
Wörter = [ "eins", "oans", "zwei", "zwoa", "adin" ]
Zahl = [1, 1, 2, 2, 1 ] 
wort_zahl = {}

# Ihre Lösung
wort_zahl = dict( zip(Wörter, Zahl) )
#wort_zahl = list( zip(Wörter, Zahl) )
#wort_zahl = tuple( zip(Wörter, Zahl) )

# Ihr Ergebnis
wort_zahl
# Test
wort_zahl == {'eins': 1, 'oans': 1, 'zwei': 2, 'zwoa': 2, 'adin': 1}
# Lösung 2, ohne zip()
# Kontext wie oben
Wörter = [ "eins", "oans", "zwei", "zwoa", "adin" ]
Zahl = [1, 1, 2, 2, 1 ] 
wort_zahl = {}

# Ihre Lösung
# indirektes Durchgehen mit Index
for i in range( len(Wörter) ):
    wort_zahl[ Wörter[i] ] = Zahl[i]

# Ihr Ergebnis
wort_zahl
# Test
wort_zahl == {'eins': 1, 'oans': 1, 'zwei': 2, 'zwoa': 2, 'adin': 1}