Compare commits
10 Commits
f4a0576f3c
...
1121c6a171
Author | SHA1 | Date | |
---|---|---|---|
1121c6a171 | |||
9ea341183d | |||
801b641fb2 | |||
f3e49c96cd | |||
f89435117a | |||
56c0d4bec3 | |||
407389a5cb | |||
da878ec3e6 | |||
8ed82e01aa | |||
23f4c7be52 |
22
README.md
22
README.md
@@ -1,33 +1,33 @@
|
|||||||
# Übungsaufgaben zur EidP (WS2023) Klausur
|
# Übungsaufgaben zur EidP (WS2023) Klausur
|
||||||
|
|
||||||
Alle Aufgaben hier behandeln Konzepte aus der Vorlesung **Einführung in die Programmierung** von der Albert-Ludwig-Universität Freiburg. Hierbei handelt es sich um selbsterstellte Aufgaben der EidP-Tutoren [**Nils Pukropp**](mailto:nils@narl.io) und [**Daniel Mironow**](mailto:mail@danielmironov.dev) die bei der Vorbereitung auf die Klausur helfen sollen.
|
Alle Aufgaben hier behandeln Konzepte aus der Vorlesung **Einführung in die Programmierung** von der Albert-Ludwig-Universität Freiburg. Hierbei handelt es sich um selbsterstellte Aufgaben der EidP-Tutoren [**Nils Pukropp**](mailto:nils@narl.io) und [**Daniel Mironow**](mailto:mail@danielmironov.dev) die bei der Vorbereitung auf die Klausur helfen sollen. :D
|
||||||
|
|
||||||
## Reihenfolge der Themen
|
## Reihenfolge der Themen
|
||||||
|
|
||||||
Es gibt keine direkte Reihenfolge, lediglich Themen die sich teilweise überschneiden. Dennoch gibt es eine Reihenfolge nach Wichtigkeit der Themen:
|
Es gibt keine direkte Reihenfolge, lediglich Themen die sich teilweise überschneiden. Dennoch gibt es eine Reihenfolge nach Wichtigkeit der Themen:
|
||||||
|
|
||||||
- [Grundkonzept Schleifen (`for`, `while`, ...)](./loops)
|
- [Grundkonzept Schleifen (`for`, `while`, ...)](src/branch/main/loops)
|
||||||
- allgemeine Knobelaufgaben rund um Schleifen
|
- allgemeine Knobelaufgaben rund um Schleifen
|
||||||
- Einfach mit ein paar schwierigeren Aufgaben zum Nachdenken
|
- Einfach mit ein paar schwierigeren Aufgaben zum Nachdenken
|
||||||
- [Zeichenketten (Strings `str`)](./strings)
|
- [Zeichenketten (Strings `str`)](src/branch/main/strings)
|
||||||
- allgemeine Knobelaufgaben rund um `str`
|
- allgemeine Knobelaufgaben rund um `str`
|
||||||
- Einfach mit ein paar schwierigeren Aufgaben zum Nachdenken
|
- Einfach mit ein paar schwierigeren Aufgaben zum Nachdenken
|
||||||
- [Dataclasses (OOP `@dataclass`)](./dataclasses)
|
- [Dataclasses (OOP `@dataclass`)](src/branch/main/dataclasses)
|
||||||
- Objekt orientierte Programmierung mit `@dataclass`
|
- Objekt orientierte Programmierung mit `@dataclass`
|
||||||
- Einfach (Auswendig lernen)
|
- Einfach (Auswendig lernen)
|
||||||
- [Pattern Matching (`match`)](./pattern_matching)
|
- [Pattern Matching (`match`)](src/branch/main/pattern_matching)
|
||||||
- Intensive Übungen zu `match`
|
- Intensive Übungen zu `match`
|
||||||
- Mittel (Auswendig lernen, aber erfordert grundlegende Konzepte)
|
- Mittel (Auswendig lernen, aber erfordert grundlegende Konzepte)
|
||||||
- [Typvariabeln (Generics `[T]`)](./generics)
|
- [Typvariabeln (Generics `[T]`)](src/branch/main/generics)
|
||||||
- Platzhalter Variabeln um generische Typannotation umzusetzen
|
- Platzhalter Variabeln um generische Typannotation umzusetzen
|
||||||
- Mittel (Auswendig lernen, aber erfordert grundlegende Konzepte)
|
- Mittel (Auswendig lernen, aber erfordert grundlegende Konzepte)
|
||||||
- [Rekursion (Tree)](./recursion)
|
- [Rekursion (Tree)](src/branch/main/recursion)
|
||||||
- Sich selbst aufrufende Funktionen
|
- Sich selbst aufrufende Funktionen
|
||||||
- Schwer, da das Konzept etwas verwirrend ist, aber gut für schnelle Punkte in der Klausur!
|
- Schwer, da das Konzept etwas verwirrend ist, aber gut für schnelle Punkte in der Klausur!
|
||||||
- [Generator](./generator)
|
- [Generator](src/branch/main/generator)
|
||||||
- Erzeugen von Iteratoren auf die seltsame Python Art und Weise!
|
- Erzeugen von Iteratoren auf die seltsame Python Art und Weise!
|
||||||
- Mittel, da das Konzept etwas seltsam ist. Muss man einfach ein paar mal machen!
|
- Mittel, da das Konzept etwas seltsam ist. Muss man einfach ein paar mal machen!
|
||||||
- [Funktionale Programmierung](./functional_programming)
|
- [Funktionale Programmierung](src/branch/main/functional_programming)
|
||||||
- Programmieren-Paradigma bei dem der Programmfluss durch Funktionen bestimmt wird!
|
- Programmieren-Paradigma bei dem der Programmfluss durch Funktionen bestimmt wird!
|
||||||
- Schwer, da das Konzept etwas schwer zu verstehen ist und viele Grundlagen vorraussetzt
|
- Schwer, da das Konzept etwas schwer zu verstehen ist und viele Grundlagen vorraussetzt
|
||||||
|
|
||||||
@@ -45,9 +45,11 @@ Es gibt keine direkte Reihenfolge, lediglich Themen die sich teilweise überschn
|
|||||||
- Könnt auch gerne nachfragen wenn was nicht funktioniert!
|
- Könnt auch gerne nachfragen wenn was nicht funktioniert!
|
||||||
- Dann könnt ihr einfach die Tests mit `pytest` in der Konsole aufrufen
|
- Dann könnt ihr einfach die Tests mit `pytest` in der Konsole aufrufen
|
||||||
- Schlagen die Tests fehl sieht das so aus:
|
- Schlagen die Tests fehl sieht das so aus:
|
||||||
|
|
||||||

|

|
||||||
- Hier sagt euch Pytest auch was alles nicht an eurem Code funktioniert
|
- Hier sagt euch Pytest auch was alles nicht an eurem Code funktioniert
|
||||||
- Funktioniert euer Code sieht das so aus:
|
- Funktioniert euer Code sieht das so aus:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Kontakt
|
## Kontakt
|
||||||
@@ -59,4 +61,4 @@ Es gibt keine direkte Reihenfolge, lediglich Themen die sich teilweise überschn
|
|||||||
- Daniel Mironow (Tutor)
|
- Daniel Mironow (Tutor)
|
||||||
- [E-Mail](mailto:mail@danielmironov.dev)
|
- [E-Mail](mailto:mail@danielmironov.dev)
|
||||||
- [Discord](https://discord.com/users/236939658301407243)
|
- [Discord](https://discord.com/users/236939658301407243)
|
||||||
- [Discord-Server](https://discord.gg/naeprrX7hB)
|
- [Discord-Server](https://discord.gg/naeprrX7hB)
|
||||||
|
1
generator/primes/README.md
Normal file
1
generator/primes/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# primes generator
|
0
generator/primes/primes.py
Normal file
0
generator/primes/primes.py
Normal file
29
generator/primes/solution/primes.py
Normal file
29
generator/primes/solution/primes.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from typing import Iterator
|
||||||
|
|
||||||
|
|
||||||
|
def is_prime(n: int) -> bool:
|
||||||
|
if n < 2:
|
||||||
|
return False
|
||||||
|
for d in range(2, n // 2 + 1):
|
||||||
|
if n % d == 0:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def primes() -> Iterator[int]:
|
||||||
|
num = 2
|
||||||
|
while True:
|
||||||
|
if is_prime(num):
|
||||||
|
yield num
|
||||||
|
num += 1
|
||||||
|
|
||||||
|
|
||||||
|
def prime_factorize(n: int) -> Iterator[int]:
|
||||||
|
it = primes()
|
||||||
|
num = n
|
||||||
|
while num > 1:
|
||||||
|
if num % (prime := next(it)) != 0:
|
||||||
|
continue
|
||||||
|
num //= prime
|
||||||
|
it = primes()
|
||||||
|
yield prime
|
51
generator/primes/solution/test_primes.py
Normal file
51
generator/primes/solution/test_primes.py
Normal file
File diff suppressed because one or more lines are too long
1
list_comprehensions/README.md
Normal file
1
list_comprehensions/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# List Comprehensions
|
36
list_comprehensions/comprehensions.py
Normal file
36
list_comprehensions/comprehensions.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
def divisible_by_7(n: int) -> list[int]:
|
||||||
|
"""
|
||||||
|
Returns a list of all numbers till 'n' that are divisible by '7'
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def contains_3(n: int) -> list[int]:
|
||||||
|
"""
|
||||||
|
Returns a list of all numbers that contain the digit '3' in them
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def count_spaces(string: str) -> int:
|
||||||
|
"""
|
||||||
|
Count the spaces in a string
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def remove_vowels(string: str) -> str:
|
||||||
|
"""
|
||||||
|
Remove all vowels from the string
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def word_lengths(string: str) -> dict[str, int]:
|
||||||
|
"""
|
||||||
|
Create a dictionary of all words with their lengths
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def prime_numbers(n: int) -> list[int]:
|
||||||
|
"""
|
||||||
|
Returns a list of all prime numbers till 'n' (HARD)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
0
list_comprehensions/solution/README.md
Normal file
0
list_comprehensions/solution/README.md
Normal file
41
list_comprehensions/solution/comprehensions.py
Normal file
41
list_comprehensions/solution/comprehensions.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
def divisible_by_7(n: int) -> list[int]:
|
||||||
|
"""
|
||||||
|
Returns a list of all numbers till 'n' that are divisible by '7'
|
||||||
|
"""
|
||||||
|
return [x for x in range(1, n) if x % 7 == 0]
|
||||||
|
|
||||||
|
|
||||||
|
def contains_3(n: int) -> list[int]:
|
||||||
|
"""
|
||||||
|
Returns a list of all numbers that contain the digit '3' in them
|
||||||
|
"""
|
||||||
|
return [x for x in range(1, n) if '3' in str(x)]
|
||||||
|
|
||||||
|
|
||||||
|
def count_spaces(string: str) -> int:
|
||||||
|
"""
|
||||||
|
Count the spaces in a string
|
||||||
|
"""
|
||||||
|
return len([ch for ch in string if ' ' == ch])
|
||||||
|
|
||||||
|
|
||||||
|
def remove_vowels(string: str) -> str:
|
||||||
|
"""
|
||||||
|
Remove all vowels from the string
|
||||||
|
"""
|
||||||
|
return ''.join([ch for ch in string if ch.lower() not in 'aeiou'])
|
||||||
|
|
||||||
|
|
||||||
|
def word_lengths(string: str) -> dict[str, int]:
|
||||||
|
"""
|
||||||
|
Create a dictionary of all words with their lengths
|
||||||
|
"""
|
||||||
|
return {word: len(word) for word in string.split(' ') if len(word) > 0}
|
||||||
|
|
||||||
|
|
||||||
|
def prime_numbers(n: int) -> list[int]:
|
||||||
|
"""
|
||||||
|
Returns a list of all prime numbers till 'n' (HARD)
|
||||||
|
"""
|
||||||
|
return [x for x in range(2, n) if all(x % y != 0 for y in range(2, x))]
|
||||||
|
|
77
list_comprehensions/test_comprehensions.py
Normal file
77
list_comprehensions/test_comprehensions.py
Normal file
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
# [Primzahlen](./primes.py)
|
# [Primzahlen](src/branch/main/loops/primes/primes.py)
|
||||||
|
|
||||||
## `is_prime`
|
## `is_prime`
|
||||||
|
|
||||||
@@ -28,4 +28,4 @@ Schreiben Sie nun folgende Funktion `prime_factorize(n: int) -> list[int]` welch
|
|||||||
|
|
||||||
Tipp: Sie können hierfür die Funktionen `is_prime` und `next_prime` verwenden
|
Tipp: Sie können hierfür die Funktionen `is_prime` und `next_prime` verwenden
|
||||||
|
|
||||||
## [Hier gehts zu den Lösungen](./solution/primes.py)
|
## [Hier gehts zu den Lösungen](src/branch/main/loops/primes/solution)
|
||||||
|
84
loops/sort/README.md
Normal file
84
loops/sort/README.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# [Sortierte Datenstrukturen](src/branch/main/loops/sort/sort.py)
|
||||||
|
|
||||||
|
## `selection_sort`
|
||||||
|
|
||||||
|
**Selection Sort** basiert auf dem Konzept durch jedes Element in einer Liste zu gehen um dann das kleineste Element in den übrigen zu suchen und mit dem aktuellen Element zu tauschen.
|
||||||
|
|
||||||
|
- Wichtig ist dass dabei die übergebene Liste nicht verändert wird und eine neue sortierte erstellt wird
|
||||||
|
- Manuell erstellen mit loop oder `deepcopy`
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
```
|
||||||
|
arr[] = 64 25 12 22 11
|
||||||
|
|
||||||
|
// Find the minimum element in arr[0...4]
|
||||||
|
// and place it at beginning
|
||||||
|
11 25 12 22 64
|
||||||
|
|
||||||
|
// Find the minimum element in arr[1...4]
|
||||||
|
// and place it at beginning of arr[1...4]
|
||||||
|
11 12 25 22 64
|
||||||
|
|
||||||
|
// Find the minimum element in arr[2...4]
|
||||||
|
// and place it at beginning of arr[2...4]
|
||||||
|
11 12 22 25 64
|
||||||
|
|
||||||
|
// Find the minimum element in arr[3...4]
|
||||||
|
// and place it at beginning of arr[3...4]
|
||||||
|
11 12 22 25 64
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Hilfe 1: Pseudocode</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
for e_i in xs
|
||||||
|
kleinstes_e = e_i
|
||||||
|
for e_j in xs mit: j = i + 1
|
||||||
|
if kleinstes_e > e_j
|
||||||
|
kleinstes_e = e_j
|
||||||
|
vertausche e_i und kleinstes_e
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## `binary_search`
|
||||||
|
|
||||||
|
Hierbei handelt es sich um einen Algorithmus welcher die Position von einem Wert in einem sortierten Array schnell findet.
|
||||||
|
|
||||||
|
Beispiele:
|
||||||
|
```python
|
||||||
|
binary_search([1, 2, 3, 4, 5], 4) # 3, was der index von 4 ist
|
||||||
|
binary_search(["a", "b", "c", "d"], "b") # 1, was der index von "b" ist
|
||||||
|
```
|
||||||
|
|
||||||
|
- Dazu definieren wir eine linke Grenze `left` mit dem Anfangswert `0` und eine rechte Grenze `right` mit dem Anfangswert `len(xs) - 1`, damit können wir unser gesuchtes Element immer weiter eingrenzen.
|
||||||
|
- Jetzt wissen wir durch die Sortierung dass `left <= right` sein muss.
|
||||||
|
- Also gehen wir jetzt durch unsere Liste und berechnen die Mitte `middle` von `left` und `right` aus und vergleichen diese mit unserem gesuchten Wert.
|
||||||
|
- Ist `middle` kleiner als unser Wert dann können wir `left = middle + 1` setzen
|
||||||
|
- Ist `middle` größer als unser Wert dann können wir `right = middle - 1` setzen
|
||||||
|
- Sonst haben wir unseren Wert, nämlich `middle`, gefunden und können diesen zurückgeben
|
||||||
|
- Wenn der Wert nicht existiert wird `None` zurückgegeben
|
||||||
|
- Für leere Listen soll auch `None` zurückgegeben werden
|
||||||
|
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Hilfe 1: Pseudocode</summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
linker_index = 0
|
||||||
|
rechter_index = länge - 1
|
||||||
|
solange linker_index <= rechter_index dann
|
||||||
|
mitte = (linker_index + rechter_index) / 2
|
||||||
|
Wenn Liste[mitte] < gesuchter Wert dann
|
||||||
|
linker_index = mitte + 1
|
||||||
|
Wenn Liste[mitte] > gesuchter Wert dann
|
||||||
|
rechter_index = mitte - 1
|
||||||
|
Sonst
|
||||||
|
return Liste[mitte]
|
||||||
|
return Nichts
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## [Hier gehts zur Lösung](src/branch/main/loops/sort/solution)
|
87
loops/sort/solution/README.md
Normal file
87
loops/sort/solution/README.md
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# Solution
|
||||||
|
|
||||||
|
## `selection_sort`
|
||||||
|
|
||||||
|
Zunächst müssen wir eine neue Liste mit den selben Elementen erstellen, am schnellsten geht das mit `copy.deepcopy` welche eine vollständige Copie erstellt.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
xss = deepcopy(xs)
|
||||||
|
```
|
||||||
|
|
||||||
|
Wir müssen durch jedes Element gehen, also
|
||||||
|
|
||||||
|
```python
|
||||||
|
for i in range(len(xss)):
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
Nun wollen wir in den übrigen Elementen ($j = i + 1$) das kleinste finden
|
||||||
|
|
||||||
|
```python
|
||||||
|
for i in range(len(xss)):
|
||||||
|
min_i = i # index vom kleinsten Element,
|
||||||
|
# das aktuelle i falls dieses schon das kleinste ist
|
||||||
|
for j in range(i + 1, len(xss)):
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Jetzt vergleichen wir nur noch jedes j-te Element mit dem aktuellen kleinsten
|
||||||
|
|
||||||
|
```python
|
||||||
|
for i in range(len(xss)):
|
||||||
|
min_i = i # index vom kleinsten Element,
|
||||||
|
# das aktuelle i falls dieses schon das kleinste ist
|
||||||
|
for j in range(i + 1, len(xss)):
|
||||||
|
if xss[j] < xss[min_i]:
|
||||||
|
min_i = j # kleineres element gefunden
|
||||||
|
```
|
||||||
|
|
||||||
|
Nun können wir einfach das i-te mit dem min_i vertauschen (entweder ist es i oder wir haben ein kleineres gefunden)
|
||||||
|
|
||||||
|
```python
|
||||||
|
xss[i], xss[min_i] = xss[min_i], xss[i] # tauschen i mit min_i
|
||||||
|
```
|
||||||
|
|
||||||
|
und am Ende können wir `xss` zurückgeben
|
||||||
|
|
||||||
|
```python
|
||||||
|
return xss
|
||||||
|
```
|
||||||
|
|
||||||
|
## `binary_search`
|
||||||
|
|
||||||
|
Hierfür definieren wir zunächst `left = 0` und `right = len(xs) - 1`, dann können wir die Schleifenbedingung definieren als
|
||||||
|
|
||||||
|
```python
|
||||||
|
while left <= right:
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
|
weil sobald diese nicht mehr gilt konnten wir den Wert nicht finden. (Links und Rechts tauschen) und wir können `None` zurückgeben.
|
||||||
|
|
||||||
|
Nun berechnen wir den mittleren Index mit dem integer division (oder auch floor weil es die Zahl hinterm Komma verwirft).
|
||||||
|
|
||||||
|
```python
|
||||||
|
middle = (left + right) // 2
|
||||||
|
```
|
||||||
|
|
||||||
|
Nun müssen wir nur noch `xs[middle]` mit `value` vergleichen
|
||||||
|
|
||||||
|
```python
|
||||||
|
if xs[middle] < value:
|
||||||
|
left = middle + 1
|
||||||
|
elif xs[middle] > value:
|
||||||
|
right = middle - 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Und wenn `xs[middle] == value` ist haben wir unseren Index `middle` gefunden.
|
||||||
|
|
||||||
|
```python
|
||||||
|
if xs[middle] < value:
|
||||||
|
left = middle + 1
|
||||||
|
elif xs[middle] > value:
|
||||||
|
right = middle - 1
|
||||||
|
else:
|
||||||
|
return middle
|
||||||
|
```
|
27
loops/sort/solution/sort.py
Normal file
27
loops/sort/solution/sort.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
from copy import deepcopy
|
||||||
|
from typing import Iterator, Optional
|
||||||
|
|
||||||
|
|
||||||
|
def selection_sort[T](xs: Iterator[T]) -> Iterator[T]:
|
||||||
|
length = len(xs)
|
||||||
|
xss = deepcopy(xs)
|
||||||
|
for i in range(length):
|
||||||
|
min_i = i
|
||||||
|
for j in range(i + 1, length):
|
||||||
|
if xss[j] < xss[min_i]:
|
||||||
|
min_i = j
|
||||||
|
xss[i], xss[min_i] = xss[min_i], xss[i]
|
||||||
|
return xss
|
||||||
|
|
||||||
|
def binary_search[T](xs: list[T], value: T) -> Optional[int]:
|
||||||
|
left = 0
|
||||||
|
right = len(xs) - 1
|
||||||
|
while left <= right:
|
||||||
|
middle = (left + right) // 2
|
||||||
|
if xs[middle] < value:
|
||||||
|
left = middle + 1
|
||||||
|
elif xs[middle] > value:
|
||||||
|
right = middle - 1
|
||||||
|
else:
|
||||||
|
return middle
|
||||||
|
return None
|
9
loops/sort/sort.py
Normal file
9
loops/sort/sort.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from typing import Iterator, Optional
|
||||||
|
|
||||||
|
|
||||||
|
def selection_sort[T](xs: Iterator[T]) -> Iterator[T]:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def binary_search[T](xs: list[T], value: T) -> Optional[int]:
|
||||||
|
return None
|
22
loops/sort/test_sort.py
Normal file
22
loops/sort/test_sort.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
from random import randint
|
||||||
|
from typing import Iterator
|
||||||
|
from sort import selection_sort, binary_search
|
||||||
|
|
||||||
|
def get_random_collection(min: int, max: int, size: int) -> Iterator[int]:
|
||||||
|
return [randint(min, max) for _ in range(size)]
|
||||||
|
|
||||||
|
def test_selection_sort():
|
||||||
|
xs = [5, 4, 3, 2, 1, 0]
|
||||||
|
assert list(selection_sort(xs)) == sorted(xs)
|
||||||
|
assert xs == [5, 4, 3, 2, 1, 0], "list was modified in `selection_sort` return a copy instead"
|
||||||
|
xs = get_random_collection(0, 100, 100)
|
||||||
|
print(xs)
|
||||||
|
assert list(selection_sort(xs)) == sorted(xs)
|
||||||
|
|
||||||
|
def test_binary_search():
|
||||||
|
xs = sorted(set(get_random_collection(0, 10000, 100)))
|
||||||
|
for i, e in enumerate(xs):
|
||||||
|
assert binary_search(xs, e) == i
|
||||||
|
assert binary_search([], 1) == None
|
||||||
|
assert binary_search([2], 1) == None
|
||||||
|
assert binary_search([2, 3], 1) == None
|
4
strings/string_manipulation/README.md
Normal file
4
strings/string_manipulation/README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Mit Zeichenketten arbeiten und manipulieren
|
||||||
|
|
||||||
|
Diese Teilaufgaben sind teilweise sehr einfach zu implementieren und sollen veranschaulichen was man alles mit Strings machen kann. Hierbei könnt ihr euch es natürlich einfach machen und die Buildins von `str` verwenden oder die Funktionen komplett selber implementieren.
|
||||||
|
|
93
strings/string_manipulation/solution/strings.py
Normal file
93
strings/string_manipulation/solution/strings.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
from dataclasses import dataclass, InitVar
|
||||||
|
from typing import Iterator
|
||||||
|
|
||||||
|
type Str = 'String' | str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class String:
|
||||||
|
_s: InitVar[str]
|
||||||
|
|
||||||
|
def __post_init__(self, s: str) -> None:
|
||||||
|
self.__s = s
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.__s
|
||||||
|
|
||||||
|
def __add__(self, other: Str) -> 'String':
|
||||||
|
return String(self.__s + str(other))
|
||||||
|
|
||||||
|
def __iadd__(self, other: Str) -> 'String':
|
||||||
|
return self + other
|
||||||
|
|
||||||
|
def __len__(self) -> int:
|
||||||
|
return len(self.__s)
|
||||||
|
|
||||||
|
def __eq__(self, other: Str) -> bool:
|
||||||
|
return str(self) == str(other)
|
||||||
|
|
||||||
|
def concat(self, other: Str) -> None:
|
||||||
|
self + other
|
||||||
|
|
||||||
|
def contains(self, other: Str) -> bool:
|
||||||
|
s = str(other)
|
||||||
|
for c in str(self):
|
||||||
|
if len(s) <= 0:
|
||||||
|
break
|
||||||
|
elif c == s[0]:
|
||||||
|
s: str = s[1:]
|
||||||
|
else:
|
||||||
|
s = str(other)
|
||||||
|
return len(s) == 0
|
||||||
|
|
||||||
|
def concat(self, other: Str) -> None:
|
||||||
|
self.__s += str(other)
|
||||||
|
|
||||||
|
def substring(self, start: int, end: int) -> 'String':
|
||||||
|
substr: str = ""
|
||||||
|
for i, c in enumerate(self.__s):
|
||||||
|
if i >= start and i <= end:
|
||||||
|
substr += c
|
||||||
|
return substr
|
||||||
|
|
||||||
|
def strip(self, chars: Str = ' ' + '\n' + '\t' + '\r') -> None:
|
||||||
|
i = 0
|
||||||
|
while i < len(self) and self.__s[i] in chars:
|
||||||
|
i += 1
|
||||||
|
j: int = len(self) - 1
|
||||||
|
while i <= j and self.__s[j] in chars:
|
||||||
|
j -= 1
|
||||||
|
self.__s: str = str(self)[i:j + 1]
|
||||||
|
|
||||||
|
def replace(self, old: Str, new: Str, count = -1) -> None:
|
||||||
|
o = str(old)
|
||||||
|
n = str(new)
|
||||||
|
j = 0
|
||||||
|
while count > 0 or (count < 0 and j < len(self)):
|
||||||
|
i: int = j
|
||||||
|
while len(o) > 0 and j < len(self):
|
||||||
|
if o[0] == self.__s[j]:
|
||||||
|
o: str = o[1:]
|
||||||
|
j += 1
|
||||||
|
else:
|
||||||
|
j += 1
|
||||||
|
break
|
||||||
|
if len(o) <= 0:
|
||||||
|
self.__s = self.__s[:i] + n + self.__s[j:]
|
||||||
|
j += len(new) - len(old)
|
||||||
|
count -= 1
|
||||||
|
o = str(old)
|
||||||
|
|
||||||
|
def add_prefix(self, prefix: Str) -> None:
|
||||||
|
self.__s = str(prefix) + self.__s
|
||||||
|
|
||||||
|
def add_suffix(self, suffix: Str) -> None:
|
||||||
|
self.__s += str(suffix)
|
||||||
|
|
||||||
|
def join[T](self, xs: Iterator[T]) -> 'String':
|
||||||
|
output = String("")
|
||||||
|
length: int = len(xs)
|
||||||
|
for i, e in enumerate(xs):
|
||||||
|
output += str(e)
|
||||||
|
if i < length - 1:
|
||||||
|
output += self
|
||||||
|
return output
|
9
strings/string_manipulation/strings.py
Normal file
9
strings/string_manipulation/strings.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
# kleine Hilfestellung mit `Str` kann man sowohl `str` als auch `String` meinen
|
||||||
|
type Str = 'String' | str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class String:
|
||||||
|
# Implement!
|
||||||
|
pass
|
49
strings/string_manipulation/test_strings.py
Normal file
49
strings/string_manipulation/test_strings.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
from strings import String
|
||||||
|
|
||||||
|
def test_eq_for_str():
|
||||||
|
test_str = String("this is a test string!")
|
||||||
|
assert test_str == "this is a test string!", "__eq__ wasn't implemented correctly for `String` and `str`"
|
||||||
|
|
||||||
|
def test_strings_contains():
|
||||||
|
test_str = String("this is a test")
|
||||||
|
assert test_str.contains("this")
|
||||||
|
assert not test_str.contains("release")
|
||||||
|
|
||||||
|
def test_strings_concat():
|
||||||
|
test_str = String("")
|
||||||
|
test_str += "test succesful!"
|
||||||
|
assert test_str == "test succesful!"
|
||||||
|
test_str.concat(" Or is it?")
|
||||||
|
assert test_str == "test succesful! Or is it?"
|
||||||
|
|
||||||
|
def test_strings_strip():
|
||||||
|
test_str = String(" halo? \n")
|
||||||
|
test_str.strip()
|
||||||
|
assert test_str == "halo?"
|
||||||
|
test_str = String(" \n ")
|
||||||
|
test_str.strip()
|
||||||
|
assert test_str == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_strings_replace():
|
||||||
|
test_str = String("har har har, try replacing thhis")
|
||||||
|
test_str.replace('har ', 'ha')
|
||||||
|
assert test_str == "hahahar, try replacing thhis"
|
||||||
|
test_str.replace('r', '', 1)
|
||||||
|
assert test_str == "hahaha, try replacing thhis"
|
||||||
|
test_str.replace('hh', 'h')
|
||||||
|
assert test_str == "hahaha, try replacing this"
|
||||||
|
test_str.replace('try replacing this', "replaced")
|
||||||
|
assert test_str == "hahaha, replaced"
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_pre_suf():
|
||||||
|
test_str = String(" ")
|
||||||
|
test_str.add_suffix("suff")
|
||||||
|
assert test_str == " suff"
|
||||||
|
test_str.add_prefix("pref")
|
||||||
|
assert test_str == "pref suff"
|
||||||
|
|
||||||
|
def test_join():
|
||||||
|
assert String(", ").join([1, 2, 3, 4]) == "1, 2, 3, 4"
|
||||||
|
assert String(", ").join([]) == ""
|
Reference in New Issue
Block a user