Compare commits

..

34 Commits

Author SHA1 Message Date
060362ec09 feat: json exercise 2026-03-19 13:28:20 +01:00
e28a2bdc67 feat: pathlib exercise 2026-03-19 11:58:22 +01:00
a455b46b72 refractor: added comment and removed infinite loop guardrail 2026-03-17 18:07:52 +01:00
9ff7d9161e feat: kata snail now has function, which rearanges list based on kata rules. Pre test commit, may still be incorrect 2026-03-17 18:03:24 +01:00
11f8bf5394 feat: list created, where endresult will be saved 2026-03-16 18:19:01 +01:00
f722614590 feat: initial commit for kata 'Snail'. test: initial commit for kata 'Snail' 2026-03-16 18:09:21 +01:00
fdcde7a855 chore: Kata description for Snail added to README 2026-03-16 17:50:23 +01:00
e867f69ad9 build: changed name of test/codewars to test/test_codewars 2026-03-13 17:49:29 +01:00
87eea6433e Merge branch 'tutorial' 2026-03-13 17:44:57 +01:00
60cf2dd6c6 feat: module and import exercises 2026-03-13 17:44:37 +01:00
03427a784f Merge pull request 'task2' (#1) from task2 into main
Reviewed-on: #1

Nein, von der Struktur sieht das sehr schön aus. Du hast sogar tests (z.B. für piracy-OOP) eingefügt, das ist natürlich sehr vorbildlich. Weil Du dort den Order tests/codewars/test___ nennst, bin ich nicht ganz sicher, ob dieser in jedem falle automatisch als Testordner erkannt wird (wegen dem codewars). Wenn Du viele Tests in einem Order tests/ hast und alle Files mit test_ beginnen, kannst Du alle zusammen automatisch ausführen mit pytest in der Konsole (oder auch einzeln unter Angabe des exakten Files).
2026-03-13 10:24:15 +01:00
7d1e778902 Merge pull request 'task3' (#2) from task3 into main
Reviewed-on: #2

Wow, alle Beispiele gelöst, sehr schön. Wenn Du konkrete Feedbacks willst, müsstest Du diese einfach stellen.
Was mir gefällt ist die strukturierte Beschrifftung der commits (feat etc.) und dass Du alle Aufgaben modular commitest.
2026-03-13 10:11:17 +01:00
51964de52c feat: tutorial analysis for modules and imports 2026-03-12 12:30:45 +01:00
f3d6554b1b build: matplotlib and pandas added to requirements 2026-03-12 12:04:30 +01:00
ce9a4029b7 refractor: removed print statement, that was ment for development 2026-03-11 23:57:28 +01:00
9df3b783fb feat: kata finished. Now correctly finds next bigger number. test: added test cases 2026-03-11 23:41:59 +01:00
fbe9f4bf02 function will now swamp pivot with lowest number right of pivot 2026-03-11 22:22:40 +01:00
c16bdad9b9 feat: function now finds pivot of number. Returns -1 if there is no pivot 2026-03-11 22:02:34 +01:00
5797eb8ef9 test: added a large number test case for kata 'Next bigger number with the same digits' 2026-03-11 21:44:56 +01:00
01a6ff1ead feat: kata next biggest number. Works but struggles with big numbers. test: test cases for kata 'Next bigger number with the same digits' 2026-03-11 17:45:04 +01:00
bc00bcf5f3 chore: added context for kata 'Next bigger number with the same digits' 2026-03-11 17:19:06 +01:00
d010de0fe5 test: test cases for kata 'Who has the most money' 2026-03-10 16:38:11 +01:00
c00cbd030b feat: kata 'Who has the most money' compleated. 2026-03-10 16:36:56 +01:00
a681ae4f2b chore: README updated for kata 'Who has the most money' 2026-03-10 15:24:22 +01:00
90ba3e1e60 chore: README updated for kata 'Who has the most money' 2026-03-10 15:24:00 +01:00
e521f037a4 refractor: removed unnecessary comment 2026-03-09 21:20:36 +01:00
00a42ea0fd fix: fixed function page_item_count. from calculating: constant * muliplicator * 2. to: constant * multiplicator + constant. first calculation returned wrong amount of items to return 2026-03-09 21:19:09 +01:00
fa8b2b21f9 fix: forgot to return len() of list in function page_item_count. Insted list itself was returned 2026-03-09 20:20:52 +01:00
7e43f0d42d feat: function page_count and page_item_count finished 2026-03-09 20:14:59 +01:00
fbf13b3f3f feat: function item_count() finished, working on page_count() 2026-03-09 18:36:38 +01:00
17de0e0f92 test: added test cases for kata 'PaginationHelper' 2026-03-09 18:20:09 +01:00
27c5087006 chore: README updated for kata content 'PaginationHelper' 2026-03-09 18:03:58 +01:00
99e6d45790 Merge branch 'task2' of https://gitea.fhgr.ch/zimmersandro/ppe2 into task2 2026-03-06 18:36:52 +01:00
95d79c84a8 feat: added inheritace and comparisond methods 2026-03-06 16:38:28 +01:00
45 changed files with 769 additions and 15 deletions

View File

@ -17,7 +17,7 @@ Repository for CDS-2020 Programming and Promt Engineering II
# Codewars
|Title|Source (src/codewars/)|Test (test/codewars/)|URL|
|-|-|-|-|
|Find the force of gravity between two objects|kata_force_of_gravity.py|test_force_of_gravity.py|[5b609ebc8f47bd595e000627](https://www.codewars.com/kata/5b609ebc8f47bd595e000627/)|
|Find the force of gravity between two objects|kata_force_of_gravity.py|test_force_of_gravity.py|[5b609ebc8f47bd595e000627](https://www.codewars.com/kata/5b609ebc8f47bd595e000627)|
|The Lamp: Revisited|kata_the_lamp.py|test_the_lamp.py|[570e6e32de4dc8a8340016dd](https://www.codewars.com/kata/570e6e32de4dc8a8340016dd)|
|OOP: Object Oriented Piracy|kata_object_oriented_piracy.py|test_object_oriented_piracy.py|[54fe05c4762e2e3047000add](https://www.codewars.com/kata/54fe05c4762e2e3047000add)|
|Vigenère Cipher Helper|kata_vigenere_cipher_helper.py|test_vigenere_cipher_helper.py|[52d1bd3694d26f8d6e0000d3](https://www.codewars.com/kata/52d1bd3694d26f8d6e0000d3)|
@ -26,3 +26,7 @@ Repository for CDS-2020 Programming and Promt Engineering II
|Thinkful - Object Drills: Quarks|kata_thinkful_quarks.py|test_thinkful_quarks.py|[5882b052bdeafec15e0000e6](https://www.codewars.com/kata/5882b052bdeafec15e0000e6)|
|Thinkful - Object Drills: Vectors|kata_thinkful_vectors.py|test_thinkful_vectors.py|[587f1e1f39d444cee6000ad4](https://www.codewars.com/kata/587f1e1f39d444cee6000ad4)|
|Building blocks|kata_building_blocks.py|test_building_blocks.py|[55b75fcf67e558d3750000a3](https://www.codewars.com/kata/55b75fcf67e558d3750000a3)|
|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

@ -2,3 +2,5 @@ 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

View File

@ -0,0 +1,31 @@
def next_bigger(n):
# get number as digits in list
digits = [int(x) for x in list(str(n))]
# find index of pivot. return -1 if there is no pivot, meaning number is alreadig biggest
pivot = -1
for i in range(1, len(digits)):
if digits[-i] > digits[-i - 1]:
pivot = -i - 1
break
if pivot == -1:
return -1
# find the smallest digit to the right that is bigger than the pivot
right = digits[pivot + 1 :]
swap = right.index(min([x for x in right if x > digits[pivot]]))
# swap pivot with found digit
digits[pivot], digits[len(digits) - len(right) + swap] = (
right[swap],
digits[pivot],
)
# sort right side of new swapped pivot and replace it at the end
right = digits[pivot + 1 :]
right.sort()
digits[pivot + 1 :] = right
# return number
return int("".join([str(x) for x in digits]))

View File

@ -0,0 +1,46 @@
class PaginationHelper:
# The constructor takes in an array of items and an integer indicating
# how many items fit within a single page
def __init__(self, collection, items_per_page):
self.collection = collection
self.items_per_page = items_per_page
# returns the number of items within the entire collection
def item_count(self):
return len(self.collection)
# returns the number of pages
def page_count(self):
return int(len(self.collection) / self.items_per_page) + (
len(self.collection) % self.items_per_page > 0
)
# returns the number of items on the given page. page_index is zero based
# this method should return -1 for page_index values that are out of range
def page_item_count(self, page_index):
if page_index < 0 or self.page_count() - 1 < page_index:
return -1
if page_index == 0:
return len(self.collection[: self.items_per_page])
return len(
self.collection[
self.items_per_page * page_index : self.items_per_page * page_index
+ self.items_per_page
]
)
# determines what page an item at the given index is on. Zero based indexes.
# this method should return -1 for item_index values that are out of range
def page_index(self, item_index):
try:
self.collection[item_index]
if item_index < 0:
raise IndexError
except IndexError:
return -1
return item_index // self.items_per_page

View File

@ -0,0 +1,86 @@
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

@ -0,0 +1,15 @@
class Student:
def __init__(self, name, fives, tens, twenties):
self.name = name
self.fives = fives
self.tens = tens
self.twenties = twenties
def most_money(students):
student_names = [x.name for x in students]
student_money = [x.fives * 5 + x.tens * 10 + x.twenties * 20 for x in students]
if len(set(student_money)) == 1 and len(student_money) > 1:
return "all"
return max(list(zip(student_names, student_money)), key=lambda x: x[1])[0]

View File

@ -1,41 +1,88 @@
class Hund:
from abc import ABC, abstractmethod
class Hund(ABC):
anzahl_hunde = 0
def __init__(self, name: str, rasse: str, alter: int, gewicht: float):
def __init__(self, name: str, alter: int, gewicht: float, bellgeraeusch: str):
self.name = name
self.rasse = rasse
self.alter = alter
self.gewicht = gewicht
self.bellgeraeusch = bellgeraeusch
Hund.anzahl_hunde += 1
def __repr__(self):
return f"Hund(name={self.name!r}, rasse={self.rasse}, alter={self.alter}, gewicht={self.gewicht}"
def __repr__(self) -> str:
return f"Hund(name={self.name!r}, rasse={self.__class__.__name__}, alter={self.alter}, gewicht={self.gewicht}"
def __str__(self):
return f"{self.name} ist ein {self.alter}-jähriger {self.rasse}"
def __str__(self) -> str:
return f"{self.name} ist ein {self.alter}-jähriger {self.__class__.__name__}"
def bellen(self, n=1) -> int:
print(n * "Woof! ")
@abstractmethod
def bellen(self, n: int = 1) -> None:
print(" ".join([self.bellgeraeusch] * n))
def geburtstag(self):
def geburtstag(self) -> None:
self.alter += 1
print(
f"Alles Gute zum Geburtstag, {self.name}! Du bist jetzt {self.alter} Jahre alt."
)
def ist_welpe(self):
def ist_welpe(self) -> None:
if self.alter < 2:
print(f"{self.name} ist ein {self.alter}-jähriger Welpe")
else:
print(f"{self.name} ist ein {self.alter}-jähriger erwachsener Hund")
def __lt__(self, other): # less than: self < other
return self.alter < other.alter
hund1 = Hund(name="Bello", rasse="Pudel", alter=99, gewicht=357)
hund2 = Hund(name="Dewy", rasse="Labrador", alter=-6, gewicht=1)
def __le__(self, other): # less equal: self <= other
return self.alter <= other.alter
def __gt__(self, other): # greater than: self > other
return self.alter > other.alter
def __ge__(self, other): # greater equal: self >= other
return self.alter >= other.alter
def __eq__(self, other): # equal: self == other
return self.alter == other.alter
class Pudel(Hund):
def __init__(self, name, alter, gewicht):
super().__init__(name, alter, gewicht, "wau")
def bellen(self, n=1):
super().bellen(n)
class Labrador(Hund):
def __init__(self, name, alter, gewicht):
super().__init__(name, alter, gewicht, "wuff")
def bellen(self, n=1):
super().bellen(n)
class Bulldog(Hund):
def __init__(self, name, alter, gewicht):
super().__init__(name, alter, gewicht, "woff")
def bellen(self, n=1):
super().bellen(n)
hund1 = Labrador(name="Bello", alter=33, gewicht=27)
hund2 = Pudel(name="Dewy", alter=6, gewicht=1)
hund3 = Bulldog(name="Stone", alter=15, gewicht=1000)
print(repr(hund1))
print(hund2)
hund2.bellen(3)
hund1.bellen(2)
hund1.geburtstag()
hund2.ist_welpe()
hund1.ist_welpe()
hund3.bellen(4)
print(hund3 > hund2)

View File

@ -0,0 +1,6 @@
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

@ -0,0 +1,8 @@
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

@ -0,0 +1,11 @@
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

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

View File

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

View File

@ -0,0 +1,33 @@
# 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

@ -0,0 +1,14 @@
# 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

@ -0,0 +1,14 @@
# 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

@ -0,0 +1,59 @@
# 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

@ -0,0 +1,21 @@
# 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

@ -0,0 +1,30 @@
# 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

@ -0,0 +1,27 @@
# 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

@ -0,0 +1,51 @@
# 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

@ -0,0 +1,20 @@
# 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

@ -0,0 +1,19 @@
# 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

@ -0,0 +1,53 @@
# 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

@ -0,0 +1,16 @@
# ---------------------------------------------------------------
# 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

@ -0,0 +1,35 @@
# 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

@ -0,0 +1,28 @@
# 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

@ -0,0 +1,15 @@
from src.codewars.kata_next_bigger_number_same_digits import next_bigger
def test_next_bigger():
assert next_bigger(12) == 21
assert next_bigger(21) == -1
assert next_bigger(513) == 531
assert next_bigger(2017) == 2071
assert next_bigger(414) == 441
assert next_bigger(144) == 414
assert next_bigger(1234567890) == 1234567908
assert next_bigger(59884848459853) == 59884848483559
assert next_bigger(7600201336) == 7600201363
assert next_bigger(5113455566888) == 5113455568688
assert next_bigger(4769560370633) == 4769560373036

View File

@ -0,0 +1,27 @@
from src.codewars.kata_pagination_helper import PaginationHelper
def test_pagination():
collection = ["a", "b", "c", "d", "e", "f"]
helper = PaginationHelper(collection, 4)
assert helper.page_count() == 2
assert helper.item_count() == 6
assert helper.page_item_count(0) == 4
assert helper.page_item_count(1) == 2
assert helper.page_item_count(2) == -1
assert helper.page_index(5) == 1
assert helper.page_index(2) == 0
assert helper.page_index(20) == -1
assert helper.page_index(-10) == -1
empty = PaginationHelper([], 10)
assert empty.item_count() == 0
assert empty.page_count() == 0
assert empty.page_index(0) == -1
assert empty.page_index(1) == -1
assert empty.page_index(-1) == -1
assert empty.page_item_count(0) == -1
assert empty.page_item_count(1) == -1
assert empty.page_item_count(-1) == -1

View File

@ -0,0 +1,10 @@
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

@ -0,0 +1,15 @@
from src.codewars.kata_who_the_most_money import Student, most_money
def test_most_money():
phil = Student("Phil", 2, 2, 1)
cam = Student("Cameron", 2, 2, 0)
geoff = Student("Geoff", 0, 3, 0)
assert most_money([cam, geoff, phil]) == "Phil"
phil = Student("Phil", 2, 2, 2)
cam = Student("Cameron", 2, 2, 2)
geoff = Student("Geoff", 2, 2, 2)
assert most_money([cam, geoff, phil]) == "all"