Rekursive Funktionsaufrufe
Analyse von Firmengehältern
Für eine bundesweite Untersuchung von Jahresgehältern mittelständischer Unternehmen stellen einige Firmen ihre Gehaltslisten zur Verfügung. Um diese Listen effektiv analysieren und verarbeiten zu können, wollen wir uns einige Funktionen definieren, die die Arbeit mit den Listen vereinfachen.
Aufgabe 1: Liste automatisiert füllen
In rein funktionalen Sprachen gibt es keine Schleifenstrukturen wie while oder for. Um unsere gewünschten Funktionen in späteren Aufgaben definieren zu können, benötigen wir daher eine andere Möglichkeit, um die Listen zu durchlaufen: Rekursion.
Die Funktion list-fill
erhält als Übergabedatum eine Zahl $n \in \mathbb{N}$ und soll eine Liste $(list\ 0\ ...\ n)$
produzieren. Hierfür wurde zusätzlich die Hilfsfunktion create
erstellt. Allerdings liefert die Funktion
noch nicht die gewünschten Ergebnisse.
(a) Analysiere die beiden Funktionen list-fill
und create
und verbessere diese an
geeigneter Stelle. Die gewünschte Verarbeitung der Funktionen lässt sich mit Änderungen in einer Zeile erreichen.
;Gibt eine Liste von 0 bis n zurück
(: list-fill (natural -> (list-of natural)))
(check-expect (list-fill 3) (list 0 1 2 3))
(define list-fill
(lambda (n)
(create empty n)))
;Fügt an den Beginn einer Liste die Zahlen n bis 0 an
(: create ((list-of natural) natural -> (list-of natural)))
(check-expect (create empty 3) (list 0 1 2 3))
(check-expect (create (list 3) 2) (list 0 1 2 3))
(define create
(lambda (l n)
(if [> 1 n]
(create (cons n l) (- n 1))
(cons n l))))
Aufgabe 2: Median-Bestimmung mittels Index
Zur Analyse der Gehälter legt Firma-A eine geordnete Liste mit den Jahresgehältern der 30 Mitarbeitenden vor:
(define firmaA
(list 21000 28000 28000 34000 34000 35000 35000 38000 38000 38000 38000 38000 38000 50000 50000 50000 50000 50000 50000 50000
51000 57000 57000 57000 60000 60000 60000 75000 110000 110000))
Da der Medianwert im Gegensatz zum Mittelwert robust gegenüber extremen Ausreißern ist, wird dieser
häufig zur Analyse von Gehältern genutzt.
Der Medianwert stellt den in der Mitte liegenden Wert einer geordneten Liste dar. Zum Beispiel der Wert $2$ bei der Liste $(list\ 1\ 2\ 3)$. Wenn es keine eindeutige Mitte gibt (bei einer Liste von gerader Länge), wird der Mittelwert der beiden mittleren Werte berechnet. Zum Beispiel der Wert $2.5$ bei der Liste $(list\ 1\ 2\ 3\ 4)$.
(a) Zur Bestimmung des Medianwerts ist es hilfreich, wenn wir Elemente einer Liste anhand ihres Index selektieren können.
Ergänze die fehlenden Segmente ...
in der untenstehenden Funktion.
;Gibt den Wert einer Liste an Index i zurück
(: select-index ((list-of any) natural -> any))
...
(define select-index
(lambda (l i)
(cond
([> (+ i 1) (length l)] empty)
([= i 0] ...)
(else ...))))
(b) Bestimme den Medianwert der Jahresgehälter von Firma-A. Ob du hierfür eine eigene allgemeine Funktion zur Bestimmung eines Medianwerts schreibst oder einfach einen Ausdruck in die REPL, ist dir überlassen.
Aufgabe 3: Die ersten und letzten n Elemente einer Liste
Ebenfalls interessieren uns Informationen wie: "Die $n$ bestverdienenden Personen haben folgende Gehälter... ". Wir möchten hierzu beispielsweise die letzten oder ersten 10 Einträge einer Liste erhalten.
(a) Implementiere die Funktion takeLast
, die die letzten $n$ Elemente einer Liste als Liste zurückgibt
(b) Implementiere die Funktion takeFirst
, die die ersten $n$ Elemente einer Liste als Liste zurückgibt
(c) Bestimme die drei höchsten und die fünf geringsten Jahresgehälter in Firma-A.
Tipp: In dieser Aufgabe können Hilfsfunktionen, wie in Aufgabe 1 vorgestellt, nützlich sein.
Tipp: Mit der Funktion reverse
lassen sich Listen in Racket invertieren.
Diese Funktion kann für diese Aufgabe nützlich sein, ist jedoch nicht zwingend notwendig.