Compare commits

..

No commits in common. "main" and "task3_completed" have entirely different histories.

45 changed files with 4 additions and 640 deletions

View File

@ -29,4 +29,3 @@ Repository for CDS-2020 Programming and Promt Engineering II
|PaginationHelper|kata_pagination_helper.py|test_pagination_helper.py|[515bb423de843ea99400000a](https://www.codewars.com/kata/515bb423de843ea99400000a)|
|Who has the most money?|kata_who_the_most_money.py|test_who_the_most_money.py|[528d36d7cc451cd7e4000339](https://www.codewars.com/kata/528d36d7cc451cd7e4000339)|
|Next bigger number with the same digits|kata_next_bigger_number_same_digits.py|test_next_bigger_number_same_digits.py|[55983863da40caa2c900004e](https://www.codewars.com/kata/55983863da40caa2c900004e)|
|Snail|kata_snail.py|test_snail.py|[521c2db8ddc89b9b7a0000c1](https://www.codewars.com/kata/521c2db8ddc89b9b7a0000c1)|

View File

@ -1,6 +1,4 @@
ruff == 0.15.1
black == 26.1.0
pytest == 9.0.2
pre-commit == 4.5.1
matplotlib == 3.10.8
pandas == 3.0.1
pre-commit == 4.5.1

View File

@ -1,24 +0,0 @@
class Block:
def __init__(self, dimensions: list):
self.width = dimensions[0]
self.length = dimensions[1]
self.height = dimensions[2]
def get_width(self):
return self.width
def get_length(self):
return self.length
def get_height(self):
return self.height
def get_volume(self):
return self.width * self.length * self.height
def get_surface_area(self):
return (
2 * self.length * self.height
+ 2 * self.width * self.height
+ 2 * self.width * self.length
)

View File

@ -29,3 +29,6 @@ def next_bigger(n):
# return number
return int("".join([str(x) for x in digits]))
print(next_bigger(5113455566888))

View File

@ -1,86 +0,0 @@
def snail(snail_map):
# first list in array is always first. So add it to new list snail and pop it from snail_map
snail = [x for x in snail_map[0]]
snail_map.pop(0)
# transpone list and append first list to snail. Then pop firt item of snail_map. Loop till snail_map is empty
while len(snail_map) > 0:
snail_map = [list(reversed(x)) for x in snail_map]
snail_map = [list(row) for row in zip(*snail_map)]
[snail.append(x) for x in snail_map[0]]
snail_map.pop(0)
return snail
array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
array = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
print(snail(array))
"""
Konzept:
Ziel: 1 2 3 6 9 8 7 4 5
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
6 9
5 8
4 7
1 2 3 6 9
5 8
4 7
8 7
5 4
1 2 3 6 9 8 7
5 4
4
5
1 2 3 6 9 8 7 4
5
1 2 3 6 9 8 7 4 5
Ziel: 1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
8 12 16
7 11 15
6 10 14
5 9 13
1 2 3 4 8 12 16
7 11 15
6 10 14
5 9 13
...
"""

View File

@ -1,8 +0,0 @@
class Quark(object):
def __init__(self, color, flavor):
self.color = color
self.flavor = flavor
self.baryon_number = 1 / 3
def interact(self, other) -> None:
self.color, other.color = other.color, self.color

View File

@ -1,7 +0,0 @@
class Vector(object):
def __init__(self, x: int, y: int):
self.x = x
self.y = y
def add(self, other):
return Vector(self.x + other.x, self.y + other.y)

View File

@ -1,6 +0,0 @@
from pathlib import Path
base_dir = Path("data")
file_path = base_dir / "raw" / "processed.json"
file_path.mkdir(parents=True, exist_ok=True)

View File

@ -1,8 +0,0 @@
from analysis.io import read_csv
from analysis.metrics import revenue
if __name__ == "__main__":
df = read_csv("analysis/csv/sales.csv")
print(df)
df = revenue(df)
print(df)

View File

@ -1,11 +0,0 @@
day,product,quantity,unit_price,region
Mon,Notebook,3,899.0,West
Mon,Mouse,12,25.0,West
Tue,Notebook,2,899.0,Ost
Tue,Keyboard,5,70.0,Ost
Wed,Monitor,4,220.0,West
Wed,Mouse,10,25.0,Nord
Thu,Keyboard,6,70.0,Sued
Thu,Monitor,3,220.0,Ost
Fri,Notebook,1,899.0,Nord
Fri,Mouse,15,25.0,Sued
1 day product quantity unit_price region
2 Mon Notebook 3 899.0 West
3 Mon Mouse 12 25.0 West
4 Tue Notebook 2 899.0 Ost
5 Tue Keyboard 5 70.0 Ost
6 Wed Monitor 4 220.0 West
7 Wed Mouse 10 25.0 Nord
8 Thu Keyboard 6 70.0 Sued
9 Thu Monitor 3 220.0 Ost
10 Fri Notebook 1 899.0 Nord
11 Fri Mouse 15 25.0 Sued

View File

@ -1,5 +0,0 @@
import pandas as pd
def read_csv(file: str) -> pd.DataFrame:
return pd.read_csv(file)

View File

@ -1,6 +0,0 @@
import pandas as pd
def revenue(df: pd.DataFrame) -> pd.DataFrame:
revenue = df["quantity"] * df["unit_price"]
return revenue.groupby("day").sum()

View File

@ -1,33 +0,0 @@
# Ziel dieses Skripts:
#
# 1. Das Produkt von 6 * 7 berechnen → Erwartet: 42.0
# 2. Die Kreisfläche für Radius 5 berechnen → Erwartet: ~78.54
# 3. Den genauen Wert von PI ausgeben → Erwartet: 3.141592653589793
#
# ----------------------------------------------------------------------
# AUFGABE: Das Skript liefert falsche Ergebnisse. Finde den Fehler und
# korrigiere die Import-Anweisungen ohne den restlichen Code
# zu verändern!
# ----------------------------------------------------------------------
# from src.mathematik import berechne, PI # (1) Import aus mathematik
# from src.geometrie import berechne, PI # (2) Import aus geometrie
import src.geometrie as geo
import src.mathematik as mathe
def main():
# --- Aufgabe 1: Produkt berechnen (nutzt mathematik.berechne) ---
produkt = mathe.berechne(6, 7) # Erwartet: 42.0 — bekommt aber einen Fehler!
print(f"6 × 7 = {produkt}")
# --- Aufgabe 2: Kreisfläche (nutzt geometrie.berechne) ---
flaeche = geo.berechne(5) # Erwartet: ~78.54
print(f"Kreisfläche (r=5): {flaeche:.4f}")
# --- Aufgabe 3: PI-Wert ---
print(f"PI = {mathe.PI}") # Erwartet: 3.141592653589793
if __name__ == "__main__":
main()

View File

@ -1,14 +0,0 @@
# geometrie.py
# Modul für geometrische Berechnungen (Kreisflächen, Umfang usw.)
PI = 3.14 # Vereinfachter Wert (nur 2 Nachkommastellen!)
def berechne(radius: float) -> float:
"""Berechnet die Fläche eines Kreises: A = PI * r²"""
return PI * radius**2
def umfang(radius: float) -> float:
"""Berechnet den Umfang eines Kreises: U = 2 * PI * r"""
return 2 * PI * radius

View File

@ -1,14 +0,0 @@
# mathematik.py
# Modul für allgemeine mathematische Berechnungen
PI = 3.141592653589793 # Hochpräziser Wert
def berechne(a: float, b: float) -> float:
"""Berechnet das Produkt zweier Zahlen."""
return a * b
def potenz(basis: float, exponent: int) -> float:
"""Berechnet basis hoch exponent."""
return basis**exponent

View File

@ -1,59 +0,0 @@
# Ziel dieses Skripts:
#
# Testergebnisse einer Klasse auswerten und formatiert ausgeben.
#
# Gegeben: Punkte von 5 Studierenden (von max. 100 Punkten)
# Erwartet:
# Mittelwert → 73.5 (kaufm. gerundet → 74 → "Gut")
# Max. Punkte → 100 (aus statistik.MAX_WERT)
#
# ----------------------------------------------------------------------
# AUFGABE: Das Skript gibt falsche Werte aus. Es gibt keine Fehlermeldung
# vom Interpreter. Finde heraus, warum die Ergebnisse falsch sind
# und korrigiere die Import-Anweisungen!
# ----------------------------------------------------------------------
from src.statistik import (
runde,
mittelwert,
bewerte,
MAX_WERT,
) # importiert: runde, mittelwert, bewerte, MAX_WERT, MIN_WERT
from src.formatierung import (
trennlinie,
) # importiert: runde, als_prozent, trennlinie, MAX_WERT, MIN_WERT
PUNKTE = [92, 85, 61, 48, 82]
def auswertung():
print(trennlinie("="))
print(" TESTERGEBNISSE")
print(trennlinie("="))
# --- Mittelwert berechnen und benoten ---
mw = mittelwert(PUNKTE)
mw_gerundet = runde(mw) # Soll kaufm. auf int runden → Erwartet: 74
note = bewerte(mw)
print(f" Mittelwert : {mw}")
print(f" Gerundet : {mw_gerundet} ← Erwartet: 74 (int)")
print(f" Durchschnittsnote: {note}")
print(trennlinie())
# --- Maximale Punktzahl aus dem Modul ---
print(f" Max. Punkte : {MAX_WERT} ← Erwartet: 100")
print(trennlinie())
# --- Einzelne Ergebnisse ---
print(" Einzelergebnisse:")
for p in PUNKTE:
print(f" {p:>3} Punkte → {bewerte(p)}")
print(trennlinie("="))
if __name__ == "__main__":
auswertung()

View File

@ -1,21 +0,0 @@
# formatierung.py
# Modul für Ausgabe-Formatierung und Darstellung
MAX_WERT = 255 # Maximaler RGB-Farbwert (0255)
MIN_WERT = 0 # Minimaler RGB-Farbwert
def runde(wert: float, stellen: int = 2) -> float:
"""Rundet auf 'stellen' Nachkommastellen (für Anzeige-Formatierung)."""
faktor = 10**stellen
return int(wert * faktor + 0.5) / faktor
def als_prozent(wert: float, gesamt: float) -> str:
"""Gibt einen Wert als formatierten Prozentstring zurück."""
return f"{runde(wert / gesamt * 100)} %"
def trennlinie(zeichen: str = "-", laenge: int = 40) -> str:
"""Erzeugt eine Trennlinie für die Konsolenausgabe."""
return zeichen * laenge

View File

@ -1,30 +0,0 @@
# statistik.py
# Modul für statistische Berechnungen
MAX_WERT = 100 # Maximale Punktzahl in einem Test (0100)
MIN_WERT = 0 # Minimale Punktzahl
def runde(wert: float) -> int:
"""Rundet kaufmännisch auf ganze Zahlen (für Testergebnisse)."""
return int(wert + 0.5)
def mittelwert(werte: list[float]) -> float:
"""Berechnet den arithmetischen Mittelwert einer Liste."""
return sum(werte) / len(werte)
def bewerte(punkte: float) -> str:
"""Gibt eine Note zurück basierend auf Punktzahl (0100)."""
p = runde(punkte)
if p >= 90:
return "Sehr gut"
elif p >= 75:
return "Gut"
elif p >= 60:
return "Befriedigend"
elif p >= 45:
return "Ausreichend"
else:
return "Ungenügend"

View File

@ -1,27 +0,0 @@
# random.py
#
# Dieses Modul wurde angelegt, um eigene Hilfsfunktionen für
# "Zufallsentscheidungen" in der Lotterie-Logik bereitzustellen.
#
# Es definiert einige der gleichen Funktionen wie das Standardmodul
# aber mit vereinfachter (fehlerhafter) Implementierung.
def randint(a: int, b: int) -> int:
"""Gibt eine 'zufällige' Ganzzahl zwischen a und b zurück."""
return a # ← gibt IMMER den kleinsten Wert zurück!
def shuffle(lst: list) -> None:
"""Mischt eine Liste in-place."""
pass # ← tut gar nichts!
def sample(population: list, k: int) -> list:
"""Gibt k zufällige Elemente aus population zurück."""
return list(population)[:k] # ← gibt IMMER die ersten k Elemente zurück!
def seed(a=None):
"""Setzt den Zufallsgenerator-Seed."""
pass # ← keine Wirkung

View File

@ -1,51 +0,0 @@
# Lotterie-Simulation: Zieht 6 aus 45 Zahlen, dazu eine Zusatzzahl.
#
# Wiederholt die Ziehung 5× und gibt die Ergebnisse aus.
# Anschließend wird die Gewinnerliste zufällig gemischt.
#
# Erwartetes Verhalten:
# • Jede Ziehung liefert 6 VERSCHIEDENE, ZUFÄLLIGE Zahlen aus 145
# • Wiederholte Aufrufe liefern UNTERSCHIEDLICHE Ergebnisse
# • Die Teilnehmerliste ist nach dem Mischen in ZUFÄLLIGER Reihenfolge
#
# ----------------------------------------------------------------------
# AUFGABE: Das Programm läuft ohne Fehlermeldung, aber die Ergebnisse
# sind offensichtlich nicht zufällig. Finde die Ursache und
# behebe den Fehler ohne ziehung.py oder statistik.py zu ändern!
#
# REMARK: Möglicherweise ist das Problem sogar abhängig von der verwendeten
# IDE... Lasst das main.py mal aus eurer IDE laufen sowie aus dem
# Terminal. Sind die Resultate gleich?
# ----------------------------------------------------------------------
from ziehung import ziehe_zahlen, ziehe_zusatzzahl
from statistik import simuliere_ziehungen, mische_teilnehmer
TEILNEHMER = ["Alice", "Bob", "Carol", "Dave", "Eve"]
def main():
print("=" * 45)
print(" LOTTO-SIMULATION (6 aus 45)")
print("=" * 45)
print("\n--- 5 unabhängige Ziehungen ---")
for i, ziehung in enumerate(simuliere_ziehungen(5), 1):
print(f" Ziehung {i}: {ziehung}")
print("\n--- Einzelziehung mit Zusatzzahl ---")
haupt = ziehe_zahlen()
zusatz = ziehe_zusatzzahl(haupt)
print(f" Hauptzahlen : {haupt}")
print(f" Zusatzzahl : {zusatz}")
print("\n--- Gewinnerliste (zufällig gemischt) ---")
gemischt = mische_teilnehmer(TEILNEHMER)
for rang, name in enumerate(gemischt, 1):
print(f" Rang {rang}: {name}")
print("=" * 45)
if __name__ == "__main__":
main()

View File

@ -1,20 +0,0 @@
# Wertet mehrere Lottoziehungen statistisch aus
import custom_random
from ziehung import ziehe_zahlen
def simuliere_ziehungen(anzahl: int = 10) -> list[list[int]]:
"""Führt 'anzahl' unabhängige Lottoziehungen durch."""
ergebnisse = []
for _ in range(anzahl):
zahlen = ziehe_zahlen()
ergebnisse.append(zahlen)
return ergebnisse
def mische_teilnehmer(teilnehmer: list[str]) -> list[str]:
"""Mischt die Teilnehmerliste zufällig (z. B. für Gewinner-Reihenfolge)."""
kopie = teilnehmer[:]
custom_random.shuffle(kopie)
return kopie

View File

@ -1,19 +0,0 @@
# lotterie/ziehung.py
# Modul für die eigentliche Lottoziehung
import custom_random
ZAHLEN_POOL = list(range(1, 46)) # Zahlen 145
def ziehe_zahlen(anzahl: int = 6) -> list[int]:
"""Zieht 'anzahl' verschiedene Lottozahlen aus dem Pool."""
gezogen = custom_random.sample(ZAHLEN_POOL, anzahl)
gezogen.sort()
return gezogen
def ziehe_zusatzzahl(ausgeschlossen: list[int]) -> int:
"""Zieht eine Zusatzzahl, die nicht in der Hauptziehung vorkommt."""
pool = [z for z in ZAHLEN_POOL if z not in ausgeschlossen]
return custom_random.randint(1, len(pool) - 1) # ← Index in pool, dann Lookup

View File

@ -1,53 +0,0 @@
# Schulverwaltungs-Simulation:
# • Drei Schüler werden angelegt (mit Noten in zwei Kursen)
# • Zwei Kurse werden erstellt, Schüler werden eingeschrieben
# • Notenspiegel je Schüler und Kursbericht je Kurs wird ausgegeben
#
# ----------------------------------------------------------------------
# AUFGABE: Das Programm lässt sich gar nicht erst starten es gibt
# sofort einen ImportError.
#
# 1. Lies die Fehlermeldung sorgfältig und zeichne den
# Importgraphen auf: Welches Modul importiert welches?
#
# 2. Versuche durch eine geeignete Gegenmassnahme den Fehler zu
# beheben.
# ----------------------------------------------------------------------
from src.kurs import Kurs
from src.schueler import Schueler
def main():
# --- Schüler anlegen ---
anna = Schueler("Anna Meier", {"Mathematik": 2.5, "Deutsch": 3.0})
ben = Schueler("Ben Keller", {"Mathematik": 5.0, "Deutsch": 2.0})
clara = Schueler("Clara Huber", {"Mathematik": 3.5, "Deutsch": 4.5})
# --- Kurse anlegen und Schüler einschreiben ---
mathe = Kurs("Mathematik")
deutsch = Kurs("Deutsch")
for s in [anna, ben, clara]:
mathe.einschreiben(s)
deutsch.einschreiben(s)
# --- Ausgabe Notenspiegel ---
print("=" * 45)
print(" NOTENSPIEGEL")
print("=" * 45)
for s in [anna, ben, clara]:
print(s.notenspiegel())
print()
# --- Ausgabe Kursberichte ---
print("=" * 45)
print(" KURSBERICHTE")
print("=" * 45)
print(mathe.kursbericht())
print(deutsch.kursbericht())
print("=" * 45)
if __name__ == "__main__":
main()

View File

@ -1,16 +0,0 @@
# ---------------------------------------------------------------
# Gemeinsam genutzte Hilfsfunktion wird auch in schueler.py
# über den Import von oben verwendet.
# ---------------------------------------------------------------
def ist_bestanden(note: float) -> bool:
"""Gibt True zurück, wenn die Note ≤ 4.0 (bestanden) ist."""
return note <= 4.0
def berechne_klassendurchschnitt(noten: list[float]) -> float:
"""Berechnet den Notendurchschnitt einer Gruppe."""
if not noten:
return 0.0
return round(sum(noten) / len(noten), 2)

View File

@ -1,35 +0,0 @@
# schulverwaltung/kurs.py
#
# Verwaltet Kurse und eingeschriebene Schüler.
# Benötigt die Schueler-Klasse aus schueler.py für die Einschreibung
# und Notenauswertung.
from notenrechner import ist_bestanden, berechne_klassendurchschnitt
from .schueler import Schueler
class Kurs:
def __init__(self, name: str):
self.name = name
self.schueler: list[Schueler] = []
def einschreiben(self, schueler: Schueler) -> None:
"""Schreibt einen Schüler in diesen Kurs ein."""
self.schueler.append(schueler)
def kursbericht(self) -> str:
"""Gibt eine Übersicht über alle Schüler und den Kursdurchschnitt aus."""
zeilen = [f"\n Kurs: {self.name} ({len(self.schueler)} Schüler)"]
noten_im_kurs = []
for s in self.schueler:
note = s.noten.get(self.name)
if note is not None:
status = "" if ist_bestanden(note) else ""
zeilen.append(f" {status} {s.name:<20} {note:.1f}")
noten_im_kurs.append(note)
if noten_im_kurs:
schnitt = berechne_klassendurchschnitt(noten_im_kurs)
zeilen.append(f" → Klassendurchschnitt: {schnitt:.2f}")
return "\n".join(zeilen)

View File

@ -1,28 +0,0 @@
# Verwaltet Schüler-Daten und prüft den Abschlussstatus.
# Benötigt ist_bestanden() aus kurs.py, um festzustellen ob
# ein Schüler alle Kurse bestanden hat.
from notenrechner import ist_bestanden
class Schueler:
def __init__(self, name: str, noten: dict[str, float]):
"""
name : Vollständiger Name des Schülers
noten : {Kursname: Note} z. B. {'Mathematik': 4.5, 'Deutsch': 3.0}
"""
self.name = name
self.noten = noten
def kann_abschliessen(self) -> bool:
"""Gibt True zurück, wenn alle Kursnoten bestanden sind (Note ≤ 4.0)."""
return all(ist_bestanden(note) for note in self.noten.values())
def notenspiegel(self) -> str:
"""Gibt eine formatierte Übersicht aller Noten zurück."""
zeilen = [f" Schüler: {self.name}"]
for kurs, note in self.noten.items():
status = "" if ist_bestanden(note) else ""
zeilen.append(f" {status} {kurs:<18} Note: {note:.1f}")
zeilen.append(f" → Abschluss möglich: {self.kann_abschliessen()}")
return "\n".join(zeilen)

View File

@ -1,17 +0,0 @@
from src.codewars.kata_building_blocks import Block
def test_block():
b1 = Block([2, 2, 2])
b2 = Block([41, 87, 67])
assert b1.get_width() == 2
assert b1.get_length() == 2
assert b1.get_height() == 2
assert b1.get_volume() == 8
assert b1.get_surface_area() == 24
assert b2.get_width() == 41
assert b2.get_length() == 87
assert b2.get_height() == 67
assert b2.get_volume() == 238989
assert b2.get_surface_area() == 24286

View File

@ -1,10 +0,0 @@
from src.codewars.kata_snail import snail
def test_snail():
array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
assert snail(array) == [1, 2, 3, 6, 9, 8, 7, 4, 5]
array = [[1, 2, 3], [8, 9, 4], [7, 6, 5]]
assert snail(array) == [1, 2, 3, 4, 5, 6, 7, 8, 9]

View File

@ -1,15 +0,0 @@
from src.codewars.kata_thinkful_quarks import Quark
def test_quark():
q1 = Quark("red", "up")
q2 = Quark("blue", "strange")
assert q1.color == "red"
assert q2.flavor == "strange"
assert q2.baryon_number == 1 / 3
q1.interact(q2)
assert q1.color == "blue"
assert q2.color == "red"

View File

@ -1,13 +0,0 @@
from src.codewars.kata_thinkful_vectors import Vector
def test_vector():
v1 = Vector(3, 4)
v2 = Vector(1, 2)
assert v1.x == 3
assert v2.y == 2
assert hasattr(v1, "add")
assert isinstance(v1.add(v2), Vector)
assert (v1.add(v2)).x == 4
assert (v1.add(v2)).y == 6