diff --git a/README.md b/README.md index 0152bed..47056a2 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,15 @@ 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|[URL](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)| +|Caesar Cipher Helper|kata_ceasar_cipher_helper.py|test_ceasar_cipher_helper.py|[526d42b6526963598d0004db](https://www.codewars.com/kata/526d42b6526963598d0004db)| +|Versions manager|kata_version_mamanger.py|test_version_manager.py|[5bc7bb444be9774f100000c3](https://www.codewars.com/kata/5bc7bb444be9774f100000c3)| +|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)| diff --git a/src/codewars/kata_building_blocks.py b/src/codewars/kata_building_blocks.py new file mode 100644 index 0000000..e69de29 diff --git a/src/codewars/kata_ceasar_cipher_helper.py b/src/codewars/kata_ceasar_cipher_helper.py new file mode 100644 index 0000000..f9d6643 --- /dev/null +++ b/src/codewars/kata_ceasar_cipher_helper.py @@ -0,0 +1,28 @@ +class CaesarCipher(object): + def __init__(self, shift): + self.shift = shift + self.alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + def encode(self, text): + idx_alph = [ + self.alphabet.index(x) if x in self.alphabet else x for x in text.upper() + ] + idx_shift = [ + (x + self.shift) % len(self.alphabet) if isinstance(x, (int)) else x + for x in idx_alph + ] + return "".join( + [self.alphabet[x] if isinstance(x, (int)) else x for x in idx_shift] + ) + + def decode(self, text): + idx_alph = [ + self.alphabet.index(x) if x in self.alphabet else x for x in text.upper() + ] + idx_shift = [ + (x - self.shift) % len(self.alphabet) if isinstance(x, (int)) else x + for x in idx_alph + ] + return "".join( + [self.alphabet[x] if isinstance(x, (int)) else x for x in idx_shift] + ) diff --git a/src/codewars/kata_next_bigger_number_same_digits.py b/src/codewars/kata_next_bigger_number_same_digits.py new file mode 100644 index 0000000..59469d3 --- /dev/null +++ b/src/codewars/kata_next_bigger_number_same_digits.py @@ -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])) diff --git a/src/codewars/kata_object_oriented_piracy.py b/src/codewars/kata_object_oriented_piracy.py new file mode 100644 index 0000000..4300254 --- /dev/null +++ b/src/codewars/kata_object_oriented_piracy.py @@ -0,0 +1,7 @@ +class Ship: + def __init__(self, draft, crew): + self.draft = draft + self.crew = crew + + def is_worth_it(self): + return self.draft - self.crew * 1.5 > 20 diff --git a/src/codewars/kata_pagination_helper.py b/src/codewars/kata_pagination_helper.py new file mode 100644 index 0000000..98eb598 --- /dev/null +++ b/src/codewars/kata_pagination_helper.py @@ -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 diff --git a/src/codewars/kata_the_lamp.py b/src/codewars/kata_the_lamp.py new file mode 100644 index 0000000..418a8f6 --- /dev/null +++ b/src/codewars/kata_the_lamp.py @@ -0,0 +1,13 @@ +class Lamp: + + def __init__(self, color: str): + self.color = color + self.on = False + + def toggle_switch(self): + self.on = not self.on + + def state(self): + if self.on: + return "The lamp is on." + return "The lamp is off." diff --git a/src/codewars/kata_thinkful_quarks.py b/src/codewars/kata_thinkful_quarks.py new file mode 100644 index 0000000..e69de29 diff --git a/src/codewars/kata_thinkful_vectors.py b/src/codewars/kata_thinkful_vectors.py new file mode 100644 index 0000000..e69de29 diff --git a/src/codewars/kata_version_mamanger.py b/src/codewars/kata_version_mamanger.py new file mode 100644 index 0000000..e32722e --- /dev/null +++ b/src/codewars/kata_version_mamanger.py @@ -0,0 +1,47 @@ +class VersionManager: + def __init__(self, version=None): + if not version: + version = "0.0.1" + + parts = version.split(".")[:3] + + if not all(p.isdecimal() for p in parts): + raise ValueError("Error occured while parsing version!") + + nums = [int(p) for p in parts] + + while len(nums) < 3: + nums.append(0) + + self.major_v, self.minor_v, self.patch_v = nums + self.history = [] + + def _save(self): + self.history.append((self.major_v, self.minor_v, self.patch_v)) + + def major(self): + self._save() + self.major_v += 1 + self.minor_v = 0 + self.patch_v = 0 + return self + + def minor(self): + self._save() + self.minor_v += 1 + self.patch_v = 0 + return self + + def patch(self): + self._save() + self.patch_v += 1 + return self + + def rollback(self): + if not self.history: + raise Exception("Cannot rollback!") + self.major_v, self.minor_v, self.patch_v = self.history.pop() + return self + + def release(self): + return f"{self.major_v}.{self.minor_v}.{self.patch_v}" diff --git a/src/codewars/kata_vigenere_cipher_helper.py b/src/codewars/kata_vigenere_cipher_helper.py new file mode 100644 index 0000000..3d53b5d --- /dev/null +++ b/src/codewars/kata_vigenere_cipher_helper.py @@ -0,0 +1,40 @@ +class VigenereCipher(object): + def __init__(self, key, alphabet): + self.key = key + self.alphabet = alphabet + + def encode(self, text): + encoded = [] + idx_key = 0 + + for char in text: + if char in self.alphabet: + text_pos = self.alphabet.index(char) + key_char = self.key[idx_key % len(self.key)] + key_pos = self.alphabet.index(key_char) + + pos = (text_pos + key_pos) % len(self.alphabet) + encoded.append(self.alphabet[pos]) + else: + encoded.append(char) + idx_key += 1 + + return "".join(encoded) + + def decode(self, text): + decoded = [] + idx_key = 0 + + for char in text: + if char in self.alphabet: + text_pos = self.alphabet.index(char) + key_char = self.key[idx_key % len(self.key)] + key_pos = self.alphabet.index(key_char) + + pos = (text_pos - key_pos) % len(self.alphabet) + decoded.append(self.alphabet[pos]) + else: + decoded.append(char) + idx_key += 1 + + return "".join(decoded) diff --git a/src/codewars/kata_who_the_most_money.py b/src/codewars/kata_who_the_most_money.py new file mode 100644 index 0000000..a521421 --- /dev/null +++ b/src/codewars/kata_who_the_most_money.py @@ -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] diff --git a/src/tutorial/class/animal.py b/src/tutorial/class/animal.py new file mode 100644 index 0000000..77a7406 --- /dev/null +++ b/src/tutorial/class/animal.py @@ -0,0 +1,32 @@ +from abc import ABC, abstractmethod + + +class Animal(ABC): + @abstractmethod + def speak(slef) -> str: + return "..." + + def chorus(self, n: int) -> str: + # Wiederhole den Laut n-mal als eine Zeile" + if n <= 0: + raise ValueError("n muss positiv sein") + return " ".join(self.speak() for _ in range(n)) + + +class Dog(Animal): + def speak(self) -> str: + return "wuff" + + +class Cat(Animal): + def speak(self) -> str: + return "miau" + + +class Cow(Animal): + def speak(self) -> str: + return "muh" + + +cow = Cow() +print(cow.chorus(3)) diff --git a/src/tutorial/class/hund.py b/src/tutorial/class/hund.py index 129deb9..d47423f 100644 --- a/src/tutorial/class/hund.py +++ b/src/tutorial/class/hund.py @@ -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) diff --git a/src/tutorial/class/mro_tutorial.py b/src/tutorial/class/mro_tutorial.py new file mode 100644 index 0000000..715035d --- /dev/null +++ b/src/tutorial/class/mro_tutorial.py @@ -0,0 +1,17 @@ +class A: + pass + + +class B(A): + pass + + +class C(A): + pass + + +class D(B, C): + pass + + +print(D.mro()) diff --git a/src/tutorial/class/robot.py b/src/tutorial/class/robot.py new file mode 100644 index 0000000..a4ab031 --- /dev/null +++ b/src/tutorial/class/robot.py @@ -0,0 +1,21 @@ +class Dog: + def speak(self) -> str: + return "wuff" + + +class Cat: + def speak(self) -> str: + return "miau" + + +class Robot: + def speak(self) -> str: + return "bip bup" + + +def chorus(animals) -> list: + for a in animals: + print(a.speak()) + + +chorus([Dog(), Cat(), Robot()]) diff --git a/src/tutorial/class/storage.py b/src/tutorial/class/storage.py new file mode 100644 index 0000000..a6859db --- /dev/null +++ b/src/tutorial/class/storage.py @@ -0,0 +1,27 @@ +from abc import ABC, abstractmethod + + +class Storage(ABC): + @abstractmethod + def save(self, key: str, value: str) -> None: + pass + + @abstractmethod + def load(self, key: str) -> str: + pass + + +class MemoryStorage(Storage): + def __init__(self) -> None: + self.storage = {} + + def save(self, key: str, value: str) -> None: + self.storage[key] = value + + def load(self, key): + return self.storage[key] + + +s = MemoryStorage() +s.save("randomkey", "My Value") +print(s.load("randomkey")) diff --git a/tests/codewars/test_building_blocks.py b/tests/codewars/test_building_blocks.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/codewars/test_ceasar_cipher_helper.py b/tests/codewars/test_ceasar_cipher_helper.py new file mode 100644 index 0000000..70efd3b --- /dev/null +++ b/tests/codewars/test_ceasar_cipher_helper.py @@ -0,0 +1,8 @@ +from src.codewars.kata_ceasar_cipher_helper import CaesarCipher + + +def test_cipher_helper(): + c = CaesarCipher(5) + + assert c.encode("Codewars") == "HTIJBFWX" + assert c.decode("HTIJBFWX") == "CODEWARS" diff --git a/tests/codewars/test_next_bigger_number_same_digits.py b/tests/codewars/test_next_bigger_number_same_digits.py new file mode 100644 index 0000000..a1793a5 --- /dev/null +++ b/tests/codewars/test_next_bigger_number_same_digits.py @@ -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 diff --git a/tests/codewars/test_object_oriented_piracy.py b/tests/codewars/test_object_oriented_piracy.py new file mode 100644 index 0000000..61f4872 --- /dev/null +++ b/tests/codewars/test_object_oriented_piracy.py @@ -0,0 +1,15 @@ +from src.codewars.kata_object_oriented_piracy import Ship + + +def test_piracy(): + empty_ship = Ship(0, 0) + assert not empty_ship.is_worth_it() + + boat = Ship(15, 20) + assert not boat.is_worth_it() + + worthy_ship = Ship(100, 20) + assert worthy_ship.is_worth_it() + + big_boat = Ship(35, 20) + assert not big_boat.is_worth_it() diff --git a/tests/codewars/test_pagination_helper.py b/tests/codewars/test_pagination_helper.py new file mode 100644 index 0000000..12f3185 --- /dev/null +++ b/tests/codewars/test_pagination_helper.py @@ -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 diff --git a/tests/codewars/test_the_lamp.py b/tests/codewars/test_the_lamp.py new file mode 100644 index 0000000..811cec0 --- /dev/null +++ b/tests/codewars/test_the_lamp.py @@ -0,0 +1,13 @@ +from src.codewars.kata_the_lamp import Lamp + + +def test_lamp(): + my_lamp = Lamp("Blue") + + assert my_lamp.color == "Blue" + assert not my_lamp.on + assert my_lamp.state() == "The lamp is off." + my_lamp.toggle_switch() + assert my_lamp.state() == "The lamp is on." + my_lamp.toggle_switch() + assert my_lamp.state() == "The lamp is off." diff --git a/tests/codewars/test_thinkful_quarks.py b/tests/codewars/test_thinkful_quarks.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/codewars/test_thinkful_vectors.py b/tests/codewars/test_thinkful_vectors.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/codewars/test_version_manager.py b/tests/codewars/test_version_manager.py new file mode 100644 index 0000000..fb9c76b --- /dev/null +++ b/tests/codewars/test_version_manager.py @@ -0,0 +1,7 @@ +from src.codewars.kata_version_mamanger import VersionManager + + +def test_lamp(): + v = VersionManager("1.1.1") + + assert v.release() == "1.1.1" diff --git a/tests/codewars/test_vigenere_cipher_helper.py b/tests/codewars/test_vigenere_cipher_helper.py new file mode 100644 index 0000000..a851339 --- /dev/null +++ b/tests/codewars/test_vigenere_cipher_helper.py @@ -0,0 +1,16 @@ +from src.codewars.kata_vigenere_cipher_helper import VigenereCipher + + +def test_cipher_helper(): + abc = "abcdefghijklmnopqrstuvwxyz" + key = "password" + c = VigenereCipher(key, abc) + + assert c.encode("codewars") == "rovwsoiv" + assert c.decode("rovwsoiv") == "codewars" + + assert c.encode("waffles") == "laxxhsj" + assert c.decode("laxxhsj") == "waffles" + + assert c.encode("CODEWARS") == "CODEWARS" + assert c.decode("CODEWARS") == "CODEWARS" diff --git a/tests/codewars/test_who_the_most_money.py b/tests/codewars/test_who_the_most_money.py new file mode 100644 index 0000000..f7aeeff --- /dev/null +++ b/tests/codewars/test_who_the_most_money.py @@ -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"