diff --git a/homeworks/sem01/hw1/aggregate_segmentation.py b/homeworks/sem01/hw1/aggregate_segmentation.py index 1cdc176a..a9ba1a69 100644 --- a/homeworks/sem01/hw1/aggregate_segmentation.py +++ b/homeworks/sem01/hw1/aggregate_segmentation.py @@ -1,3 +1,5 @@ +from uuid import UUID + ALLOWED_TYPES = { "spotter_word", "voice_human", @@ -5,6 +7,40 @@ } +def is_valid_uuid(uuid): + try: + UUID(uuid) + return True + except ValueError: + return False + + +def is_valid_segment(segment): + if "segment_id" not in segment: + return False + + if not is_valid_uuid(segment["segment_id"]): + return False + + if ( + segment["type"] is None + and segment["segment_start"] is None + and segment["segment_end"] is None + ): + pass + elif ( + not isinstance(segment["type"], str) + or not isinstance(segment["segment_start"], float) + or not isinstance(segment["segment_end"], float) + ): + return False + + if segment["type"] not in ALLOWED_TYPES and segment["type"] is not None: + return False + + return True + + def aggregate_segmentation( segmentation_data: list[dict[str, str | float | None]], ) -> tuple[dict[str, dict[str, dict[str, str | float]]], list[str]]: @@ -24,5 +60,40 @@ def aggregate_segmentation( Список `audio_id` (str), которые требуют переразметки. """ - # ваш код - return {}, [] + audio = {} + not_valid_audio_id = set() + + for i in segmentation_data: + audio_id = i["audio_id"] if "audio_id" in i else None + segment_id = i["segment_id"] + start = i["segment_start"] + end = i["segment_end"] + segment_type = i["type"] + + if is_valid_uuid(audio_id) and is_valid_segment(i): + if audio_id not in audio: + audio[audio_id] = {segment_id: {"end": end, "start": start, "type": segment_type}} + else: + if segment_id not in audio[audio_id]: + audio[audio_id][segment_id] = {"end": end, "start": start, "type": segment_type} + else: + segment = audio[audio_id][segment_id] + if ( + segment["end"] != end + or segment["start"] != start + or segment["type"] != segment_type + ): + not_valid_audio_id.add(audio_id) + + else: + not_valid_audio_id.add(audio_id) + + audio_without_empty_segments = {} + for a_id, segments in audio.items(): + new_segments = {} + for s_id, s in segments.items(): + if any(s.values()): + new_segments[s_id] = s + audio_without_empty_segments[a_id] = new_segments + + return audio_without_empty_segments, list(not_valid_audio_id) diff --git a/homeworks/sem01/hw1/backoff.py b/homeworks/sem01/hw1/backoff.py index 696ffa73..2a422417 100644 --- a/homeworks/sem01/hw1/backoff.py +++ b/homeworks/sem01/hw1/backoff.py @@ -1,3 +1,4 @@ +from functools import wraps from random import uniform from time import sleep from typing import ( @@ -34,5 +35,32 @@ def backoff( ValueError, если были переданы невозможные аргументы. """ - # ваш код - pass + if retry_amount < 1 or retry_amount > 100: + raise ValueError + if timeout_start <= 0 or timeout_start > 10: + raise ValueError + if timeout_max <= 0 or timeout_max > 10: + raise ValueError + if backoff_scale <= 0 or backoff_scale > 10: + raise ValueError + + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + nonlocal timeout_start + + last_error = None + for i in range(retry_amount): + try: + return func(*args, **kwargs) + except backoff_triggers as e: + sleep(timeout_start + uniform(0, 0.5)) + if timeout_start < timeout_max: + timeout_start *= backoff_scale + last_error = e + + raise last_error + + return wrapper + + return decorator diff --git a/homeworks/sem01/hw1/cache.py b/homeworks/sem01/hw1/cache.py index 9eb1d5d2..7d8dc65a 100644 --- a/homeworks/sem01/hw1/cache.py +++ b/homeworks/sem01/hw1/cache.py @@ -1,3 +1,4 @@ +from functools import wraps from typing import ( Callable, ParamSpec, @@ -23,5 +24,31 @@ def lru_cache(capacity: int) -> Callable[[Callable[P, R]], Callable[P, R]]: для получения целого числа. ValueError, если после округления capacity - число, меньшее 1. """ - # ваш код - pass + + try: + capacity = round(capacity) + except TypeError: + raise TypeError(f"{type(capacity).__name__} неверный тип для размера кэша") from None + if capacity < 1: + raise ValueError + + cache = {} + + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + func_args = args + tuple(sorted(kwargs.items())) + if func_args in cache: + cache[func_args] = cache.pop(func_args) + return cache[func_args] + + else: + if len(cache) == capacity: + cache.pop(next(iter(cache.keys()))) + res = func(*args, **kwargs) + cache[func_args] = res + return res + + return wrapper + + return decorator diff --git a/homeworks/sem01/hw1/convert_exception.py b/homeworks/sem01/hw1/convert_exception.py index fe5c770f..3a94c5cf 100644 --- a/homeworks/sem01/hw1/convert_exception.py +++ b/homeworks/sem01/hw1/convert_exception.py @@ -1,3 +1,4 @@ +from functools import wraps from typing import ( Callable, ParamSpec, @@ -24,5 +25,16 @@ def convert_exceptions_to_api_compitable_ones( Декоратор для непосредственного использования. """ - # ваш код - pass + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + try: + func(*args, **kwargs) + except Exception as e: + if type(e) in exception_to_api_exception: + raise exception_to_api_exception[type(e)] from None + raise e + + return wrapper + + return decorator diff --git a/solutions/sem01/lesson02/task1.py b/solutions/sem01/lesson02/task1.py index c782dcd8..478c0588 100644 --- a/solutions/sem01/lesson02/task1.py +++ b/solutions/sem01/lesson02/task1.py @@ -1,4 +1,5 @@ def get_factorial(num: int) -> int: factorial = 1 - # ваш код + for i in range(2, num + 1): + factorial *= i return factorial diff --git a/solutions/sem01/lesson02/task2.py b/solutions/sem01/lesson02/task2.py index b91420c5..63b4b9be 100644 --- a/solutions/sem01/lesson02/task2.py +++ b/solutions/sem01/lesson02/task2.py @@ -1,4 +1,6 @@ def get_doubled_factorial(num: int) -> int: factorial = 1 - # ваш код + while num > 1: + factorial *= num + num -= 2 return factorial diff --git a/solutions/sem01/lesson02/task3.py b/solutions/sem01/lesson02/task3.py index ee2a84ec..e6649c4c 100644 --- a/solutions/sem01/lesson02/task3.py +++ b/solutions/sem01/lesson02/task3.py @@ -1,4 +1,6 @@ def get_amount_of_ways_to_climb(stair_amount: int) -> int: step_prev, step_curr = 1, 1 - # ваш код + for i in range(1, stair_amount): + step_prev, step_curr = step_curr, step_prev + step_curr + return step_curr diff --git a/solutions/sem01/lesson02/task4.py b/solutions/sem01/lesson02/task4.py index 45ff4bb4..69e54d14 100644 --- a/solutions/sem01/lesson02/task4.py +++ b/solutions/sem01/lesson02/task4.py @@ -1,4 +1,11 @@ def get_multiplications_amount(num: int) -> int: multiplications_amount = 0 - # ваш код + while num != 1: + if num % 2 == 0: + multiplications_amount += 1 + num //= 2 + else: + multiplications_amount += 1 + num -= 1 + return multiplications_amount diff --git a/solutions/sem01/lesson02/task5.py b/solutions/sem01/lesson02/task5.py index 8fb9a048..2712bd70 100644 --- a/solutions/sem01/lesson02/task5.py +++ b/solutions/sem01/lesson02/task5.py @@ -1,3 +1,8 @@ def get_gcd(num1: int, num2: int) -> int: - # ваш код - return num1 + if num1 < num2: + num1, num2 = num2, num1 + d = num1 % num2 + while d != 0: + num1, num2 = num2, d + d = num1 % num2 + return num2 diff --git a/solutions/sem01/lesson02/task6.py b/solutions/sem01/lesson02/task6.py index bec4b6cd..0b18c12e 100644 --- a/solutions/sem01/lesson02/task6.py +++ b/solutions/sem01/lesson02/task6.py @@ -1,4 +1,17 @@ def get_sum_of_prime_divisors(num: int) -> int: sum_of_divisors = 0 - # ваш код + mult_of_divisors = 1 + while num != 1: + for i in range(2, int(num**0.5) + 1): + if num % i == 0: + num //= i + if mult_of_divisors % i != 0: + sum_of_divisors += i + mult_of_divisors *= i + break + else: + if mult_of_divisors % num != 0: + sum_of_divisors += num + break + return sum_of_divisors diff --git a/solutions/sem01/lesson02/task7.py b/solutions/sem01/lesson02/task7.py index 4b2d73be..b58f5872 100644 --- a/solutions/sem01/lesson02/task7.py +++ b/solutions/sem01/lesson02/task7.py @@ -1,5 +1,20 @@ def is_palindrome(num: int) -> bool: + if num < 0: + return False + num_reversed = 0 num_origin = num - # ваш код + + smax = 0 + for i in range(1, 10): + if num // 10**i > 0: + smax += 1 + + s = smax + while s != -1: + n_s = num // 10**s + num -= n_s * 10**s + num_reversed += n_s * 10 ** (smax - s) + s -= 1 + return num_origin == num_reversed diff --git a/solutions/sem01/lesson03/task1.py b/solutions/sem01/lesson03/task1.py index f1d8fe26..3f09fdab 100644 --- a/solutions/sem01/lesson03/task1.py +++ b/solutions/sem01/lesson03/task1.py @@ -1,3 +1,29 @@ def flip_bits_in_range(num: int, left_bit: int, right_bit: int) -> int: - # ваш код - return num \ No newline at end of file + n = num + s = 0 + while n: + s += 1 + n //= 2 + + t = s + new_num = 0 + + for i in range(left_bit - 1): + r = 0 if num % 2 == 0 else 1 + new_num += r * 2 ** (s - t) + num //= 2 + t -= 1 + + for j in range(right_bit - left_bit + 1): + r = 1 if num % 2 == 0 else 0 + new_num += r * 2 ** (s - t) + num //= 2 + t -= 1 + + for k in range(t): + r = 0 if num % 2 == 0 else 1 + new_num += r * 2 ** (s - t) + num //= 2 + t -= 1 + + return new_num diff --git a/solutions/sem01/lesson03/task2.py b/solutions/sem01/lesson03/task2.py index a3a738c2..61acffc2 100644 --- a/solutions/sem01/lesson03/task2.py +++ b/solutions/sem01/lesson03/task2.py @@ -1,3 +1,20 @@ def get_cube_root(n: float, eps: float) -> float: - # ваш код - return n \ No newline at end of file + if n == 0: + return 0 + + abs_n = abs(n) + + low = 0 + high = abs_n if abs_n >= 1 else 1 + mid = (low + high) / 2 + mid3 = mid * mid * mid + while abs(mid3 - abs_n) > eps: + if mid3 > abs_n: + high = mid + else: + low = mid + + mid = (low + high) / 2 + mid3 = mid * mid * mid + + return mid * abs_n / n diff --git a/solutions/sem01/lesson03/task3.py b/solutions/sem01/lesson03/task3.py index 5e91a6ac..22f94142 100644 --- a/solutions/sem01/lesson03/task3.py +++ b/solutions/sem01/lesson03/task3.py @@ -1,3 +1,20 @@ def get_nth_digit(num: int) -> int: - # ваш код - return 0 + if num <= 5: + return 2 * (num - 1) + + q = 5 + r = 1 + w = 0 + while q < num: + w = q + q += 45 * 10 ** (r - 1) * (r + 1) + r += 1 + d = num - w + count = (d + r - 1) // r + res = 10 ** (r - 1) + 2 * (count - 1) + last_num = count * r + while last_num - d: + res //= 10 + last_num -= 1 + + return res % 10 diff --git a/solutions/sem01/lesson04/task1.py b/solutions/sem01/lesson04/task1.py index 47384423..78b5c42b 100644 --- a/solutions/sem01/lesson04/task1.py +++ b/solutions/sem01/lesson04/task1.py @@ -1,3 +1,6 @@ -def is_arithmetic_progression(lst: list[list[int]]) -> bool: - # ваш код - return False \ No newline at end of file +def is_arithmetic_progression(lst: list[int]) -> bool: + lst.sort() + for i in range(len(lst) - 2): + if lst[i] - lst[i + 1] != lst[i + 1] - lst[i + 2]: + return False + return True diff --git a/solutions/sem01/lesson04/task2.py b/solutions/sem01/lesson04/task2.py index 4591d0a3..aaaab8c0 100644 --- a/solutions/sem01/lesson04/task2.py +++ b/solutions/sem01/lesson04/task2.py @@ -1,3 +1,15 @@ def merge_intervals(intervals: list[list[int, int]]) -> list[list[int, int]]: - # ваш код - return [[0,0]] \ No newline at end of file + if not intervals: + return [] + + intervals.sort() + new_intervals = [intervals[0]] + for i in range(1, len(intervals)): + x1, y1 = new_intervals[-1] + x2, y2 = intervals[i] + if x2 <= y1: + new_intervals[-1] = [x1, max(y2, y1)] + else: + new_intervals.append(intervals[i]) + + return new_intervals diff --git a/solutions/sem01/lesson04/task3.py b/solutions/sem01/lesson04/task3.py index 7253f6cb..9db4c15b 100644 --- a/solutions/sem01/lesson04/task3.py +++ b/solutions/sem01/lesson04/task3.py @@ -1,3 +1,5 @@ def find_single_number(nums: list[int]) -> int: - # ваш код - return 0 + n = 0 + for i in nums: + n ^= i + return n diff --git a/solutions/sem01/lesson04/task4.py b/solutions/sem01/lesson04/task4.py index b21bc5a3..b97b52f4 100644 --- a/solutions/sem01/lesson04/task4.py +++ b/solutions/sem01/lesson04/task4.py @@ -1,3 +1,15 @@ -def move_zeros_to_end(nums: list[int]) -> list[int]: - # ваш код - return 0 \ No newline at end of file +def move_zeros_to_end(nums: list[int]) -> int: + if not nums.count(0): + return len(nums) + + n = len(nums) - nums.count(0) + i = 0 + while i != n: + elem = nums[i] + if elem == 0: + del nums[i] + nums.append(0) + else: + i += 1 + + return nums.index(0) diff --git a/solutions/sem01/lesson04/task5.py b/solutions/sem01/lesson04/task5.py index 02d7742b..a20636de 100644 --- a/solutions/sem01/lesson04/task5.py +++ b/solutions/sem01/lesson04/task5.py @@ -1,3 +1,12 @@ def find_row_with_most_ones(matrix: list[list[int]]) -> int: - # ваш код - return 0 \ No newline at end of file + if not matrix: + return 0 + + m = len(matrix[0]) + best_index = 0 + for i in range(len(matrix)): + while m > 0 and matrix[i][m - 1]: + m -= 1 + best_index = i + + return best_index diff --git a/solutions/sem01/lesson04/task6.py b/solutions/sem01/lesson04/task6.py index 16df27ca..1ac6656b 100644 --- a/solutions/sem01/lesson04/task6.py +++ b/solutions/sem01/lesson04/task6.py @@ -1,3 +1,13 @@ -def count_cycles(arr: list[int]) -> int: - # ваш код - return 0 \ No newline at end of file +def count_cycles(arr: list[int]) -> int: + used_indexes = [] + cycles_count = 0 + for i in range(len(arr)): + new_index = arr[i] + f = new_index in used_indexes + while new_index not in used_indexes: + used_indexes.append(new_index) + new_index = arr[new_index] + if not f: + cycles_count += 1 + + return cycles_count diff --git a/solutions/sem01/lesson05/task1.py b/solutions/sem01/lesson05/task1.py index 9a17211e..8d94d0ac 100644 --- a/solutions/sem01/lesson05/task1.py +++ b/solutions/sem01/lesson05/task1.py @@ -1,3 +1,3 @@ def is_palindrome(text: str) -> bool: - # ваш код - return False \ No newline at end of file + text = text.lower() + return text == text[::-1] diff --git a/solutions/sem01/lesson05/task2.py b/solutions/sem01/lesson05/task2.py index 36750380..850722e4 100644 --- a/solutions/sem01/lesson05/task2.py +++ b/solutions/sem01/lesson05/task2.py @@ -1,3 +1,29 @@ def are_anagrams(word1: str, word2: str) -> bool: - # ваш код - return False \ No newline at end of file + low_letters = [0] * 26 + upper_letters = [0] * 26 + a_index = ord("a") + A_index = ord("A") + + for i in word1: + index = ord(i) + if index >= 97: + low_letters[index - a_index] += 1 + elif index >= 65: + upper_letters[index - A_index] += 1 + + for j in word2: + index = ord(j) + if index >= 97: + low_letters[index - a_index] -= 1 + elif index >= 65: + upper_letters[index - A_index] -= 1 + + # return not any(low_letters) and not any(upper_letters) + for k in low_letters: + if k: + return False + for p in upper_letters: + if p: + return False + + return True diff --git a/solutions/sem01/lesson05/task3.py b/solutions/sem01/lesson05/task3.py index e368e2f4..41331860 100644 --- a/solutions/sem01/lesson05/task3.py +++ b/solutions/sem01/lesson05/task3.py @@ -1,3 +1,7 @@ def is_punctuation(text: str) -> bool: - # ваш код - return False + if not text: + return False + for i in text: + if i not in r'!"#$%&\'()*+,-./:;<=>?@[]^_{|}~`': + return False + return True diff --git a/solutions/sem01/lesson05/task4.py b/solutions/sem01/lesson05/task4.py index 4c4e9086..0f6cce30 100644 --- a/solutions/sem01/lesson05/task4.py +++ b/solutions/sem01/lesson05/task4.py @@ -1,3 +1,9 @@ def unzip(compress_text: str) -> str: - # ваш код - return compress_text \ No newline at end of file + result = "" + for i in compress_text.split(): + if "*" in i: + s, count = i.split("*") + result += s * int(count) + else: + result += i + return result diff --git a/solutions/sem01/lesson05/task5.py b/solutions/sem01/lesson05/task5.py index 076c5bb6..1a128a4e 100644 --- a/solutions/sem01/lesson05/task5.py +++ b/solutions/sem01/lesson05/task5.py @@ -1,3 +1,37 @@ -def reg_validator(reg_expr: str, text: str) -> bool: - # ваш код - return False \ No newline at end of file +def reg_validator(reg_expr: str, text: str) -> bool: + index = 0 + text_len = len(text) + + for char in reg_expr: + if index == text_len: + return False + + if char == "d": + num_len = 0 + while index < text_len and text[index].isdigit(): + index += 1 + num_len += 1 + if not num_len: + return False + + elif char == "w": + word_len = 0 + while index < text_len and text[index].isalpha(): + index += 1 + word_len += 1 + if not word_len: + return False + + elif char == "s": + string_len = 0 + while index < text_len and text[index].isalnum(): + index += 1 + string_len += 1 + if not string_len: + return False + + else: + if char != text[index]: + return False + index += 1 + return index == text_len diff --git a/solutions/sem01/lesson05/task6.py b/solutions/sem01/lesson05/task6.py index 1b914ada..1a334083 100644 --- a/solutions/sem01/lesson05/task6.py +++ b/solutions/sem01/lesson05/task6.py @@ -1,3 +1,14 @@ def simplify_path(path: str) -> str: - # ваш код - return path \ No newline at end of file + catalogs = [] + for i in path.replace("//", "/").split("/"): + if i == ".." and not catalogs: + return "" + if i == "..": + del catalogs[-1] + continue + if i == ".": + continue + if i: + catalogs.append(i) + + return "/" + "/".join(catalogs) diff --git a/solutions/sem01/lesson06/task1.py b/solutions/sem01/lesson06/task1.py index 2d1e30e9..2d03a401 100644 --- a/solutions/sem01/lesson06/task1.py +++ b/solutions/sem01/lesson06/task1.py @@ -1,3 +1,31 @@ def int_to_roman(num: int) -> str: - # ваш код - return "" \ No newline at end of file + symbols = { + 1: "I", + 4: "IV", + 5: "V", + 9: "IX", + 10: "X", + 40: "XL", + 50: "L", + 90: "XC", + 100: "C", + 400: "CD", + 500: "D", + 900: "CM", + 1000: "M", + } + + res = "" + counter = 0 + while num: + n = (num % 10) * 10**counter + if n in symbols: + res = symbols[n] + res + elif n > 5 * 10**counter: + res = symbols[5 * 10**counter] + symbols[10**counter] * (n // 10**counter - 5) + res + else: + res = symbols[10**counter] * (n // 10**counter) + res + num //= 10 + counter += 1 + + return res diff --git a/solutions/sem01/lesson06/task2.py b/solutions/sem01/lesson06/task2.py index f535b5a0..74a8dc79 100644 --- a/solutions/sem01/lesson06/task2.py +++ b/solutions/sem01/lesson06/task2.py @@ -1,3 +1,23 @@ def get_len_of_longest_substring(text: str) -> int: - # ваш код - return 0 \ No newline at end of file + text_len = len(text) + max_len = 0 + symbols_count = len(set(text)) + + for i in range(text_len): + f = False + + for j in range(i + max_len, text_len): + substring_len = j + 1 - i + + if len(set(text[i : j + 1])) == substring_len: + max_len = substring_len + if max_len == symbols_count: + f = True + break + else: + break + + if f: + break + + return max_len diff --git a/solutions/sem01/lesson06/task3.py b/solutions/sem01/lesson06/task3.py index 7449a1e7..ae08a11c 100644 --- a/solutions/sem01/lesson06/task3.py +++ b/solutions/sem01/lesson06/task3.py @@ -1,7 +1,10 @@ -def is_there_any_good_subarray( - nums: list[int], - k: int, -) -> bool: - - # ваш код +def is_there_any_good_subarray(nums: list[int], k: int) -> bool: + nums_len = len(nums) + for i in range(nums_len - 1): + s = nums[i] + for j in range(i + 1, nums_len): + s += nums[j] + if s % k == 0: + return True + return False diff --git a/solutions/sem01/lesson06/task4.py b/solutions/sem01/lesson06/task4.py index 5b75a110..95aaccbc 100644 --- a/solutions/sem01/lesson06/task4.py +++ b/solutions/sem01/lesson06/task4.py @@ -1,3 +1,6 @@ def count_unique_words(text: str) -> int: - # ваш код - return 0 \ No newline at end of file + for i in text: + if not i.isalnum() and i != " ": + text = text.replace(i, "") + + return len(set(text.lower().split())) diff --git a/solutions/sem01/lesson08/task1.py b/solutions/sem01/lesson08/task1.py index 4390f6c8..a6e93196 100644 --- a/solutions/sem01/lesson08/task1.py +++ b/solutions/sem01/lesson08/task1.py @@ -1,5 +1,13 @@ from typing import Callable + def make_averager(accumulation_period: int) -> Callable[[float], float]: - # ваш код - pass \ No newline at end of file + daily_profits = [] + + def get_avg(profit: float) -> float: + daily_profits.append(profit) + if len(daily_profits) < accumulation_period: + return sum(daily_profits) / len(daily_profits) + return sum(daily_profits[-accumulation_period:]) / accumulation_period + + return get_avg diff --git a/solutions/sem01/lesson08/task2.py b/solutions/sem01/lesson08/task2.py index 6e4af870..088fbacd 100644 --- a/solutions/sem01/lesson08/task2.py +++ b/solutions/sem01/lesson08/task2.py @@ -1,10 +1,28 @@ +import time +from functools import wraps from typing import Callable, TypeVar T = TypeVar("T") -def collect_statistic( - statistics: dict[str, list[float, int]] -) -> Callable[[T], T]: - - # ваш код - pass \ No newline at end of file + +def collect_statistic(statistics: dict[str, list[float, int]]) -> Callable[[T], T]: + def _collect_statistic(func) -> T: + @wraps(func) + def wrapper(*args, **kwargs): + func_name = func.__name__ + start_time = time.time() + res = func(*args, **kwargs) + delta_time = time.time() - start_time + if func_name not in statistics: + statistics[func_name] = [delta_time, 1] + else: + time_avg, counter = statistics[func_name] + statistics[func_name] = [ + (time_avg * counter + delta_time) / (counter + 1), + counter + 1, + ] + return res + + return wrapper + + return _collect_statistic diff --git a/solutions/sem01/lesson11/task1.py b/solutions/sem01/lesson11/task1.py index 6a15f31f..d71326c4 100644 --- a/solutions/sem01/lesson11/task1.py +++ b/solutions/sem01/lesson11/task1.py @@ -1,10 +1,107 @@ +from math import acos + + class Vector2D: + _abscissa = 0.0 + _ordinate = 0.0 + + def __init__(self, abscissa=0.0, ordinate=0.0): + self._abscissa = round(abscissa, 12) + self._ordinate = round(ordinate, 12) + + @property + def abscissa(self): + return self._abscissa + + @property + def ordinate(self): + return self._ordinate + + def __repr__(self): + return f"Vector2D(abscissa={self._abscissa}, ordinate={self._ordinate})" + + def __eq__(self, other): + if not isinstance(other, Vector2D): + return False + + return self._ordinate == other.ordinate and self._abscissa == other.abscissa + + def __ne__(self, other): + return not (self == other) + + def __gt__(self, other): + if not isinstance(other, Vector2D): + raise TypeError() + + return self._abscissa > other.abscissa or ( + self._abscissa == other.abscissa and self._ordinate > other.ordinate + ) + + def __lt__(self, other): + return not (self > other) and not (self == other) + + def __ge__(self, other): + return not (self < other) + + def __le__(self, other): + return not (self > other) + + def __abs__(self): + return (self._abscissa**2 + self._ordinate**2) ** 0.5 + + def __bool__(self): + return abs(self) != 0 + + def __mul__(self, num): + return Vector2D(self._abscissa * num, self._ordinate * num) + + def __rmul__(self, num): + return self * num + + def __truediv__(self, num): + return self * (1 / num) + + def __add__(self, other): + if isinstance(other, (float, int)): + return Vector2D(self._abscissa + other, self._ordinate + other) + if isinstance(other, Vector2D): + return Vector2D(self._abscissa + other.abscissa, self._ordinate + other.ordinate) + + raise TypeError() + + def __radd__(self, other): + return self + other + + def __sub__(self, other): + return self + -other + + def __neg__(self): + return Vector2D(-self._abscissa, -self._ordinate) + + def __int__(self): + return int(abs(self)) + + def __float__(self): + return abs(self) + + def __complex__(self): + return complex(self._abscissa, self._ordinate) + + def __matmul__(self, other): + if not isinstance(other, Vector2D): + raise TypeError() + + return self._abscissa * other.abscissa + self._ordinate * other.ordinate + def conj(self) -> "Vector2D": - # ваш код - return Vector2D() + return Vector2D(self._abscissa, -self._ordinate) def get_angle(self, other: "Vector2D") -> float: - # ваш код - return 0 + if not isinstance(other, Vector2D): + raise TypeError() - # ваш код + if (not self._abscissa and not self._ordinate) or ( + not other.abscissa and not other.ordinate + ): + raise ValueError("Нельзя рассчитать угол с нулевым вектором") + return acos((self @ other) / (abs(self) * abs(other))) diff --git a/solutions/sem01/lesson12/task1.py b/solutions/sem01/lesson12/task1.py index d1bb828c..f413bd85 100644 --- a/solutions/sem01/lesson12/task1.py +++ b/solutions/sem01/lesson12/task1.py @@ -2,5 +2,14 @@ def chunked(iterable: Iterable, size: int) -> Generator[tuple[Any], None, None]: - # ваш код - ... + arr = [] + arr_size = 0 + for i in iterable: + arr.append(i) + arr_size += 1 + if arr_size == size: + yield tuple(arr) + arr = [] + arr_size = 0 + if arr: + yield tuple(arr) diff --git a/solutions/sem01/lesson12/task2.py b/solutions/sem01/lesson12/task2.py index 3ad802ee..ef6bf1ac 100644 --- a/solutions/sem01/lesson12/task2.py +++ b/solutions/sem01/lesson12/task2.py @@ -2,5 +2,14 @@ def circle(iterable: Iterable) -> Generator[Any, None, None]: - # ваш код - ... + elems = [] + for i in iterable: + yield i + elems.append(i) + + if not elems: + return + + while True: + for i in elems: + yield i diff --git a/solutions/sem01/lesson12/task3.py b/solutions/sem01/lesson12/task3.py index 64c112cc..a11b8493 100644 --- a/solutions/sem01/lesson12/task3.py +++ b/solutions/sem01/lesson12/task3.py @@ -2,11 +2,26 @@ class FileOut: - def __init__( - self, - path_to_file: str, - ) -> None: - # ваш код - ... - - # ваш код + file = None + path_to_file = None + original_stdout = None + + def __init__(self, path_to_file: str) -> None: + self.path_to_file = path_to_file + + def __enter__(self): + self.file = open(self.path_to_file, "w") + self.original_stdout = sys.stdout + sys.stdout = self.file + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.original_stdout is not None: + sys.stdout = self.original_stdout + self.original_stdout = None + + if self.file: + self.file.close() + self.file = None + + return False diff --git a/solutions/sem02/lesson07/task1.py b/solutions/sem02/lesson07/task1.py index 3a505d89..05d2e88e 100644 --- a/solutions/sem02/lesson07/task1.py +++ b/solutions/sem02/lesson07/task1.py @@ -13,8 +13,55 @@ def visualize_diagrams( ordinates: np.ndarray, diagram_type: Any, ) -> None: - # ваш код - pass + if abscissa.shape[0] != ordinates.shape[0] or diagram_type not in ["hist", "box", "violin"]: + raise ShapeMismatchError + fig = plt.figure(figsize=(8, 8)) + grid = plt.GridSpec(4, 4, wspace=0.2, hspace=0.2) + scat_graph = fig.add_subplot(grid[0:-1, 1:]) + graph1 = fig.add_subplot(grid[0:-1, 0], sharey=scat_graph) + graph2 = fig.add_subplot(grid[-1, 1:], sharex=scat_graph) + scat_graph.scatter(abscissa, ordinates, color="#00FF00", alpha=0.3) + + if diagram_type == "box": + graph1.boxplot( + ordinates, + boxprops={"color": "#00FF00"}, + ) + graph2.boxplot( + abscissa, + vert=False, + boxprops={"color": "#00FF00"}, + ) + + if diagram_type == "violin": + viol_vertical = graph1.violinplot( + ordinates, + showmedians=True, + ) + for body in viol_vertical["bodies"]: + body.set_facecolor("#00FF00") + body.set_edgecolor("black") + for parts in viol_vertical: + if parts == "bodies": + continue + viol_vertical[parts].set_edgecolor("black") + + viol_horizontal = graph2.violinplot(abscissa, vert=False, showmedians=True) + for body in viol_horizontal["bodies"]: + body.set_facecolor("#00FF00") + body.set_edgecolor("black") + for parts in viol_horizontal: + if parts == "bodies": + continue + viol_horizontal[parts].set_edgecolor("black") + + if diagram_type == "hist": + graph1.hist( + ordinates, orientation="horizontal", bins=50, color="#00FF00", alpha=0.3, edgecolor="black" + ) + graph2.hist(abscissa, bins=50, color="#00FF00", alpha=0.3, edgecolor="black") + graph1.invert_xaxis() + graph2.invert_yaxis() if __name__ == "__main__": diff --git a/solutions/sem02/lesson07/task2.py b/solutions/sem02/lesson07/task2.py index decd607e..2cba87fb 100644 --- a/solutions/sem02/lesson07/task2.py +++ b/solutions/sem02/lesson07/task2.py @@ -1 +1,49 @@ -# ваш код (используйте функции или классы для решения данной задачи) +import json + +import matplotlib.pyplot as plt +import numpy as np + + +def mitrial_disiase_analyse(path_to_json): + with open(path_to_json, "r", encoding="utf-8") as f: + data_dict = json.load(f) + + before_data = np.array(data_dict["before"]) + after_data = np.array(data_dict["after"]) + + _, counts_before = np.unique(before_data, return_counts=True) + _, counts_after = np.unique(after_data, return_counts=True) + + fig, axis = plt.subplots(figsize=(9, 9)) + axis: plt.Axes + labels = np.array(["I", "II", "III", "IV"]) + + x = np.arange(labels.size) + width = 0.35 + + axis.set_title("анализ заболевания", fontsize=17,) + axis.set_ylabel("кол-во людей", fontsize=12) + + axis.bar( + x - width / 2, + counts_before, + width=width, + color="red", + edgecolor="red", + label="before", + ) + axis.bar( + x + width / 2, + counts_after, + width=width, + color="blue", + edgecolor="blue", + label="after", + ) + + axis.set_xticks(x, labels=labels, weight="bold") + axis.tick_params(axis="x", labelsize=14, labelcolor="dimgray") + axis.legend() + + plt.savefig("mitral_disease_analysis.png") +