From dd58585190bf11f2e6497e5b9762cf05cf52d479 Mon Sep 17 00:00:00 2001 From: hakanyorukk Date: Sun, 23 Aug 2026 23:14:51 +0300 Subject: [PATCH 1/3] add oop --- dsa/d1/exercise_1.py | 17 +++-- dsa/d1/exercise_2.py | 21 ++++++ dsa/d1/exercise_3.py | 20 ++++++ dsa/d2/exercise_1.py | 11 +-- dsa/d2/exercise_2.py | 22 ++++++ dsa/d2/exercise_3.py | 22 ++++++ dsa/d3/exercise_1.py | 2 +- dsa/d3/exercise_2.py | 25 +++++++ dsa/d4/exercise_3.py | 26 +++++++ dsa/d4/exercise_4.py | 26 +++++++ dsa/d5/exercise_2.py | 18 +++++ dsa/d5/exercise_3.py | 16 +++++ exercise/dunder_methods/Employee.py | 9 +++ hashing/task4/exercise_6.py | 18 +++++ hashing/task5/exercise_5.py | 18 +++++ kadanes_algorithm/task1/exercise_4.py | 26 +++++++ oop/exercise_1/Package.py | 37 ++++++++++ oop/exercise_1/PackageRegistry.py | 36 ++++++++++ oop/exercise_1/main.py | 52 ++++++++++++++ oop/exercise_1/task.txt | 62 ++++++++++++++++ oop/exercise_2/Alert.py | 72 +++++++++++++++++++ oop/exercise_2/AlertLog.py | 49 +++++++++++++ oop/exercise_2/main.py | 40 +++++++++++ searching_sorting/binary_search/exercise_5.py | 22 ++++++ searching_sorting/bubble_sort/exercise_4.py | 4 +- searching_sorting/bubble_sort/exercise_5.py | 17 +++++ searching_sorting/builtin_search/Employee.py | 8 ++- .../builtin_search/exercise_1.py | 42 ++++++++--- sliding_window/task1/exercise_5.py | 22 ++++++ sliding_window/task2/exercise_4.py | 23 ++++++ sliding_window/task3/exercise_4.py | 25 +++++++ sliding_window/task3/exercise_5.py | 25 +++++++ sliding_window/task3/exercise_6.py | 24 +++++++ stack_queue/task1/exercise_3.py | 20 ++++++ 34 files changed, 849 insertions(+), 28 deletions(-) create mode 100644 dsa/d1/exercise_2.py create mode 100644 dsa/d1/exercise_3.py create mode 100644 dsa/d2/exercise_2.py create mode 100644 dsa/d2/exercise_3.py create mode 100644 dsa/d3/exercise_2.py create mode 100644 dsa/d4/exercise_3.py create mode 100644 dsa/d4/exercise_4.py create mode 100644 dsa/d5/exercise_2.py create mode 100644 dsa/d5/exercise_3.py create mode 100644 hashing/task4/exercise_6.py create mode 100644 hashing/task5/exercise_5.py create mode 100644 kadanes_algorithm/task1/exercise_4.py create mode 100644 oop/exercise_1/Package.py create mode 100644 oop/exercise_1/PackageRegistry.py create mode 100644 oop/exercise_1/main.py create mode 100644 oop/exercise_1/task.txt create mode 100644 oop/exercise_2/Alert.py create mode 100644 oop/exercise_2/AlertLog.py create mode 100644 oop/exercise_2/main.py create mode 100644 searching_sorting/binary_search/exercise_5.py create mode 100644 searching_sorting/bubble_sort/exercise_5.py create mode 100644 sliding_window/task1/exercise_5.py create mode 100644 sliding_window/task2/exercise_4.py create mode 100644 sliding_window/task3/exercise_4.py create mode 100644 sliding_window/task3/exercise_5.py create mode 100644 sliding_window/task3/exercise_6.py create mode 100644 stack_queue/task1/exercise_3.py diff --git a/dsa/d1/exercise_1.py b/dsa/d1/exercise_1.py index 728f737..aae8f7f 100644 --- a/dsa/d1/exercise_1.py +++ b/dsa/d1/exercise_1.py @@ -5,17 +5,16 @@ def main(): print(two_sum(nums, target)) def two_sum(nums, target): - map = {} + seen = set() #num, index - pairs=[] - for i in range(len(nums)): - required_num = target - nums[i] - if required_num in map: - pairs.append((nums[i], required_num)) - #pairs[nums[i]] = required_num + pairs=set() + for num in nums: + required_num = target - num + if required_num in seen: + pairs.add((min(num, required_num), max(num, required_num))) - map[nums[i]] = i - return sorted(pairs, key=lambda v: v[0]) + seen.add(num) + return sorted(pairs) if __name__ == "__main__": main() \ No newline at end of file diff --git a/dsa/d1/exercise_2.py b/dsa/d1/exercise_2.py new file mode 100644 index 0000000..5a8f5aa --- /dev/null +++ b/dsa/d1/exercise_2.py @@ -0,0 +1,21 @@ +def main(): + nums = [2, 7, 11, 15, 3, 4, 8, 1] + target = 11 + + print(two_sum(nums, target)) + +def two_sum(nums, target): + seen = set() + pairs = set() + for num in nums: + required_num = target - num + if required_num in seen: + if required_num > num: + pairs.add((num, required_num)) + else: + pairs.add((required_num, num)) + seen.add(num) + return sorted(pairs) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/dsa/d1/exercise_3.py b/dsa/d1/exercise_3.py new file mode 100644 index 0000000..0c063ea --- /dev/null +++ b/dsa/d1/exercise_3.py @@ -0,0 +1,20 @@ +def main(): + nums = [2, 7, 11, 15, 3, 4, 8, 1] + target = 11 + + print(two_sum(nums, target)) + +def two_sum(nums, target): + seen = set() + pairs=set() + for num in nums: + required_num = target - num + if required_num in seen: + if required_num > num: + pairs.add((num, required_num)) + else: + pairs.add((required_num, num)) + seen.add(num) + return sorted(pairs) +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/dsa/d2/exercise_1.py b/dsa/d2/exercise_1.py index 1329ef7..ea75570 100644 --- a/dsa/d2/exercise_1.py +++ b/dsa/d2/exercise_1.py @@ -1,5 +1,5 @@ def main(): - # s = "abcabcbb" # → "abc" + #s = "abcabcbb" # → "abc" # # s = "pwwkew" # → "wke" # # s = "" # → "" # print(longest_substring(s)) @@ -8,16 +8,19 @@ def main(): print(longest_substring(s)) def longest_substring(s): - maxLength = 0 + max_length = 0 seen = set() left = 0 + best_start = 0 for right in range(len(s)): while s[right] in seen: seen.remove(s[left]) left+=1 seen.add(s[right]) - maxLength = max(maxLength,right - left +1) - return s[left:right+1] + if right - left + 1 > max_length: + max_length = right-left+1 + best_start = left + return s[best_start:best_start+max_length] if __name__ == "__main__": main() \ No newline at end of file diff --git a/dsa/d2/exercise_2.py b/dsa/d2/exercise_2.py new file mode 100644 index 0000000..4ce98dd --- /dev/null +++ b/dsa/d2/exercise_2.py @@ -0,0 +1,22 @@ +def main(): + s = "abcabcbb" + print(longest_substring(s)) + +def longest_substring(s): + seen = set() + max_length = 0 + left = 0 + best_start = 0 + + for right in range(len(s)): + while s[right] in seen: + seen.remove(s[left]) + left+=1 + seen.add(s[right]) + if right - left + 1 > max_length: + max_length = right - left + 1 + best_start = left + return s[best_start:best_start+max_length] + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/dsa/d2/exercise_3.py b/dsa/d2/exercise_3.py new file mode 100644 index 0000000..eecea7a --- /dev/null +++ b/dsa/d2/exercise_3.py @@ -0,0 +1,22 @@ +def main(): + s = "xyzxy" + print(longest_substring(s)) + +def longest_substring(s): + + left = 0 + seen = set() + max_length =0 + best_start = 0 + for right in range(len(s)): + while s[right] in seen: + seen.remove(s[left]) + left+=1 + + if max_length < right - left + 1: + max_length = right - left + 1 + best_start = left + seen.add(s[right]) + return s[best_start:best_start+max_length] +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/dsa/d3/exercise_1.py b/dsa/d3/exercise_1.py index fbeb149..ca57145 100644 --- a/dsa/d3/exercise_1.py +++ b/dsa/d3/exercise_1.py @@ -5,7 +5,7 @@ def main(): def palindrome(s): clean_s = "" for i in range(len(s)): - if s[i].isalpha(): + if s[i].isalpha() or s[i].isdigit(): clean_s += s[i].lower() print(clean_s) diff --git a/dsa/d3/exercise_2.py b/dsa/d3/exercise_2.py new file mode 100644 index 0000000..d730749 --- /dev/null +++ b/dsa/d3/exercise_2.py @@ -0,0 +1,25 @@ +def main(): + s = "race a car" + print(palindrome(s)) + +def palindrome(string): + #clean_s = "" + clean_list = [] + for i in string: + if i.isalpha() or i.isdigit(): + #clean_s += i.lower() + clean_list.append(i) + clean_string = "".join(clean_list) + left = 0 + right = len(clean_string)-1 + print(clean_string) + while left < right: + + if clean_string[left] != clean_string[right]: + return False + left+=1 + right-=1 + return True + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/dsa/d4/exercise_3.py b/dsa/d4/exercise_3.py new file mode 100644 index 0000000..c1b5284 --- /dev/null +++ b/dsa/d4/exercise_3.py @@ -0,0 +1,26 @@ +def main(): + nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4] # → [4, -1, 2, 1] + print(kadane_algorithm(nums)) + +def kadane_algorithm(nums): + current_sum = nums[0] + max_sum = nums[0] + temp_start = 0 + best_start = 0 + best_end = 0 + for i in range(1, len(nums)): + if current_sum + nums[i] > nums[i]: + current_sum = current_sum + nums[i] + else: + current_sum = nums[i] + temp_start = i + if current_sum > max_sum: + max_sum = current_sum + best_start = temp_start + best_end = i + return nums[best_start:best_end+1] + + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/dsa/d4/exercise_4.py b/dsa/d4/exercise_4.py new file mode 100644 index 0000000..04211e2 --- /dev/null +++ b/dsa/d4/exercise_4.py @@ -0,0 +1,26 @@ +def main(): + nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4] # → [4, -1, 2, 1] + print(kadane_algorithm(nums)) + +def kadane_algorithm(nums): + current_sum = nums[0] + max_sum = nums[0] + temp_start = 0 + best_start = 0 + best_end =0 + for i in range(1, len(nums)): + if current_sum +nums[i] > nums[i]: + current_sum = current_sum + nums[i] + else: + current_sum = nums[i] + temp_start = i + if current_sum > max_sum: + max_sum = current_sum + best_start = temp_start + best_end = i + return nums[best_start:best_end + 1] + +if __name__ == "__main__": + main() + + diff --git a/dsa/d5/exercise_2.py b/dsa/d5/exercise_2.py new file mode 100644 index 0000000..e9fe744 --- /dev/null +++ b/dsa/d5/exercise_2.py @@ -0,0 +1,18 @@ +from collections import defaultdict + +def main(): + words = ["eat", "tea", "tan", "ate", "nat", "bat"] + print(algorithm(words)) + +def algorithm(words): + word_list = defaultdict(list) + + for word in words: + key = "".join(sorted(word)) + + word_list[key].append(word) + + return dict(word_list) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/dsa/d5/exercise_3.py b/dsa/d5/exercise_3.py new file mode 100644 index 0000000..967f133 --- /dev/null +++ b/dsa/d5/exercise_3.py @@ -0,0 +1,16 @@ +from collections import defaultdict + +def main(): + words = ["eat", "tea", "tan", "ate", "nat", "bat"] + print(algorithm(words)) + +def algorithm(words): + anagram_words = defaultdict(list) + for word in words: + key = "".join(sorted(word)) + anagram_words[key].append(word) + + return dict(anagram_words) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/exercise/dunder_methods/Employee.py b/exercise/dunder_methods/Employee.py index 7da8dde..c234dce 100644 --- a/exercise/dunder_methods/Employee.py +++ b/exercise/dunder_methods/Employee.py @@ -12,6 +12,15 @@ def __init__(self,name): self.name = name Employee.count += 1 + def __eq__(self, other): + if isinstance(other, Employee): + if self.name == other.name: + return True + return False + + def __hash__(self): + return hash((self.name)) + @staticmethod def is_valid_name(name): return len(name) > 0 # doesn't need self or the class diff --git a/hashing/task4/exercise_6.py b/hashing/task4/exercise_6.py new file mode 100644 index 0000000..b3d242e --- /dev/null +++ b/hashing/task4/exercise_6.py @@ -0,0 +1,18 @@ +def main(): + + nums = [1, 2, 1] + k = 2 + print(is_contains_nearby_duplicate(nums, k)) + +def is_contains_nearby_duplicate(nums, k): + #hash_map -> value, index + hash_map = {} + + for i in range(0, len(nums)): + if nums[i] in hash_map and i - hash_map[nums[i]] == k: + return True + hash_map[nums[i]] = i + return False + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/hashing/task5/exercise_5.py b/hashing/task5/exercise_5.py new file mode 100644 index 0000000..d455a70 --- /dev/null +++ b/hashing/task5/exercise_5.py @@ -0,0 +1,18 @@ +def main(): + s = "rat" + t = "tar" + print(is_anagram(s,t)) + +def is_anagram(s,t): + hash_map = {} + for i in range(len(s)): + hash_map[s[i]] = hash_map.get(s[i],0)+1 + + for j in range(len(t)): + if t[j] not in hash_map or hash_map[t[j]] == 0: + return False + hash_map[t[j]] = hash_map.get(t[j],0)-1 + + return True +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/kadanes_algorithm/task1/exercise_4.py b/kadanes_algorithm/task1/exercise_4.py new file mode 100644 index 0000000..0d16b2d --- /dev/null +++ b/kadanes_algorithm/task1/exercise_4.py @@ -0,0 +1,26 @@ +def main(): + nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4] + print(f"Largest sum in the array -> {max_subarray_sum(nums)}") + +def max_subarray_sum(nums): + current_sum = nums[0] + max_sum = nums[0] + temp_start=0 + best_start=0 + best_end=0 + + for i in range(1, len(nums)): + if current_sum + nums[i] > nums[i]: + current_sum = current_sum + nums[i] + else: + current_sum = nums[i] + temp_start=i + + if current_sum > max_sum: + max_sum = current_sum + best_start = temp_start + best_end = i + #return nums[best_start:best_end+1] + return max_sum +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/oop/exercise_1/Package.py b/oop/exercise_1/Package.py new file mode 100644 index 0000000..419857b --- /dev/null +++ b/oop/exercise_1/Package.py @@ -0,0 +1,37 @@ +class Package: + + def __init__(self,name,version): + self.name = name + self.version = version + + @classmethod + def from_string(cls,text): + if not "==" in text: + raise ValueError("Doesn't contain ==") + try: + name,version = text.split("==") + except (ValueError, AttributeError): + raise ValueError("Invalid") + return cls(name, version) + + @property + def major(self): + nums = self.version.split(".") + return int(nums[0]) + + def __str__(self): + return f"{self.name}=={self.version}" + + def __repr__(self): + return f"Package('{self.name}', '{self.version}')" + + def __eq__(self, other): + if isinstance(other, Package): + if self.name == other.name and self.version == other.version: + return True + return False + + def __hash__(self): + return hash((self.name, self.version)) + + diff --git a/oop/exercise_1/PackageRegistry.py b/oop/exercise_1/PackageRegistry.py new file mode 100644 index 0000000..f40f1d2 --- /dev/null +++ b/oop/exercise_1/PackageRegistry.py @@ -0,0 +1,36 @@ +from collections import defaultdict + + +class PackageRegistry: + def __init__(self): + self.packages = [] + + def add(self, package): + if package not in self.packages: + self.packages.append(package) + + def __len__(self): + return int(len(self.packages)) + + def __contains__(self, package): + return package in self.packages + + def __iter__(self): + self.index=0 + return self + + def __next__(self): + if self.index>=len(self.packages): + raise StopIteration + package = self.packages[self.index] + self.index+=1 + return package + + def names(self): + return sorted({p.name for p in self.packages}) + + def versions_by_name(self): + versions = defaultdict(list) + for p in self.packages: + versions[p.name].append(p.version) + return {name: sorted(v) for name, v in versions.items()} \ No newline at end of file diff --git a/oop/exercise_1/main.py b/oop/exercise_1/main.py new file mode 100644 index 0000000..90fb661 --- /dev/null +++ b/oop/exercise_1/main.py @@ -0,0 +1,52 @@ + +from PackageRegistry import PackageRegistry +from Package import Package + +raw = [ + "requests==2.31.0", + "flask==3.0.0", + "requests==2.28.1", + "not-a-package", + "flask==3.0.0", + "django==4.2.7", + "requests==2.31.0", +] + +def main(): + # package_registry = PackageRegistry() + # for r in raw: + # try: + # package_registry.add(Package.from_string(r)) + # except ValueError as e: + # print(str(e)) + # print(package_registry.names()) + + p1 = Package.from_string("requests==2.31.0") + p2 = Package.from_string("requests==2.31.0") + p3 = Package.from_string("requests==2.28.1") + + print(p1 == p2) # True — same name and version + print(p1 == p3) # False — different version + print(p1 == "requests") # False — must NOT crash + print(hash(p1) == hash(p2)) # True — the contract + print(len({p1, p2, p3}) == 2) # True — set dedupes p1 and p2 + print(p1.major == 2) # True — an int, not "2" + print(str(p1) == "requests==2.31.0") + print(repr(p1) == "Package('requests', '2.31.0')") + print(repr([p1]) == "[Package('requests', '2.31.0')]") # containers use __repr__ + + r = PackageRegistry() + for line in raw: + try: + r.add(Package.from_string(line)) + except ValueError: + pass + + print(len(r) == 4) # 7 lines, 2 duplicates, 1 invalid + print(p1 in r) + print(r.names() == ["django", "flask", "requests"]) + print(r.versions_by_name()["requests"] == ["2.28.1", "2.31.0"]) + print([str(p) for p in r]) # the for loop must work + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/oop/exercise_1/task.txt b/oop/exercise_1/task.txt new file mode 100644 index 0000000..700b766 --- /dev/null +++ b/oop/exercise_1/task.txt @@ -0,0 +1,62 @@ +Part 1 — Package +A package has a name and a version string like "2.31.0". + +__init__(self, name, version) +from_string(cls, text) — a @classmethod that parses "requests==2.31.0" into a Package. Raise ValueError with a clear message if the text has no ==. +major — a @property returning the first number of the version as an int. "2.31.0" → 2. +__str__ → "requests==2.31.0" +__repr__ → "Package('requests', '2.31.0')" +__eq__ — two packages are equal when name and version both match. Must not crash when compared to a non-Package. +__hash__ — consistent with __eq__. +Part 2 — PackageRegistry +Holds packages and is iterable. + +__init__(self) — starts empty +add(self, package) — ignores duplicates (same name and version). This is where __eq__/__hash__ earn their keep. +__len__(self) — so len(registry) works +__contains__(self, package) — so package in registry works +__iter__ and __next__, written manually — no generators, no delegating to a list. This is the point of the exercise. +names(self) → a sorted list of unique package names (strings) +versions_by_name(self) → a dict of name → sorted list of version strings +Part 3 — main() +Parse this list, skipping bad lines, and print the results: + +raw = [ + "requests==2.31.0", + "flask==3.0.0", + "requests==2.28.1", + "not-a-package", + "flask==3.0.0", + "django==4.2.7", + "requests==2.31.0", +] + +Checks it must pass +Copy these into your file and run them. Every one must print True. + +p1 = Package.from_string("requests==2.31.0") +p2 = Package.from_string("requests==2.31.0") +p3 = Package.from_string("requests==2.28.1") + +print(p1 == p2) # True — same name and version +print(p1 == p3) # False — different version +print(p1 == "requests") # False — must NOT crash +print(hash(p1) == hash(p2)) # True — the contract +print(len({p1, p2, p3}) == 2) # True — set dedupes p1 and p2 +print(p1.major == 2) # True — an int, not "2" +print(str(p1) == "requests==2.31.0") +print(repr(p1) == "Package('requests', '2.31.0')") +print(repr([p1]) == "[Package('requests', '2.31.0')]") # containers use __repr__ + +r = PackageRegistry() +for line in raw: + try: + r.add(Package.from_string(line)) + except ValueError: + pass + +print(len(r) == 4) # 7 lines, 2 duplicates, 1 invalid +print(p1 in r) +print(r.names() == ["django", "flask", "requests"]) +print(r.versions_by_name()["requests"] == ["2.28.1", "2.31.0"]) +print([str(p) for p in r]) # the for loop must work \ No newline at end of file diff --git a/oop/exercise_2/Alert.py b/oop/exercise_2/Alert.py new file mode 100644 index 0000000..a38df4b --- /dev/null +++ b/oop/exercise_2/Alert.py @@ -0,0 +1,72 @@ +from abc import ABC, abstractmethod + + +class Alert(ABC): + def __init__(self, timestamp, server, value): + self.timestamp = timestamp + self.server = server + self.value = value + + @abstractmethod + def threshold(self): + pass + + @abstractmethod + def metric_name(self): + pass + + def severity(self): + return self.value - self.threshold() + + def is_critical(self): + return self.severity() > 0 + + def __str__(self): + return f"{self.server} {self.metric_name()} {self.value} {"(CRITICAL)" if self.is_critical() else "(ok)"}" + + def __repr__(self): + return f"{type(self).__name__}('{self.timestamp}', '{self.server}', {self.value})" + + def __eq__(self, other): + if isinstance(other, Alert): + if self.metric_name() == other.metric_name() and self.server == other.server and self.timestamp == other.timestamp: + return True + return False + + def __hash__(self): + return hash((self.metric_name(), self.server, self.timestamp)) + + @classmethod + def from_line(cls, line): + alert_types = {"cpu": CpuAlert, "memory": MemoryAlert, "disk": DiskAlert} + try: + timestamp, server, metric, value_str = line.split(" ") + value = float(value_str) + except ValueError: + raise ValueError("Invalid value") + if metric not in alert_types: + raise ValueError(f"Unknown metric: {metric}") + return alert_types[metric](timestamp, server, value) + + +class CpuAlert(Alert): + + def threshold(self): + return 90 + + def metric_name(self): + return "cpu" + +class MemoryAlert(Alert): + def threshold(self): + return 85 + + def metric_name(self): + return "memory" + +class DiskAlert(Alert): + def threshold(self): + return 95 + + def metric_name(self): + return "disk" diff --git a/oop/exercise_2/AlertLog.py b/oop/exercise_2/AlertLog.py new file mode 100644 index 0000000..fc41896 --- /dev/null +++ b/oop/exercise_2/AlertLog.py @@ -0,0 +1,49 @@ +#from Alert import Alert +from collections import defaultdict, Counter +from logging import critical + +from oop.exercise_2.Alert import Alert + + +class AlertLog: + + def __init__(self): + self.alerts = [] + + def add(self, alert): + if alert not in self.alerts: + self.alerts.append(alert) + + def __len__(self): + return len(self.alerts) + + def __contains__(self, alert): + if alert in self.alerts: + return True + return False + + def critical_alerts(self): + alert_list = [] + for alert in self.alerts: + if alert.is_critical(): + alert_list.append(alert) + + return alert_list + + def by_server(self): + alert_dict = defaultdict(list) + for alert in self.alerts: + alert_dict[alert.server].append(alert.metric_name()) + return {server: sorted(metric) for server,metric in alert_dict.items()} + + def sorted_by_severity(self): + return sorted(self.alerts, key=lambda a:(-a.severity(), a.server)) + + def worst_offender(self): + return Counter(alert.server for alert in self.alerts) + + def summary(self): + return {"total": self.__len__(), "critical":self.critical_alerts(), "servers": self.by_server()} + + + diff --git a/oop/exercise_2/main.py b/oop/exercise_2/main.py new file mode 100644 index 0000000..ddb07b9 --- /dev/null +++ b/oop/exercise_2/main.py @@ -0,0 +1,40 @@ +from AlertLog import AlertLog +from Alert import Alert +raw_alerts = [ + "2026-08-21T10:00 web-01 cpu 95.5", + "2026-08-21T10:05 web-02 memory 88.0", + "2026-08-21T10:10 web-01 disk 97.2", + "malformed line", + "2026-08-21T10:00 web-01 cpu 95.5", # exact duplicate of line 1 + "2026-08-21T10:20 db-01 cpu 91.0", + "2026-08-21T10:25 web-02 memory 70.0", # below threshold + "2026-08-21T10:30 db-01 unknown 50.0", # unknown metric + "2026-08-21T10:35 web-01 memory 92.0", +] +def main(): + log = AlertLog() + for line in raw_alerts: + try: + log.add(Alert.from_line(line)) + except ValueError: + pass + + print(len(log) == 6) # 9 lines − 1 malformed − 1 unknown − 1 duplicate + print(len(log.critical_alerts()) == 5) + print(log.worst_offender() == ("web-01", 3)) + print(log.by_server()["web-01"] == ["cpu", "disk", "memory"]) + print(log.summary()["servers"] == 3) + print(log.sorted_by_severity()[0].server == "web-01") + print(log.sorted_by_severity()[0].severity() == 7.0) + + a = Alert.from_line("2026-08-21T10:00 web-01 cpu 95.5") + b = Alert.from_line("2026-08-21T10:00 web-01 cpu 95.5") + print(a == b and hash(a) == hash(b)) + print(a == "web-01" or True) # must not crash + print(type(a).__name__ == "CpuAlert") + print(repr(a) == "CpuAlert('2026-08-21T10:00', 'web-01', 95.5)") + print(len([(x, y) for x in log for y in log]) == 36) # nested loop → re-iterable + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/searching_sorting/binary_search/exercise_5.py b/searching_sorting/binary_search/exercise_5.py new file mode 100644 index 0000000..220c55c --- /dev/null +++ b/searching_sorting/binary_search/exercise_5.py @@ -0,0 +1,22 @@ +def main(): + nums = [1, 3, 5, 7, 9, 11] + target = 9 + print(binary_search(nums,target)) + +def binary_search(nums,target): + + left = 0 + right = len(nums)-1 + while left<=right: + mid = left + (right-left) // 2 + + if nums[mid]==target: + return mid + elif nums[mid]>target: + right = mid - 1 + else: + left = mid + 1 + return -1 + +if __name__ == "__main__": + main() diff --git a/searching_sorting/bubble_sort/exercise_4.py b/searching_sorting/bubble_sort/exercise_4.py index add481c..e08be64 100644 --- a/searching_sorting/bubble_sort/exercise_4.py +++ b/searching_sorting/bubble_sort/exercise_4.py @@ -1,5 +1,5 @@ def main(): - nums = [1,4,5,7,8] + nums = [5, 1, 4, 2, 8] print(bubble_sort(nums)) def bubble_sort(nums): @@ -9,7 +9,7 @@ def bubble_sort(nums): if nums[j] > nums[j+1]: nums[j], nums[j+1] = nums[j+1], nums[j] swapped = True - if swapped == True: + if swapped == False: break return nums diff --git a/searching_sorting/bubble_sort/exercise_5.py b/searching_sorting/bubble_sort/exercise_5.py new file mode 100644 index 0000000..47a4340 --- /dev/null +++ b/searching_sorting/bubble_sort/exercise_5.py @@ -0,0 +1,17 @@ +def main(): + nums = [5, 1, 4, 2, 8] + bubble_sort(nums) + print(nums) + +def bubble_sort(nums): + for i in range(len(nums)): + swapped = False + for j in range(len(nums)-i-1): + if nums[j] > nums[j+1]: + nums[j], nums[j+1] = nums[j+1], nums[j] + swapped=True + if not swapped: + break + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/searching_sorting/builtin_search/Employee.py b/searching_sorting/builtin_search/Employee.py index 4edce5a..eb43180 100644 --- a/searching_sorting/builtin_search/Employee.py +++ b/searching_sorting/builtin_search/Employee.py @@ -1,7 +1,11 @@ class Employee: - def __init__(self,name, salary): + def __init__(self,name, department, salary): self.name = name + self.department = department self.salary = salary def __str__(self): - return f"{self.name} {self.salary}" \ No newline at end of file + return f"{self.name} {self.department} {self.salary}" + + def __repr__(self): + return f"{self.name} {self.department} {self.salary}" \ No newline at end of file diff --git a/searching_sorting/builtin_search/exercise_1.py b/searching_sorting/builtin_search/exercise_1.py index 5de7120..147b7d6 100644 --- a/searching_sorting/builtin_search/exercise_1.py +++ b/searching_sorting/builtin_search/exercise_1.py @@ -2,20 +2,42 @@ def main(): employees = [ - Employee("Chen", 6000), - Employee("Adem", 4000), - Employee("Filip", 5000), - Employee("Dana", 3000), + Employee("Chen", "IT", 6000), + Employee("Adem", "Sales", 4000), + Employee("Filip", "IT", 5000), + Employee("Dana", "Sales", 4000), + Employee("Bora", "IT", 6000), + Employee("Elif", "HR", 3500), ] - employees.sort(key=lambda e: e.salary, reverse=True) - print("By salary:") - for e in employees: print(" ", e) + salaries = {"Chen": 6000, "Adem": 4000, "Filip": 5000, "Dana": 3000} + #employees.sort(key=lambda e: e.salary, reverse=True) + #print("By salary:") + #for e in employees: print(" ", e) - employees.sort(key=lambda e: e.name) + #employees.sort(key=lambda e: e.name) - print("By name:") - for e in employees: print(" ", e) + #print("By name:") + #for e in employees: print(" ", e) + + sorted_salaries = sorted(employees, key=lambda e: e.salary, reverse=True) + + sorted_names = [e.name for e in sorted(employees, key=lambda e: e.name)] + + sorted_departments = sorted(employees, key=lambda e:(e.department, -e.salary)) + + three_highest = [(e.name, e.salary) for e in sorted(employees, key=lambda e:e.salary, reverse=True)[:3]] + # → [('Chen', 6000), ('Bora', 6000), ('Filip', 5000)] + + sorted_tuple_salaries = sorted(salaries.items(), key=lambda item:item[1], reverse=True) + + sorted_names_by_length = sorted(salaries, key=lambda n:(len(n), n)) + print(sorted_salaries) + print(sorted_names) + print(sorted_departments) + print(three_highest) + print(sorted_tuple_salaries) + print(sorted_names_by_length) if __name__ == "__main__": main() \ No newline at end of file diff --git a/sliding_window/task1/exercise_5.py b/sliding_window/task1/exercise_5.py new file mode 100644 index 0000000..9633a47 --- /dev/null +++ b/sliding_window/task1/exercise_5.py @@ -0,0 +1,22 @@ +def main(): + nums = [2,1,5,2,3,2] + k = 3 + print(max_sum_subarray(nums, k)) + +def max_sum_subarray(nums,k): + + max_sum = 0 + window_sum = 0 + for i in range(k): + window_sum+=nums[i] + + for j in range(k, len(nums)): + window_sum = window_sum + nums[j] - nums[j-k] + #print(window_sum, j) + if window_sum>max_sum: + max_sum = window_sum + #return round(max_sum/len(nums),1) + return max_sum + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/sliding_window/task2/exercise_4.py b/sliding_window/task2/exercise_4.py new file mode 100644 index 0000000..8cd7175 --- /dev/null +++ b/sliding_window/task2/exercise_4.py @@ -0,0 +1,23 @@ +def main(): + nums = [2, 1, 5, 2, 3, 2] + k = 3 + print(average_max_subarray(nums, k)) + +def average_max_subarray(nums, k): + + window_sum = 0 + max_sum = 0 + for i in range(k): + window_sum +=nums[i] + max_sum = window_sum + + for j in range(k, len(nums)): + window_sum = window_sum + nums[j] - nums[j-k] + + if window_sum>max_sum: + max_sum = window_sum + + return round(max_sum/len(nums),1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/sliding_window/task3/exercise_4.py b/sliding_window/task3/exercise_4.py new file mode 100644 index 0000000..3c04913 --- /dev/null +++ b/sliding_window/task3/exercise_4.py @@ -0,0 +1,25 @@ +def main(): + s = "abcabcbb" + print(longest_substring(s)) + +def longest_substring(s): + max_length = 0 + seen = set() + left = 0 + best_start = 0 + + for right in range(len(s)): + + if s[right] in seen: + seen.remove(s[left]) + left+=1 + seen.add(s[right]) + + if right - left + 1 > max_length: + max_length = right - left +1 + best_start = left + #return max_length + return s[best_start:max_length] + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/sliding_window/task3/exercise_5.py b/sliding_window/task3/exercise_5.py new file mode 100644 index 0000000..7a1f7c8 --- /dev/null +++ b/sliding_window/task3/exercise_5.py @@ -0,0 +1,25 @@ +def main(): + s = "abcabcbb" + print(longest_substring(s)) + +def longest_substring(s): + seen = set() + max_length = 0 + left =0 + best_start = 0 + for right in range(len(s)): + + if s[right] in seen: + seen.remove(s[left]) + left+=1 + + if right-left+1 > max_length: + max_length = right-left+1 + best_start = left + + seen.add(s[right]) + + return s[best_start:max_length] + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/sliding_window/task3/exercise_6.py b/sliding_window/task3/exercise_6.py new file mode 100644 index 0000000..5626323 --- /dev/null +++ b/sliding_window/task3/exercise_6.py @@ -0,0 +1,24 @@ + + +def main(): + s = "abcabcbb" + print(longest_non_repeating_substring(s)) + +def longest_non_repeating_substring(s): + seen = set() + left=0 + max_length=0 + best_start=0 + for right in range(len(s)): + if s[right] in seen: + seen.remove(s[left]) + left+=1 + if right-left+1 > max_length: + max_length = right-left+1 + best_start=left + seen.add(s[right]) + + return s[best_start:max_length] + +if __name__ == "__main__": + main() diff --git a/stack_queue/task1/exercise_3.py b/stack_queue/task1/exercise_3.py new file mode 100644 index 0000000..717b91d --- /dev/null +++ b/stack_queue/task1/exercise_3.py @@ -0,0 +1,20 @@ +def main(): + s = "{[()]}" + print(is_valid_parentheses(s)) + +def is_valid_parentheses(s): + stack = [] + pairs = {")":"(", "]":"[", "}":"{"} + + for c in s: + if c in pairs.values(): + stack.append(c) + + if c in pairs: + if not stack: + return False + if stack.pop() != pairs[c]: + return False + return len(stack) == 0 +if __name__ == "__main__": + main() \ No newline at end of file From 452c23e23a99b16413a7df02dbe9bc41aaa1bca4 Mon Sep 17 00:00:00 2001 From: hakanyorukk Date: Mon, 24 Aug 2026 10:16:33 +0300 Subject: [PATCH 2/3] fix oop/exercise_2 --- oop/exercise_2/AlertLog.py | 30 ++++++++++++++++++------------ oop/exercise_2/main.py | 1 + 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/oop/exercise_2/AlertLog.py b/oop/exercise_2/AlertLog.py index fc41896..bfac97a 100644 --- a/oop/exercise_2/AlertLog.py +++ b/oop/exercise_2/AlertLog.py @@ -1,9 +1,4 @@ -#from Alert import Alert from collections import defaultdict, Counter -from logging import critical - -from oop.exercise_2.Alert import Alert - class AlertLog: @@ -18,9 +13,20 @@ def __len__(self): return len(self.alerts) def __contains__(self, alert): - if alert in self.alerts: - return True - return False + return alert in self.alerts + + def __iter__(self): + return iter(self.alerts) + # self.index = 0 + # return self + + # def __next__(self): + # + # if self.index>=len(self.alerts): + # raise StopIteration + # alert = self.alerts[self.index] + # self.index+=1 + # return alert def critical_alerts(self): alert_list = [] @@ -31,19 +37,19 @@ def critical_alerts(self): return alert_list def by_server(self): - alert_dict = defaultdict(list) + alert_dict = defaultdict(set) for alert in self.alerts: - alert_dict[alert.server].append(alert.metric_name()) + alert_dict[alert.server].add(alert.metric_name()) return {server: sorted(metric) for server,metric in alert_dict.items()} def sorted_by_severity(self): return sorted(self.alerts, key=lambda a:(-a.severity(), a.server)) def worst_offender(self): - return Counter(alert.server for alert in self.alerts) + return Counter(alert.server for alert in self.alerts).most_common(1)[0] def summary(self): - return {"total": self.__len__(), "critical":self.critical_alerts(), "servers": self.by_server()} + return {"total": self.__len__(), "critical":len(self.critical_alerts()), "servers": len({a.server for a in self.alerts})} diff --git a/oop/exercise_2/main.py b/oop/exercise_2/main.py index ddb07b9..40b7a19 100644 --- a/oop/exercise_2/main.py +++ b/oop/exercise_2/main.py @@ -36,5 +36,6 @@ def main(): print(len([(x, y) for x in log for y in log]) == 36) # nested loop → re-iterable + if __name__ == "__main__": main() \ No newline at end of file From b1d1539a34128dbd2695d104b644febb76d22034 Mon Sep 17 00:00:00 2001 From: hakanyorukk Date: Mon, 24 Aug 2026 10:19:21 +0300 Subject: [PATCH 3/3] fix-2 oop/exercise_2 --- oop/exercise_2/Alert.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oop/exercise_2/Alert.py b/oop/exercise_2/Alert.py index a38df4b..55c766e 100644 --- a/oop/exercise_2/Alert.py +++ b/oop/exercise_2/Alert.py @@ -22,7 +22,8 @@ def is_critical(self): return self.severity() > 0 def __str__(self): - return f"{self.server} {self.metric_name()} {self.value} {"(CRITICAL)" if self.is_critical() else "(ok)"}" + status = "(CRITICAL)" if self.is_critical() else "(ok)" + return f"{self.server} {self.metric_name()} {self.value} {status}" def __repr__(self): return f"{type(self).__name__}('{self.timestamp}', '{self.server}', {self.value})"