From 95675ea482323a00adacf224b07f53a2bb3f5e8f Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Tue, 10 Mar 2026 13:39:44 +0300 Subject: [PATCH 01/36] Add function to calculate pyramid height --- Week03/pyramid_senkiv_vladyslav | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Week03/pyramid_senkiv_vladyslav diff --git a/Week03/pyramid_senkiv_vladyslav b/Week03/pyramid_senkiv_vladyslav new file mode 100644 index 00000000..f9aaddd5 --- /dev/null +++ b/Week03/pyramid_senkiv_vladyslav @@ -0,0 +1,10 @@ +def calculate_pyramid_height(number_of_blocks): + height = 0 + i = 1 + + while number_of_blocks >= i: + number_of_blocks = number_of_blocks - i + height += 1 + i += 1 + + return height From 7446839b70eca5b467d190bc8feb597ebb5b21dc Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Tue, 10 Mar 2026 13:40:14 +0300 Subject: [PATCH 02/36] Rename pyramid_senkiv_vladyslav to pyramid_senkiv_vladyslav.py --- Week03/{pyramid_senkiv_vladyslav => pyramid_senkiv_vladyslav.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Week03/{pyramid_senkiv_vladyslav => pyramid_senkiv_vladyslav.py} (100%) diff --git a/Week03/pyramid_senkiv_vladyslav b/Week03/pyramid_senkiv_vladyslav.py similarity index 100% rename from Week03/pyramid_senkiv_vladyslav rename to Week03/pyramid_senkiv_vladyslav.py From d4283e9b6952715d432b1c6038b750745e890dd7 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Sat, 28 Mar 2026 15:19:04 +0300 Subject: [PATCH 03/36] Rename pyramid_senkiv_vladyslav.py to pyramid_vladyslav_senkiv.py --- .../{pyramid_senkiv_vladyslav.py => pyramid_vladyslav_senkiv.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Week03/{pyramid_senkiv_vladyslav.py => pyramid_vladyslav_senkiv.py} (100%) diff --git a/Week03/pyramid_senkiv_vladyslav.py b/Week03/pyramid_vladyslav_senkiv.py similarity index 100% rename from Week03/pyramid_senkiv_vladyslav.py rename to Week03/pyramid_vladyslav_senkiv.py From cab235348fbb49a315a7ea2ced6de94654e9d1b7 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Sun, 5 Apr 2026 16:03:42 +0300 Subject: [PATCH 04/36] add sequences_vladyslav_senkiv.py Removed docstring comments from three functions. --- Week03/sequences_vladyslav_senkiv.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Week03/sequences_vladyslav_senkiv.py diff --git a/Week03/sequences_vladyslav_senkiv.py b/Week03/sequences_vladyslav_senkiv.py new file mode 100644 index 00000000..7241c055 --- /dev/null +++ b/Week03/sequences_vladyslav_senkiv.py @@ -0,0 +1,17 @@ +def remove_duplicates(seq: list) -> list: + result = [] + for item in seq: + if item not in result: + result.append(item) + return result + + +def list_counts(seq: list) -> dict: + counts = {} + for item in seq: + counts[item] = counts.get(item, 0) + 1 + return counts + + +def reverse_dict(d: dict) -> dict: + return {value: key for key, value in d.items()} From 2914844c5d063d3af04cc44825038f9bbab385ab Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Sun, 5 Apr 2026 16:09:25 +0300 Subject: [PATCH 05/36] Create decorators_vladyslav_senkiv.py --- Week04/decorators_vladyslav_senkiv.py | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Week04/decorators_vladyslav_senkiv.py diff --git a/Week04/decorators_vladyslav_senkiv.py b/Week04/decorators_vladyslav_senkiv.py new file mode 100644 index 00000000..f1d5e232 --- /dev/null +++ b/Week04/decorators_vladyslav_senkiv.py @@ -0,0 +1,28 @@ +from functools import wraps +from time import perf_counter +import tracemalloc + + + +def performance(func): + + @wraps(func) + def wrapper(*args, **kwargs): + wrapper.counter += 1 + + tracemalloc.start() + start = perf_counter() + try: + return func(*args, **kwargs) + finally: + elapsed = perf_counter() - start + current, peak = tracemalloc.get_traced_memory() + tracemalloc.stop() + + wrapper.total_time += elapsed + wrapper.total_mem += peak + + wrapper.counter = 0 + wrapper.total_time = 0.0 + wrapper.total_mem = 0 + return wrapper From a342200d6276024874ed129d7292a2708eeea249 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Sun, 5 Apr 2026 16:11:47 +0300 Subject: [PATCH 06/36] Create functions_vladyslav_senkiv.py --- Week04/functions_vladyslav_senkiv.py | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Week04/functions_vladyslav_senkiv.py diff --git a/Week04/functions_vladyslav_senkiv.py b/Week04/functions_vladyslav_senkiv.py new file mode 100644 index 00000000..be7eca34 --- /dev/null +++ b/Week04/functions_vladyslav_senkiv.py @@ -0,0 +1,41 @@ +import inspect +from typing import Dict, Tuple + + +custom_power = lambda x=0, /, e=1: x**e + + +def custom_equation( + x: int = 0, + y: int = 0, + /, + a: int = 1, + b: int = 1, + *, + c: int = 1, +) -> float: + """Calculate a custom equation. + + :param x: First base value. + :param y: Second base value. + :param a: Exponent for x. + :param b: Exponent for y. + :param c: Divisor value. + :returns: The result of (x**a + y**b) / c. + """ + return float((x**a + y**b) / c) + + +def fn_w_counter() -> Tuple[int, Dict[str, int]]: + """Count total calls and calls grouped by caller module name.""" + if not hasattr(fn_w_counter, "total_calls"): + fn_w_counter.total_calls = 0 + fn_w_counter.caller_counts = {} + + caller_frame = inspect.currentframe().f_back + caller_name = caller_frame.f_globals.get("__name__", "__main__") + + fn_w_counter.total_calls += 1 + fn_w_counter.caller_counts[caller_name] = fn_w_counter.caller_counts.get(caller_name, 0) + 1 + + return fn_w_counter.total_calls, dict(fn_w_counter.caller_counts) From 4ee7ef07541c8191e4fc91bdf917fe8cc9a27462 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Sun, 5 Apr 2026 16:13:35 +0300 Subject: [PATCH 07/36] Create awaitme_vladyslav_senkiv.py --- Week05/awaitme_vladyslav_senkiv.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Week05/awaitme_vladyslav_senkiv.py diff --git a/Week05/awaitme_vladyslav_senkiv.py b/Week05/awaitme_vladyslav_senkiv.py new file mode 100644 index 00000000..76d2e5d2 --- /dev/null +++ b/Week05/awaitme_vladyslav_senkiv.py @@ -0,0 +1,14 @@ +import inspect +from functools import wraps + + + +def awaitme(func): + @wraps(func) + async def wrapper(*args, **kwargs): + result = func(*args, **kwargs) + if inspect.isawaitable(result): + return await result + return result + + return wrapper From 293ce8e2430bcfd208013a84c0f8671bf3e0176c Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Sun, 5 Apr 2026 16:15:57 +0300 Subject: [PATCH 08/36] Create timer_vladyslav_senkiv.py --- Week06/timer_vladyslav_senkiv.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Week06/timer_vladyslav_senkiv.py diff --git a/Week06/timer_vladyslav_senkiv.py b/Week06/timer_vladyslav_senkiv.py new file mode 100644 index 00000000..76b8354d --- /dev/null +++ b/Week06/timer_vladyslav_senkiv.py @@ -0,0 +1,15 @@ +from time import perf_counter + +class Timer: + + def __init__(self): + self.start_time = None + self.end_time = None + + def __enter__(self): + self.start_time = perf_counter() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.end_time = perf_counter() + return False From 6efe4a96843ddfee8b14b85a300acae36db5a446 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Mon, 20 Apr 2026 13:49:48 +0300 Subject: [PATCH 09/36] Update functions_vladyslav_senkiv.py --- Week04/functions_vladyslav_senkiv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Week04/functions_vladyslav_senkiv.py b/Week04/functions_vladyslav_senkiv.py index be7eca34..bea89824 100644 --- a/Week04/functions_vladyslav_senkiv.py +++ b/Week04/functions_vladyslav_senkiv.py @@ -26,7 +26,7 @@ def custom_equation( return float((x**a + y**b) / c) -def fn_w_counter() -> Tuple[int, Dict[str, int]]: +def fn_w_counter() -> (int, dict[str, int]): """Count total calls and calls grouped by caller module name.""" if not hasattr(fn_w_counter, "total_calls"): fn_w_counter.total_calls = 0 From befb2e82e91f52589e41734bd178136f0fc3bba7 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Tue, 5 May 2026 10:28:40 +0300 Subject: [PATCH 10/36] Update functions_vladyslav_senkiv.py --- Week04/functions_vladyslav_senkiv.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Week04/functions_vladyslav_senkiv.py b/Week04/functions_vladyslav_senkiv.py index bea89824..f45074cc 100644 --- a/Week04/functions_vladyslav_senkiv.py +++ b/Week04/functions_vladyslav_senkiv.py @@ -1,7 +1,5 @@ -import inspect from typing import Dict, Tuple - custom_power = lambda x=0, /, e=1: x**e @@ -14,7 +12,8 @@ def custom_equation( *, c: int = 1, ) -> float: - """Calculate a custom equation. + """ + Calculate a custom equation. :param x: First base value. :param y: Second base value. @@ -26,16 +25,17 @@ def custom_equation( return float((x**a + y**b) / c) -def fn_w_counter() -> (int, dict[str, int]): - """Count total calls and calls grouped by caller module name.""" +def fn_w_counter() -> Tuple[int, Dict[str, int]]: + """Count total calls and calls grouped by this module name.""" if not hasattr(fn_w_counter, "total_calls"): fn_w_counter.total_calls = 0 fn_w_counter.caller_counts = {} - caller_frame = inspect.currentframe().f_back - caller_name = caller_frame.f_globals.get("__name__", "__main__") + module_name = __name__ fn_w_counter.total_calls += 1 - fn_w_counter.caller_counts[caller_name] = fn_w_counter.caller_counts.get(caller_name, 0) + 1 + fn_w_counter.caller_counts[module_name] = ( + fn_w_counter.caller_counts.get(module_name, 0) + 1 + ) return fn_w_counter.total_calls, dict(fn_w_counter.caller_counts) From da68022ace6311b9fb61c5b9f445c2a8da948120 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Tue, 5 May 2026 10:34:20 +0300 Subject: [PATCH 11/36] Update type hints for fn_w_counter function --- Week04/functions_vladyslav_senkiv.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Week04/functions_vladyslav_senkiv.py b/Week04/functions_vladyslav_senkiv.py index f45074cc..7035e3dc 100644 --- a/Week04/functions_vladyslav_senkiv.py +++ b/Week04/functions_vladyslav_senkiv.py @@ -1,5 +1,3 @@ -from typing import Dict, Tuple - custom_power = lambda x=0, /, e=1: x**e @@ -25,7 +23,7 @@ def custom_equation( return float((x**a + y**b) / c) -def fn_w_counter() -> Tuple[int, Dict[str, int]]: +def fn_w_counter() -> tuple[int, dict[str, int]]: """Count total calls and calls grouped by this module name.""" if not hasattr(fn_w_counter, "total_calls"): fn_w_counter.total_calls = 0 From 24ec4db21383a5aee9f8efd5c33aca21a50d6865 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Tue, 5 May 2026 10:35:51 +0300 Subject: [PATCH 12/36] Update functions_vladyslav_senkiv.py --- Week04/functions_vladyslav_senkiv.py | 68 ++++++++++++---------------- 1 file changed, 29 insertions(+), 39 deletions(-) diff --git a/Week04/functions_vladyslav_senkiv.py b/Week04/functions_vladyslav_senkiv.py index 7035e3dc..0cfc474e 100644 --- a/Week04/functions_vladyslav_senkiv.py +++ b/Week04/functions_vladyslav_senkiv.py @@ -1,39 +1,29 @@ -custom_power = lambda x=0, /, e=1: x**e - - -def custom_equation( - x: int = 0, - y: int = 0, - /, - a: int = 1, - b: int = 1, - *, - c: int = 1, -) -> float: - """ - Calculate a custom equation. - - :param x: First base value. - :param y: Second base value. - :param a: Exponent for x. - :param b: Exponent for y. - :param c: Divisor value. - :returns: The result of (x**a + y**b) / c. - """ - return float((x**a + y**b) / c) - - -def fn_w_counter() -> tuple[int, dict[str, int]]: - """Count total calls and calls grouped by this module name.""" - if not hasattr(fn_w_counter, "total_calls"): - fn_w_counter.total_calls = 0 - fn_w_counter.caller_counts = {} - - module_name = __name__ - - fn_w_counter.total_calls += 1 - fn_w_counter.caller_counts[module_name] = ( - fn_w_counter.caller_counts.get(module_name, 0) + 1 - ) - - return fn_w_counter.total_calls, dict(fn_w_counter.caller_counts) + +custom_power = lambda x=0,/, e=1 : x ** e + + +def custom_equation(x: int = 0 , y: int = 0 , /, a: int = 1, b: int=1 , * , c: int = 1) -> float : + """ + This function returns the result of an operation based on the specified base and exponent values. + + :param x: First base value + :param y: Second base value + :param a: First exponent value + :param b: Second exponent value + :param c: Divisor value + :return: (x*a + y*b)/c + """ + return (x**a + y**b)/c + + +def fn_w_counter() -> (int, dict[str, int]): + if not hasattr(fn_w_counter, "calls"): + fn_w_counter.calls = 0 + + fn_w_counter.calls += 1 + + return fn_w_counter.calls, {__name__: fn_w_counter.calls} + + + + From d051de8bb0603336aab9c94c912dcd5eae7b1f3b Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Tue, 5 May 2026 10:40:52 +0300 Subject: [PATCH 13/36] Update decorators_vladyslav_senkiv.py --- Week04/decorators_vladyslav_senkiv.py | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Week04/decorators_vladyslav_senkiv.py b/Week04/decorators_vladyslav_senkiv.py index f1d5e232..1be275d3 100644 --- a/Week04/decorators_vladyslav_senkiv.py +++ b/Week04/decorators_vladyslav_senkiv.py @@ -1,28 +1,28 @@ -from functools import wraps -from time import perf_counter +import functools +import time import tracemalloc - def performance(func): - - @wraps(func) + @functools.wraps(func) def wrapper(*args, **kwargs): - wrapper.counter += 1 - tracemalloc.start() - start = perf_counter() - try: - return func(*args, **kwargs) - finally: - elapsed = perf_counter() - start - current, peak = tracemalloc.get_traced_memory() - tracemalloc.stop() + start_time = time.perf_counter() + + result = func(*args, **kwargs) - wrapper.total_time += elapsed - wrapper.total_mem += peak + end_time = time.perf_counter() + current_mem, peak_mem = tracemalloc.get_traced_memory() + tracemalloc.stop() + + wrapper.counter += 1 + wrapper.total_time += end_time - start_time + wrapper.total_mem += peak_mem + + return result wrapper.counter = 0 wrapper.total_time = 0.0 wrapper.total_mem = 0 + return wrapper From 8fdb8b308573e04b9cb2434b868099e1058cc19a Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Tue, 5 May 2026 10:43:38 +0300 Subject: [PATCH 14/36] Update decorators_vladyslav_senkiv.py --- Week04/decorators_vladyslav_senkiv.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Week04/decorators_vladyslav_senkiv.py b/Week04/decorators_vladyslav_senkiv.py index 1be275d3..15c43777 100644 --- a/Week04/decorators_vladyslav_senkiv.py +++ b/Week04/decorators_vladyslav_senkiv.py @@ -7,17 +7,17 @@ def performance(func): @functools.wraps(func) def wrapper(*args, **kwargs): tracemalloc.start() - start_time = time.perf_counter() + start = time.perf_counter() result = func(*args, **kwargs) - end_time = time.perf_counter() - current_mem, peak_mem = tracemalloc.get_traced_memory() + end = time.perf_counter() + current, peak = tracemalloc.get_traced_memory() tracemalloc.stop() wrapper.counter += 1 - wrapper.total_time += end_time - start_time - wrapper.total_mem += peak_mem + wrapper.total_time += end - start + wrapper.total_mem += peak return result From 5cda0023c535f8fc79cead72e9a8039f13135fd2 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Tue, 5 May 2026 10:46:12 +0300 Subject: [PATCH 15/36] Delete Week04/decorators_vladyslav_senkiv.py --- Week04/decorators_vladyslav_senkiv.py | 28 --------------------------- 1 file changed, 28 deletions(-) delete mode 100644 Week04/decorators_vladyslav_senkiv.py diff --git a/Week04/decorators_vladyslav_senkiv.py b/Week04/decorators_vladyslav_senkiv.py deleted file mode 100644 index 15c43777..00000000 --- a/Week04/decorators_vladyslav_senkiv.py +++ /dev/null @@ -1,28 +0,0 @@ -import functools -import time -import tracemalloc - - -def performance(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - tracemalloc.start() - start = time.perf_counter() - - result = func(*args, **kwargs) - - end = time.perf_counter() - current, peak = tracemalloc.get_traced_memory() - tracemalloc.stop() - - wrapper.counter += 1 - wrapper.total_time += end - start - wrapper.total_mem += peak - - return result - - wrapper.counter = 0 - wrapper.total_time = 0.0 - wrapper.total_mem = 0 - - return wrapper From 247854199a3d6b0d471ef178b5c539df5adc1981 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Tue, 5 May 2026 10:46:27 +0300 Subject: [PATCH 16/36] Delete Week04/functions_vladyslav_senkiv.py --- Week04/functions_vladyslav_senkiv.py | 29 ---------------------------- 1 file changed, 29 deletions(-) delete mode 100644 Week04/functions_vladyslav_senkiv.py diff --git a/Week04/functions_vladyslav_senkiv.py b/Week04/functions_vladyslav_senkiv.py deleted file mode 100644 index 0cfc474e..00000000 --- a/Week04/functions_vladyslav_senkiv.py +++ /dev/null @@ -1,29 +0,0 @@ - -custom_power = lambda x=0,/, e=1 : x ** e - - -def custom_equation(x: int = 0 , y: int = 0 , /, a: int = 1, b: int=1 , * , c: int = 1) -> float : - """ - This function returns the result of an operation based on the specified base and exponent values. - - :param x: First base value - :param y: Second base value - :param a: First exponent value - :param b: Second exponent value - :param c: Divisor value - :return: (x*a + y*b)/c - """ - return (x**a + y**b)/c - - -def fn_w_counter() -> (int, dict[str, int]): - if not hasattr(fn_w_counter, "calls"): - fn_w_counter.calls = 0 - - fn_w_counter.calls += 1 - - return fn_w_counter.calls, {__name__: fn_w_counter.calls} - - - - From af8267ab0a36d5b3ea792900b276b223e9f50a48 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 14:54:17 +0300 Subject: [PATCH 17/36] Update pyramid_vladyslav_senkiv.py --- Week03/pyramid_vladyslav_senkiv.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Week03/pyramid_vladyslav_senkiv.py b/Week03/pyramid_vladyslav_senkiv.py index f9aaddd5..c1f013d7 100644 --- a/Week03/pyramid_vladyslav_senkiv.py +++ b/Week03/pyramid_vladyslav_senkiv.py @@ -1,10 +1,10 @@ def calculate_pyramid_height(number_of_blocks): height = 0 - i = 1 + needed_blocks = 1 - while number_of_blocks >= i: - number_of_blocks = number_of_blocks - i + while number_of_blocks >= needed_blocks: + number_of_blocks -= needed_blocks height += 1 - i += 1 + needed_blocks += 1 return height From 1ef3815ae6b7e246dbcb63853403219b7e7b76a9 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 14:55:21 +0300 Subject: [PATCH 18/36] Update sequences_vladyslav_senkiv.py --- Week03/sequences_vladyslav_senkiv.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Week03/sequences_vladyslav_senkiv.py b/Week03/sequences_vladyslav_senkiv.py index 7241c055..d10dbfbf 100644 --- a/Week03/sequences_vladyslav_senkiv.py +++ b/Week03/sequences_vladyslav_senkiv.py @@ -1,17 +1,29 @@ def remove_duplicates(seq: list) -> list: result = [] + for item in seq: if item not in result: result.append(item) + return result def list_counts(seq: list) -> dict: - counts = {} + result = {} + for item in seq: - counts[item] = counts.get(item, 0) + 1 - return counts + if item in result: + result[item] += 1 + else: + result[item] = 1 + + return result def reverse_dict(d: dict) -> dict: - return {value: key for key, value in d.items()} + result = {} + + for key, value in d.items(): + result[value] = key + + return result From 802c4b90395dad66622c2accd93d7f4d618d07e6 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 14:57:22 +0300 Subject: [PATCH 19/36] Create functions_vladyslav_senkiv.py --- Week04/functions_vladyslav_senkiv.py | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Week04/functions_vladyslav_senkiv.py diff --git a/Week04/functions_vladyslav_senkiv.py b/Week04/functions_vladyslav_senkiv.py new file mode 100644 index 00000000..ae2aac43 --- /dev/null +++ b/Week04/functions_vladyslav_senkiv.py @@ -0,0 +1,42 @@ +custom_power = lambda x=0, /, e=1: x ** e + + +def custom_equation( + x: int = 0, + y: int = 0, + /, + a: int = 1, + b: int = 1, + *, + c: int = 1 +) -> float: + """ + Calculates the equation (a*x + b*y) / c. + + :param x: first integer value + :param y: second integer value + :param a: multiplier for x + :param b: multiplier for y + :param c: divisor value + :return: result of the equation + """ + + values = [x, y, a, b, c] + + for value in values: + if not isinstance(value, int): + raise TypeError("All parameters must be integers") + + return (a * x + b * y) / c + + +counter = 0 + + +def fn_w_counter() -> (int, dict[str, int]): + global counter + + counter += 1 + module_name = __name__ + + return counter, {module_name: counter} From 74e2f05ef73cc055ac99153d2f08b84e134786b8 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 14:57:58 +0300 Subject: [PATCH 20/36] Create decorators_vladyslav.senkiv.py --- Week04/decorators_vladyslav.senkiv.py | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Week04/decorators_vladyslav.senkiv.py diff --git a/Week04/decorators_vladyslav.senkiv.py b/Week04/decorators_vladyslav.senkiv.py new file mode 100644 index 00000000..08bd895b --- /dev/null +++ b/Week04/decorators_vladyslav.senkiv.py @@ -0,0 +1,30 @@ +import time +import sys +from functools import wraps + + +def performance(func): + @wraps(func) + def wrapper(*args, **kwargs): + start_time = time.perf_counter() + + result = func(*args, **kwargs) + + end_time = time.perf_counter() + + performance.counter += 1 + performance.total_time += end_time - start_time + performance.total_mem += sys.getsizeof(result) + + if isinstance(result, list): + for item in result: + performance.total_mem += sys.getsizeof(item) + + return result + + return wrapper + + +performance.counter = 0 +performance.total_time = 0 +performance.total_mem = 0 From 22c8d37e59a7bc3a5fa178088a7b676fba13d981 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 14:58:39 +0300 Subject: [PATCH 21/36] Update awaitme_vladyslav_senkiv.py --- Week05/awaitme_vladyslav_senkiv.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Week05/awaitme_vladyslav_senkiv.py b/Week05/awaitme_vladyslav_senkiv.py index 76d2e5d2..ce4d64a7 100644 --- a/Week05/awaitme_vladyslav_senkiv.py +++ b/Week05/awaitme_vladyslav_senkiv.py @@ -1,14 +1,9 @@ -import inspect from functools import wraps - def awaitme(func): @wraps(func) async def wrapper(*args, **kwargs): - result = func(*args, **kwargs) - if inspect.isawaitable(result): - return await result - return result + return func(*args, **kwargs) return wrapper From df93bbcf4f0db1236e7a3df5b64e984a4fb9ad8b Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 14:59:01 +0300 Subject: [PATCH 22/36] Update timer_vladyslav_senkiv.py --- Week06/timer_vladyslav_senkiv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Week06/timer_vladyslav_senkiv.py b/Week06/timer_vladyslav_senkiv.py index 76b8354d..2867f8d4 100644 --- a/Week06/timer_vladyslav_senkiv.py +++ b/Week06/timer_vladyslav_senkiv.py @@ -1,7 +1,7 @@ from time import perf_counter -class Timer: +class Timer: def __init__(self): self.start_time = None self.end_time = None @@ -10,6 +10,6 @@ def __enter__(self): self.start_time = perf_counter() return self - def __exit__(self, exc_type, exc_val, exc_tb): + def __exit__(self, exc_type, exc_value, traceback): self.end_time = perf_counter() return False From 0839de59cd8f8fc29dff1531dbf2a5a2969e5b34 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:00:11 +0300 Subject: [PATCH 23/36] Create threaded_vladyslav_senkiv.py --- Week07/threaded_vladyslav_senkiv.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 Week07/threaded_vladyslav_senkiv.py diff --git a/Week07/threaded_vladyslav_senkiv.py b/Week07/threaded_vladyslav_senkiv.py new file mode 100644 index 00000000..3868ed07 --- /dev/null +++ b/Week07/threaded_vladyslav_senkiv.py @@ -0,0 +1,25 @@ +import threading +from functools import wraps + + +def threaded(number_of_threads): + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + threads = [] + + for _ in range(number_of_threads): + thread = threading.Thread( + target=func, + args=args, + kwargs=kwargs + ) + threads.append(thread) + thread.start() + + for thread in threads: + thread.join() + + return wrapper + + return decorator From 820f247649ce81a8fcbff793a4f6f5c2879f325b Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:01:24 +0300 Subject: [PATCH 24/36] Create estimate_pi_w_threads_vladyslav_senkiv.py --- .../estimate_pi_w_threads_vladyslav_senkiv.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Week08/estimate_pi_w_threads_vladyslav_senkiv.py diff --git a/Week08/estimate_pi_w_threads_vladyslav_senkiv.py b/Week08/estimate_pi_w_threads_vladyslav_senkiv.py new file mode 100644 index 00000000..ffff4dad --- /dev/null +++ b/Week08/estimate_pi_w_threads_vladyslav_senkiv.py @@ -0,0 +1,47 @@ +import random +import threading +import math + + +class PiWorker(threading.Thread): + def __init__(self, points_count): + super().__init__() + self.points_count = points_count + self.inside_circle = 0 + + def run(self): + for _ in range(self.points_count): + x = random.random() + y = random.random() + + if x * x + y * y <= 1: + self.inside_circle += 1 + + +def estimate_pi(total_points=1000000, thread_count=4): + points_per_thread = total_points // thread_count + threads = [] + + for _ in range(thread_count): + thread = PiWorker(points_per_thread) + threads.append(thread) + thread.start() + + inside_circle = 0 + + for thread in threads: + thread.join() + inside_circle += thread.inside_circle + + used_points = points_per_thread * thread_count + pi_value = 4 * inside_circle / used_points + + return pi_value + + +if __name__ == "__main__": + pi = estimate_pi(total_points=1000000, thread_count=4) + + print("Estimated PI:", pi) + print("Real PI:", math.pi) + print("Difference:", abs(math.pi - pi)) From 197b3804db3ae49d26b04248891766951fa043f3 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:03:06 +0300 Subject: [PATCH 25/36] Create dining_philosophers_vladyslav_senkiv.py --- dining_philosophers_vladyslav_senkiv.py | 72 +++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 dining_philosophers_vladyslav_senkiv.py diff --git a/dining_philosophers_vladyslav_senkiv.py b/dining_philosophers_vladyslav_senkiv.py new file mode 100644 index 00000000..df8d871d --- /dev/null +++ b/dining_philosophers_vladyslav_senkiv.py @@ -0,0 +1,72 @@ +import threading +import time +import random + + +class Fork: + def __init__(self, number): + self.number = number + self.lock = threading.Lock() + + +class Philosopher(threading.Thread): + def __init__(self, number, left_fork, right_fork, meals_count=3): + super().__init__() + self.number = number + self.left_fork = left_fork + self.right_fork = right_fork + self.meals_count = meals_count + + def think(self): + print(f"Philosopher {self.number} is thinking") + time.sleep(random.uniform(0.5, 1.5)) + + def eat(self): + print(f"Philosopher {self.number} is eating") + time.sleep(random.uniform(0.5, 1.5)) + + def run(self): + for _ in range(self.meals_count): + self.think() + + if self.number % 2 == 0: + first_fork = self.left_fork + second_fork = self.right_fork + else: + first_fork = self.right_fork + second_fork = self.left_fork + + with first_fork.lock: + print(f"Philosopher {self.number} took fork {first_fork.number}") + + with second_fork.lock: + print(f"Philosopher {self.number} took fork {second_fork.number}") + self.eat() + + print(f"Philosopher {self.number} released fork {second_fork.number}") + + print(f"Philosopher {self.number} released fork {first_fork.number}") + + +if __name__ == "__main__": + philosophers_count = 5 + forks = [Fork(i) for i in range(philosophers_count)] + + philosophers = [] + + for i in range(philosophers_count): + philosopher = Philosopher( + number=i, + left_fork=forks[i], + right_fork=forks[(i + 1) % philosophers_count], + meals_count=3 + ) + philosophers.append(philosopher) + + for philosopher in philosophers: + philosopher.start() + + for philosopher in philosophers: + philosopher.join() + + print("Dinner is finished") From 343493c0040bff66ff237396fb83addce4093614 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:07:26 +0300 Subject: [PATCH 26/36] Create dining_philosophers_vladyslav_senkiv.py --- .../dining_philosophers_vladyslav_senkiv.py | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Week09/dining_philosophers_vladyslav_senkiv.py diff --git a/Week09/dining_philosophers_vladyslav_senkiv.py b/Week09/dining_philosophers_vladyslav_senkiv.py new file mode 100644 index 00000000..df8d871d --- /dev/null +++ b/Week09/dining_philosophers_vladyslav_senkiv.py @@ -0,0 +1,72 @@ +import threading +import time +import random + + +class Fork: + def __init__(self, number): + self.number = number + self.lock = threading.Lock() + + +class Philosopher(threading.Thread): + def __init__(self, number, left_fork, right_fork, meals_count=3): + super().__init__() + self.number = number + self.left_fork = left_fork + self.right_fork = right_fork + self.meals_count = meals_count + + def think(self): + print(f"Philosopher {self.number} is thinking") + time.sleep(random.uniform(0.5, 1.5)) + + def eat(self): + print(f"Philosopher {self.number} is eating") + time.sleep(random.uniform(0.5, 1.5)) + + def run(self): + for _ in range(self.meals_count): + self.think() + + if self.number % 2 == 0: + first_fork = self.left_fork + second_fork = self.right_fork + else: + first_fork = self.right_fork + second_fork = self.left_fork + + with first_fork.lock: + print(f"Philosopher {self.number} took fork {first_fork.number}") + + with second_fork.lock: + print(f"Philosopher {self.number} took fork {second_fork.number}") + self.eat() + + print(f"Philosopher {self.number} released fork {second_fork.number}") + + print(f"Philosopher {self.number} released fork {first_fork.number}") + + +if __name__ == "__main__": + philosophers_count = 5 + forks = [Fork(i) for i in range(philosophers_count)] + + philosophers = [] + + for i in range(philosophers_count): + philosopher = Philosopher( + number=i, + left_fork=forks[i], + right_fork=forks[(i + 1) % philosophers_count], + meals_count=3 + ) + philosophers.append(philosopher) + + for philosopher in philosophers: + philosopher.start() + + for philosopher in philosophers: + philosopher.join() + + print("Dinner is finished") From 628e6a348a1cfba7022cf21947d8fae26d2331fc Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:17:18 +0300 Subject: [PATCH 27/36] fix --- Week04/functions_vladyslav_senkiv.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Week04/functions_vladyslav_senkiv.py b/Week04/functions_vladyslav_senkiv.py index ae2aac43..0452fc16 100644 --- a/Week04/functions_vladyslav_senkiv.py +++ b/Week04/functions_vladyslav_senkiv.py @@ -11,23 +11,23 @@ def custom_equation( c: int = 1 ) -> float: """ - Calculates the equation (a*x + b*y) / c. - - :param x: first integer value - :param y: second integer value - :param a: multiplier for x - :param b: multiplier for y - :param c: divisor value - :return: result of the equation + Calculates custom equation. + + :param x: first number + :param y: second number + :param a: coefficient for x + :param b: coefficient for y + :param c: divisor + :return: result of equation """ values = [x, y, a, b, c] for value in values: if not isinstance(value, int): - raise TypeError("All parameters must be integers") + raise TypeError("value must be int") - return (a * x + b * y) / c + return (x * a + y * b) / c counter = 0 @@ -37,6 +37,5 @@ def fn_w_counter() -> (int, dict[str, int]): global counter counter += 1 - module_name = __name__ - return counter, {module_name: counter} + return counter, {__name__: counter} From 0ad8bc40713a29a2fe15a658bce035dfcbe3c576 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:18:30 +0300 Subject: [PATCH 28/36] fix week 4 --- Week04/functions_vladyslav_senkiv.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Week04/functions_vladyslav_senkiv.py b/Week04/functions_vladyslav_senkiv.py index 0452fc16..e2fb6131 100644 --- a/Week04/functions_vladyslav_senkiv.py +++ b/Week04/functions_vladyslav_senkiv.py @@ -15,10 +15,10 @@ def custom_equation( :param x: first number :param y: second number - :param a: coefficient for x - :param b: coefficient for y + :param a: additional parameter + :param b: power value :param c: divisor - :return: result of equation + :return: result of custom equation """ values = [x, y, a, b, c] @@ -27,7 +27,7 @@ def custom_equation( if not isinstance(value, int): raise TypeError("value must be int") - return (x * a + y * b) / c + return (x + y ** b) / c counter = 0 From bcb1f419c4568b7be97781b2f63179a5e57dc00b Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:21:00 +0300 Subject: [PATCH 29/36] fix week 4 decorators From 366b85a5c31763f4e6237f20c05f50c456a5e17b Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:27:32 +0300 Subject: [PATCH 30/36] Update decorators_vladyslav.senkiv.py From e975e60b6d2560de796c13313b427227e492150b Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:29:45 +0300 Subject: [PATCH 31/36] fix --- Week04/decorators_vladyslav.senkiv.py | 60 ++++++++++++++------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/Week04/decorators_vladyslav.senkiv.py b/Week04/decorators_vladyslav.senkiv.py index 08bd895b..6d008187 100644 --- a/Week04/decorators_vladyslav.senkiv.py +++ b/Week04/decorators_vladyslav.senkiv.py @@ -1,30 +1,32 @@ +import functools import time -import sys -from functools import wraps - - -def performance(func): - @wraps(func) - def wrapper(*args, **kwargs): - start_time = time.perf_counter() - - result = func(*args, **kwargs) - - end_time = time.perf_counter() - - performance.counter += 1 - performance.total_time += end_time - start_time - performance.total_mem += sys.getsizeof(result) - - if isinstance(result, list): - for item in result: - performance.total_mem += sys.getsizeof(item) - - return result - - return wrapper - - -performance.counter = 0 -performance.total_time = 0 -performance.total_mem = 0 +import tracemalloc + +class PerformanceDecorator: + def __init__(self): + self.counter = 0 + self.total_time = 0 + self.total_mem = 0 + + def __call__(self, func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + self.counter += 1 + + # Track time + start_time = time.time() + + # Track memory + tracemalloc.start() + result = func(*args, **kwargs) + current, peak = tracemalloc.get_traced_memory() + tracemalloc.stop() + + # Update metrics + self.total_time += time.time() - start_time + self.total_mem = max(self.total_mem, peak) + + return result + return wrapper + +performance = PerformanceDecorator() From 8460cd6c2d481d33f7c73d3c40c0982cf27f4433 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:32:27 +0300 Subject: [PATCH 32/36] Update decorators_vladyslav.senkiv.py --- Week04/decorators_vladyslav.senkiv.py | 61 +++++++++++++-------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/Week04/decorators_vladyslav.senkiv.py b/Week04/decorators_vladyslav.senkiv.py index 6d008187..16dcf060 100644 --- a/Week04/decorators_vladyslav.senkiv.py +++ b/Week04/decorators_vladyslav.senkiv.py @@ -1,32 +1,31 @@ -import functools import time -import tracemalloc - -class PerformanceDecorator: - def __init__(self): - self.counter = 0 - self.total_time = 0 - self.total_mem = 0 - - def __call__(self, func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - self.counter += 1 - - # Track time - start_time = time.time() - - # Track memory - tracemalloc.start() - result = func(*args, **kwargs) - current, peak = tracemalloc.get_traced_memory() - tracemalloc.stop() - - # Update metrics - self.total_time += time.time() - start_time - self.total_mem = max(self.total_mem, peak) - - return result - return wrapper - -performance = PerformanceDecorator() +import sys +from functools import wraps + + +def performance(func): + @wraps(func) + def wrapper(*args, **kwargs): + start_time = time.perf_counter() + + result = func(*args, **kwargs) + + end_time = time.perf_counter() + + performance.counter += 1 + performance.total_time += end_time - start_time + performance.total_mem += sys.getsizeof(result) + + if isinstance(result, list): + performance.total_mem += sys.getsizeof(result) + for item in result: + performance.total_mem += sys.getsizeof(item) + + return result + + return wrapper + + +performance.counter = 0 +performance.total_time = 0 +performance.total_mem = 0 From 9b9cca50c3c51bc3627c9700ca7d09f06445333d Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:35:15 +0300 Subject: [PATCH 33/36] Fix memory calculation for list results in decorator --- Week04/decorators_vladyslav.senkiv.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Week04/decorators_vladyslav.senkiv.py b/Week04/decorators_vladyslav.senkiv.py index 16dcf060..ef16153c 100644 --- a/Week04/decorators_vladyslav.senkiv.py +++ b/Week04/decorators_vladyslav.senkiv.py @@ -18,6 +18,7 @@ def wrapper(*args, **kwargs): if isinstance(result, list): performance.total_mem += sys.getsizeof(result) + for item in result: performance.total_mem += sys.getsizeof(item) From e87c3f7ec6eeeef5233c1d6931ffc6ac6a7df688 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Wed, 3 Jun 2026 15:37:43 +0300 Subject: [PATCH 34/36] x --- ...orators_vladyslav.senkiv.py => decorators_vladyslav_senkiv.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Week04/{decorators_vladyslav.senkiv.py => decorators_vladyslav_senkiv.py} (100%) diff --git a/Week04/decorators_vladyslav.senkiv.py b/Week04/decorators_vladyslav_senkiv.py similarity index 100% rename from Week04/decorators_vladyslav.senkiv.py rename to Week04/decorators_vladyslav_senkiv.py From c3618f5886aa9cb8858d3dc14294e78425a7c497 Mon Sep 17 00:00:00 2001 From: Senkiv Vladyslav Date: Thu, 4 Jun 2026 17:53:21 +0300 Subject: [PATCH 35/36] Delete dining_philosophers_vladyslav_senkiv.py --- dining_philosophers_vladyslav_senkiv.py | 72 ------------------------- 1 file changed, 72 deletions(-) delete mode 100644 dining_philosophers_vladyslav_senkiv.py diff --git a/dining_philosophers_vladyslav_senkiv.py b/dining_philosophers_vladyslav_senkiv.py deleted file mode 100644 index df8d871d..00000000 --- a/dining_philosophers_vladyslav_senkiv.py +++ /dev/null @@ -1,72 +0,0 @@ -import threading -import time -import random - - -class Fork: - def __init__(self, number): - self.number = number - self.lock = threading.Lock() - - -class Philosopher(threading.Thread): - def __init__(self, number, left_fork, right_fork, meals_count=3): - super().__init__() - self.number = number - self.left_fork = left_fork - self.right_fork = right_fork - self.meals_count = meals_count - - def think(self): - print(f"Philosopher {self.number} is thinking") - time.sleep(random.uniform(0.5, 1.5)) - - def eat(self): - print(f"Philosopher {self.number} is eating") - time.sleep(random.uniform(0.5, 1.5)) - - def run(self): - for _ in range(self.meals_count): - self.think() - - if self.number % 2 == 0: - first_fork = self.left_fork - second_fork = self.right_fork - else: - first_fork = self.right_fork - second_fork = self.left_fork - - with first_fork.lock: - print(f"Philosopher {self.number} took fork {first_fork.number}") - - with second_fork.lock: - print(f"Philosopher {self.number} took fork {second_fork.number}") - self.eat() - - print(f"Philosopher {self.number} released fork {second_fork.number}") - - print(f"Philosopher {self.number} released fork {first_fork.number}") - - -if __name__ == "__main__": - philosophers_count = 5 - forks = [Fork(i) for i in range(philosophers_count)] - - philosophers = [] - - for i in range(philosophers_count): - philosopher = Philosopher( - number=i, - left_fork=forks[i], - right_fork=forks[(i + 1) % philosophers_count], - meals_count=3 - ) - philosophers.append(philosopher) - - for philosopher in philosophers: - philosopher.start() - - for philosopher in philosophers: - philosopher.join() - - print("Dinner is finished") From 33cfd59bfafcace85c188398336c401902d3585e Mon Sep 17 00:00:00 2001 From: Bora Canbula Date: Thu, 4 Jun 2026 23:31:21 +0300 Subject: [PATCH 36/36] Delete Week09/dining_philosophers_vladyslav_senkiv.py --- .../dining_philosophers_vladyslav_senkiv.py | 72 ------------------- 1 file changed, 72 deletions(-) delete mode 100644 Week09/dining_philosophers_vladyslav_senkiv.py diff --git a/Week09/dining_philosophers_vladyslav_senkiv.py b/Week09/dining_philosophers_vladyslav_senkiv.py deleted file mode 100644 index df8d871d..00000000 --- a/Week09/dining_philosophers_vladyslav_senkiv.py +++ /dev/null @@ -1,72 +0,0 @@ -import threading -import time -import random - - -class Fork: - def __init__(self, number): - self.number = number - self.lock = threading.Lock() - - -class Philosopher(threading.Thread): - def __init__(self, number, left_fork, right_fork, meals_count=3): - super().__init__() - self.number = number - self.left_fork = left_fork - self.right_fork = right_fork - self.meals_count = meals_count - - def think(self): - print(f"Philosopher {self.number} is thinking") - time.sleep(random.uniform(0.5, 1.5)) - - def eat(self): - print(f"Philosopher {self.number} is eating") - time.sleep(random.uniform(0.5, 1.5)) - - def run(self): - for _ in range(self.meals_count): - self.think() - - if self.number % 2 == 0: - first_fork = self.left_fork - second_fork = self.right_fork - else: - first_fork = self.right_fork - second_fork = self.left_fork - - with first_fork.lock: - print(f"Philosopher {self.number} took fork {first_fork.number}") - - with second_fork.lock: - print(f"Philosopher {self.number} took fork {second_fork.number}") - self.eat() - - print(f"Philosopher {self.number} released fork {second_fork.number}") - - print(f"Philosopher {self.number} released fork {first_fork.number}") - - -if __name__ == "__main__": - philosophers_count = 5 - forks = [Fork(i) for i in range(philosophers_count)] - - philosophers = [] - - for i in range(philosophers_count): - philosopher = Philosopher( - number=i, - left_fork=forks[i], - right_fork=forks[(i + 1) % philosophers_count], - meals_count=3 - ) - philosophers.append(philosopher) - - for philosopher in philosophers: - philosopher.start() - - for philosopher in philosophers: - philosopher.join() - - print("Dinner is finished")