diff --git a/deprecated_tests/sem02/tests/task3/test_lesson03_tasks.py b/deprecated_tests/sem02/tests/task3/test_lesson03_tasks.py index 40f1cc711..aa65899c3 100644 --- a/deprecated_tests/sem02/tests/task3/test_lesson03_tasks.py +++ b/deprecated_tests/sem02/tests/task3/test_lesson03_tasks.py @@ -111,7 +111,7 @@ def test_get_mutual_l2_distances(self, lhs: list, rhs: list): ) def test_get_mutual_l2_distances_validate(self, lhs: list, rhs: list): with pytest.raises(Task1ShapeMismatchError): - sum_arrays_vectorized(np.array(lhs), np.array(rhs)) + get_mutual_l2_distances_vectorized(np.array(lhs), np.array(rhs)) class TestTask2: diff --git a/homeworks/sem01/hw1/backoff.py b/homeworks/sem01/hw1/backoff.py index 696ffa73a..a3373a982 100644 --- a/homeworks/sem01/hw1/backoff.py +++ b/homeworks/sem01/hw1/backoff.py @@ -1,5 +1,3 @@ -from random import uniform -from time import sleep from typing import ( Callable, ParamSpec, diff --git a/modulated_signal.gif b/modulated_signal.gif new file mode 100644 index 000000000..6aa467206 Binary files /dev/null and b/modulated_signal.gif differ diff --git a/requirements-ci.txt b/requirements-ci.txt index 581b008d7..9a10157f4 100644 --- a/requirements-ci.txt +++ b/requirements-ci.txt @@ -5,3 +5,5 @@ pandas==2.2.2 pytest==8.4.2 pytest-cov==7.0.0 ruff==0.13.0 + +pillow==11.1.0 \ No newline at end of file diff --git a/solutions/sem01/lesson02/task3.py b/solutions/sem01/lesson02/task3.py index ee2a84ecf..980f37930 100644 --- a/solutions/sem01/lesson02/task3.py +++ b/solutions/sem01/lesson02/task3.py @@ -1,4 +1,4 @@ def get_amount_of_ways_to_climb(stair_amount: int) -> int: - step_prev, step_curr = 1, 1 + step_curr = 1 # ваш код return step_curr diff --git a/solutions/sem01/lesson03/task1.py b/solutions/sem01/lesson03/task1.py index f1d8fe26b..7b048e654 100644 --- a/solutions/sem01/lesson03/task1.py +++ b/solutions/sem01/lesson03/task1.py @@ -1,3 +1,3 @@ def flip_bits_in_range(num: int, left_bit: int, right_bit: int) -> int: # ваш код - return num \ No newline at end of file + return num diff --git a/solutions/sem01/lesson03/task2.py b/solutions/sem01/lesson03/task2.py index a3a738c2a..5cf2b6316 100644 --- a/solutions/sem01/lesson03/task2.py +++ b/solutions/sem01/lesson03/task2.py @@ -1,3 +1,3 @@ def get_cube_root(n: float, eps: float) -> float: # ваш код - return n \ No newline at end of file + return n diff --git a/solutions/sem01/lesson04/task1.py b/solutions/sem01/lesson04/task1.py index 47384423a..0135e399b 100644 --- a/solutions/sem01/lesson04/task1.py +++ b/solutions/sem01/lesson04/task1.py @@ -1,3 +1,3 @@ def is_arithmetic_progression(lst: list[list[int]]) -> bool: # ваш код - return False \ No newline at end of file + return False diff --git a/solutions/sem01/lesson04/task2.py b/solutions/sem01/lesson04/task2.py index 4591d0a3e..5d6f8ee8a 100644 --- a/solutions/sem01/lesson04/task2.py +++ b/solutions/sem01/lesson04/task2.py @@ -1,3 +1,3 @@ def merge_intervals(intervals: list[list[int, int]]) -> list[list[int, int]]: # ваш код - return [[0,0]] \ No newline at end of file + return [[0, 0]] diff --git a/solutions/sem01/lesson04/task4.py b/solutions/sem01/lesson04/task4.py index b21bc5a39..2664384d8 100644 --- a/solutions/sem01/lesson04/task4.py +++ b/solutions/sem01/lesson04/task4.py @@ -1,3 +1,3 @@ def move_zeros_to_end(nums: list[int]) -> list[int]: # ваш код - return 0 \ No newline at end of file + return 0 diff --git a/solutions/sem01/lesson04/task5.py b/solutions/sem01/lesson04/task5.py index 02d7742bb..ec6932ee4 100644 --- a/solutions/sem01/lesson04/task5.py +++ b/solutions/sem01/lesson04/task5.py @@ -1,3 +1,3 @@ def find_row_with_most_ones(matrix: list[list[int]]) -> int: # ваш код - return 0 \ No newline at end of file + return 0 diff --git a/solutions/sem01/lesson04/task6.py b/solutions/sem01/lesson04/task6.py index 16df27ca6..d16e77dda 100644 --- a/solutions/sem01/lesson04/task6.py +++ b/solutions/sem01/lesson04/task6.py @@ -1,3 +1,3 @@ -def count_cycles(arr: list[int]) -> int: +def count_cycles(arr: list[int]) -> int: # ваш код - return 0 \ No newline at end of file + return 0 diff --git a/solutions/sem01/lesson05/task1.py b/solutions/sem01/lesson05/task1.py index 9a17211e5..fdf3b5488 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 + return False diff --git a/solutions/sem01/lesson05/task2.py b/solutions/sem01/lesson05/task2.py index 367503802..c70b40298 100644 --- a/solutions/sem01/lesson05/task2.py +++ b/solutions/sem01/lesson05/task2.py @@ -1,3 +1,3 @@ def are_anagrams(word1: str, word2: str) -> bool: # ваш код - return False \ No newline at end of file + return False diff --git a/solutions/sem01/lesson05/task4.py b/solutions/sem01/lesson05/task4.py index 4c4e9086e..7c2c26f17 100644 --- a/solutions/sem01/lesson05/task4.py +++ b/solutions/sem01/lesson05/task4.py @@ -1,3 +1,3 @@ def unzip(compress_text: str) -> str: # ваш код - return compress_text \ No newline at end of file + return compress_text diff --git a/solutions/sem01/lesson05/task5.py b/solutions/sem01/lesson05/task5.py index 076c5bb6c..da9e6d08c 100644 --- a/solutions/sem01/lesson05/task5.py +++ b/solutions/sem01/lesson05/task5.py @@ -1,3 +1,3 @@ -def reg_validator(reg_expr: str, text: str) -> bool: +def reg_validator(reg_expr: str, text: str) -> bool: # ваш код - return False \ No newline at end of file + return False diff --git a/solutions/sem01/lesson05/task6.py b/solutions/sem01/lesson05/task6.py index 1b914ada7..63207797d 100644 --- a/solutions/sem01/lesson05/task6.py +++ b/solutions/sem01/lesson05/task6.py @@ -1,3 +1,3 @@ def simplify_path(path: str) -> str: # ваш код - return path \ No newline at end of file + return path diff --git a/solutions/sem01/lesson06/task1.py b/solutions/sem01/lesson06/task1.py index 2d1e30e96..353cb3616 100644 --- a/solutions/sem01/lesson06/task1.py +++ b/solutions/sem01/lesson06/task1.py @@ -1,3 +1,3 @@ def int_to_roman(num: int) -> str: # ваш код - return "" \ No newline at end of file + return "" diff --git a/solutions/sem01/lesson06/task2.py b/solutions/sem01/lesson06/task2.py index f535b5a0c..f1034e24e 100644 --- a/solutions/sem01/lesson06/task2.py +++ b/solutions/sem01/lesson06/task2.py @@ -1,3 +1,3 @@ def get_len_of_longest_substring(text: str) -> int: # ваш код - return 0 \ No newline at end of file + return 0 diff --git a/solutions/sem01/lesson06/task3.py b/solutions/sem01/lesson06/task3.py index 7449a1e72..b160d615a 100644 --- a/solutions/sem01/lesson06/task3.py +++ b/solutions/sem01/lesson06/task3.py @@ -2,6 +2,5 @@ def is_there_any_good_subarray( nums: list[int], k: int, ) -> bool: - # ваш код return False diff --git a/solutions/sem01/lesson06/task4.py b/solutions/sem01/lesson06/task4.py index 5b75a110c..95a7098e4 100644 --- a/solutions/sem01/lesson06/task4.py +++ b/solutions/sem01/lesson06/task4.py @@ -1,3 +1,3 @@ def count_unique_words(text: str) -> int: # ваш код - return 0 \ No newline at end of file + return 0 diff --git a/solutions/sem01/lesson08/task1.py b/solutions/sem01/lesson08/task1.py index 4390f6c84..7fa724ef8 100644 --- a/solutions/sem01/lesson08/task1.py +++ b/solutions/sem01/lesson08/task1.py @@ -1,5 +1,6 @@ from typing import Callable + def make_averager(accumulation_period: int) -> Callable[[float], float]: # ваш код - pass \ No newline at end of file + pass diff --git a/solutions/sem01/lesson08/task2.py b/solutions/sem01/lesson08/task2.py index 6e4af8707..cc2ae4303 100644 --- a/solutions/sem01/lesson08/task2.py +++ b/solutions/sem01/lesson08/task2.py @@ -2,9 +2,7 @@ T = TypeVar("T") -def collect_statistic( - statistics: dict[str, list[float, int]] -) -> Callable[[T], T]: - + +def collect_statistic(statistics: dict[str, list[float, int]]) -> Callable[[T], T]: # ваш код - pass \ No newline at end of file + pass diff --git a/solutions/sem01/lesson12/task3.py b/solutions/sem01/lesson12/task3.py index 64c112ccc..58b0986e1 100644 --- a/solutions/sem01/lesson12/task3.py +++ b/solutions/sem01/lesson12/task3.py @@ -1,6 +1,3 @@ -import sys - - class FileOut: def __init__( self, diff --git a/solutions/sem02/lesson03/task1.py b/solutions/sem02/lesson03/task1.py index 2c3fc0b58..f21dcd807 100644 --- a/solutions/sem02/lesson03/task1.py +++ b/solutions/sem02/lesson03/task1.py @@ -8,13 +8,26 @@ class ShapeMismatchError(Exception): def sum_arrays_vectorized( lhs: np.ndarray, rhs: np.ndarray, -) -> np.ndarray: ... +) -> np.ndarray: + if len(lhs) != len(rhs): + raise ShapeMismatchError + return lhs + rhs -def compute_poly_vectorized(abscissa: np.ndarray) -> np.ndarray: ... +def compute_poly_vectorized(abscissa: np.ndarray) -> np.ndarray: + return np.power(abscissa, 2) * 3 + abscissa * 2 + 1 def get_mutual_l2_distances_vectorized( lhs: np.ndarray, rhs: np.ndarray, -) -> np.ndarray: ... +) -> np.ndarray: + if lhs.shape != rhs.shape: + raise ShapeMismatchError + return [ + [ + sum((lhs[i][k] - rhs[j][k]) ** 2 for k in range(len(lhs[0]))) ** 0.5 + for j in range(len(rhs)) + ] + for i in range(len(lhs)) + ] diff --git a/solutions/sem02/lesson03/task2.py b/solutions/sem02/lesson03/task2.py index fc823c1d6..17310c0be 100644 --- a/solutions/sem02/lesson03/task2.py +++ b/solutions/sem02/lesson03/task2.py @@ -9,11 +9,25 @@ def convert_from_sphere( distances: np.ndarray, azimuth: np.ndarray, inclination: np.ndarray, -) -> tuple[np.ndarray, np.ndarray, np.ndarray]: ... +) -> tuple[np.ndarray, np.ndarray, np.ndarray]: + if not (len(distances) == len(azimuth) == len(inclination)): + raise ShapeMismatchError + return ( + distances * np.sin(inclination) * np.cos(azimuth), + distances * np.sin(inclination) * np.sin(azimuth), + distances * np.cos(inclination), + ) def convert_to_sphere( abscissa: np.ndarray, ordinates: np.ndarray, applicates: np.ndarray, -) -> tuple[np.ndarray, np.ndarray, np.ndarray]: ... +) -> tuple[np.ndarray, np.ndarray, np.ndarray]: + if not (len(abscissa) == len(ordinates) == len(applicates)): + raise ShapeMismatchError + return ( + np.sqrt(np.power(abscissa, 2) + np.power(ordinates, 2) + np.power(applicates, 2)), + np.arctan2(ordinates, abscissa), + np.arctan2(np.sqrt(abscissa**2 + ordinates**2), applicates), + ) diff --git a/solutions/sem02/lesson03/task3.py b/solutions/sem02/lesson03/task3.py index 477acd0ce..8a247571f 100644 --- a/solutions/sem02/lesson03/task3.py +++ b/solutions/sem02/lesson03/task3.py @@ -1,6 +1,12 @@ import numpy as np +MIN_ELEM_COUNT = 3 + def get_extremum_indices( ordinates: np.ndarray, -) -> tuple[np.ndarray, np.ndarray]: ... +) -> tuple[np.ndarray, np.ndarray]: + if len(ordinates) < MIN_ELEM_COUNT: + raise ValueError + left, x, right = ordinates[:-2], ordinates[1:-1], ordinates[2:] + return (np.where((left > x) & (x < right))[0] + 1, np.where((left < x) & (x > right))[0] + 1) diff --git a/solutions/sem02/lesson04/task1.py b/solutions/sem02/lesson04/task1.py index 1b5526c1f..bfd7f600c 100644 --- a/solutions/sem02/lesson04/task1.py +++ b/solutions/sem02/lesson04/task1.py @@ -1,17 +1,52 @@ import numpy as np +MIN_PAD_SIZE = 1 +MIN_KERNEL_SIZE = 1 + def pad_image(image: np.ndarray, pad_size: int) -> np.ndarray: - # ваш код - return image + if pad_size < MIN_PAD_SIZE: + raise ValueError + shp = image.shape + if len(shp) == 2: + new_shp = (shp[0] + 2 * pad_size, shp[1] + 2 * pad_size) + padded_image = np.zeros(shape=new_shp, dtype=image.dtype) + for i in range(shp[0]): + for j in range(shp[1]): + padded_image[i + pad_size, j + pad_size] = image[i, j] + else: + new_shp = (shp[0] + 2 * pad_size, shp[1] + 2 * pad_size, shp[2]) + padded_image = np.zeros(shape=new_shp, dtype=image.dtype) + for i in range(shp[0]): + for j in range(shp[1]): + for k in range(shp[2]): + padded_image[i + pad_size, j + pad_size, k] = image[i, j, k] + return padded_image def blur_image( image: np.ndarray, kernel_size: int, ) -> np.ndarray: - # ваш код - return image + if (kernel_size < MIN_KERNEL_SIZE) or (kernel_size % 2 == 0): + raise ValueError + if kernel_size == 1: + return image + shp = image.shape + pad = kernel_size // 2 + image = pad_image(image, pad) + blured_image = np.zeros(shape=shp, dtype=image.dtype) + if len(shp) == 2: + for i in range(shp[0]): + for j in range(shp[1]): + kemel = image[i : i + kernel_size, j : j + kernel_size] + blured_image[i, j] = np.mean(kemel) + else: + for i in range(shp[0]): + for j in range(shp[1]): + kemel = image[i : i + kernel_size, j : j + kernel_size, :] + blured_image[i, j, :] = np.mean(kemel, axis=(0, 1)) + return blured_image if __name__ == "__main__": diff --git a/solutions/sem02/lesson04/task2.py b/solutions/sem02/lesson04/task2.py index be9a2288f..7f7c29b69 100644 --- a/solutions/sem02/lesson04/task2.py +++ b/solutions/sem02/lesson04/task2.py @@ -1,10 +1,24 @@ import numpy as np +MINIMAL_THRESHOLD = 1 + def get_dominant_color_info( image: np.ndarray[np.uint8], threshold: int = 5, ) -> tuple[np.uint8, float]: - # ваш код - - return 0, 0 + if threshold < MINIMAL_THRESHOLD: + raise ValueError("threshold must be positive") + all_possibals = np.full(shape=256, fill_value=-42, dtype=int) + image = image.reshape(-1) + for pixel in range(0, 256): + if pixel in image: + all_possibals[pixel] = 0 + mask = (image > pixel) & ((image - pixel) < threshold) | (image <= pixel) & ( + (pixel - image) < threshold + ) + all_possibals[pixel] += np.sum(mask) + return ( + np.uint8(np.argmax(all_possibals)), + all_possibals[np.argmax(all_possibals)] / image.size, + ) diff --git a/solutions/sem02/lesson05/task1.py b/solutions/sem02/lesson05/task1.py index e9c7c3c56..122b018bf 100644 --- a/solutions/sem02/lesson05/task1.py +++ b/solutions/sem02/lesson05/task1.py @@ -9,4 +9,12 @@ def can_satisfy_demand( costs: np.ndarray, resource_amounts: np.ndarray, demand_expected: np.ndarray, -) -> bool: ... +) -> bool: + if costs.size != resource_amounts.size * demand_expected.size: + raise ShapeMismatchError + spends = [0] * resource_amounts.size + for j in range(demand_expected.size): + amount = demand_expected[j] + for i in range(resource_amounts.size): + spends[i] += amount * costs[i][j] + return np.all(spends <= resource_amounts) diff --git a/solutions/sem02/lesson05/task2.py b/solutions/sem02/lesson05/task2.py index be1fb9d2b..93548d63b 100644 --- a/solutions/sem02/lesson05/task2.py +++ b/solutions/sem02/lesson05/task2.py @@ -8,4 +8,14 @@ class ShapeMismatchError(Exception): def get_projections_components( matrix: np.ndarray, vector: np.ndarray, -) -> tuple[np.ndarray | None, np.ndarray | None]: ... +) -> tuple[np.ndarray | None, np.ndarray | None]: + shp = matrix.shape + if not (shp[0] == shp[1] and shp[0] == vector.size): + raise ShapeMismatchError + if not (np.linalg.matrix_rank(matrix) == shp[0]): + return (None, None) + proj, orth = [], [] + for base in matrix: + proj.append((base @ vector) * base / (np.linalg.norm(base) ** 2)) + orth.append(vector - (base @ vector) * base / (np.linalg.norm(base) ** 2)) + return (np.array(proj), np.array(orth)) diff --git a/solutions/sem02/lesson05/task3.py b/solutions/sem02/lesson05/task3.py index 0c66906cb..ff96c7e9e 100644 --- a/solutions/sem02/lesson05/task3.py +++ b/solutions/sem02/lesson05/task3.py @@ -9,4 +9,9 @@ def adaptive_filter( Vs: np.ndarray, Vj: np.ndarray, diag_A: np.ndarray, -) -> np.ndarray: ... +) -> np.ndarray: + if not (Vs.shape[0] == Vj.shape[0] and Vj.shape[1] == diag_A.shape[0]): + raise ShapeMismatchError + return Vs - Vj @ np.linalg.inv( + np.eye(diag_A.size) + np.transpose(np.conj(Vj)) @ Vj @ np.diag(diag_A) + ) @ (np.transpose(np.conj(Vj)) @ Vs) diff --git a/solutions/sem02/lesson07/task1.py b/solutions/sem02/lesson07/task1.py index 3a505d89b..de9266a68 100644 --- a/solutions/sem02/lesson07/task1.py +++ b/solutions/sem02/lesson07/task1.py @@ -13,8 +13,122 @@ def visualize_diagrams( ordinates: np.ndarray, diagram_type: Any, ) -> None: - # ваш код - pass + if abscissa.size != ordinates.size: + raise ShapeMismatchError + plt.style.use("ggplot") + if diagram_type == "hist": + bins_amount = abscissa.size // 20 + figure = plt.figure(figsize=(9, 9)) + grid = plt.GridSpec(4, 4) + + axis_scatter = figure.add_subplot(grid[:-1, 1:]) + axis_hist_vert = figure.add_subplot( + grid[:-1, 0], + sharey=axis_scatter, + ) + axis_hist_hor = figure.add_subplot( + grid[-1, 1:], + sharex=axis_scatter, + ) + + axis_scatter.scatter(abscissa, ordinates, color="purple", alpha=0.5) + axis_hist_hor.hist( + abscissa, + bins=bins_amount, + color="cornflowerblue", + edgecolor="blue", + density=True, + alpha=0.7, + ) + axis_hist_vert.hist( + ordinates, + bins=bins_amount, + color="indianred", + edgecolor="red", + orientation="horizontal", + density=True, + alpha=0.7, + ) + + axis_hist_hor.invert_yaxis() + axis_hist_vert.invert_xaxis() + elif diagram_type == "box": + figure = plt.figure(figsize=(9, 9)) + grid = plt.GridSpec(4, 4) + + axis_scatter = figure.add_subplot(grid[:-1, 1:]) + axis_box_vert = figure.add_subplot( + grid[:-1, 0], + sharey=axis_scatter, + ) + axis_box_hor = figure.add_subplot( + grid[-1, 1:], + sharex=axis_scatter, + ) + + axis_scatter.scatter(abscissa, ordinates, color="cornflowerblue", alpha=0.5) + axis_box_hor.boxplot( + abscissa, + vert=False, + patch_artist=True, + boxprops=dict(facecolor="lightsteelblue"), + medianprops=dict(color="k"), + ) + axis_box_vert.boxplot( + ordinates, + vert=True, + patch_artist=True, + boxprops=dict(facecolor="lightsteelblue"), + medianprops=dict(color="k"), + ) + axis_box_hor.invert_yaxis() + axis_box_vert.invert_xaxis() + elif diagram_type == "violin": + figure = plt.figure(figsize=(9, 9)) + grid = plt.GridSpec(4, 4) + + axis_scatter = figure.add_subplot(grid[:-1, 1:]) + axis_viol_vert = figure.add_subplot( + grid[:-1, 0], + sharey=axis_scatter, + ) + axis_viol_hor = figure.add_subplot( + grid[-1, 1:], + sharex=axis_scatter, + ) + + axis_scatter.scatter(abscissa, ordinates, color="purple", alpha=0.5) + parts_hor = axis_viol_hor.violinplot( + abscissa, + vert=False, + showmedians=True, + ) + for body in parts_hor["bodies"]: + body.set_facecolor("cornflowerblue") + body.set_edgecolor("blue") + + for part in parts_hor: + if part == "bodies": + continue + parts_hor[part].set_edgecolor("cornflowerblue") + + parts_viol = axis_viol_vert.violinplot( + ordinates, + vert=True, + showmedians=True, + ) + for body in parts_viol["bodies"]: + body.set_facecolor("indianred") + body.set_edgecolor("red") + + for part in parts_viol: + if part == "bodies": + continue + parts_viol[part].set_edgecolor("indianred") + axis_viol_hor.invert_yaxis() + axis_viol_vert.invert_xaxis() + else: + raise ValueError if __name__ == "__main__": diff --git a/solutions/sem02/lesson07/task2.py b/solutions/sem02/lesson07/task2.py index decd607ef..fbf25ad22 100644 --- a/solutions/sem02/lesson07/task2.py +++ b/solutions/sem02/lesson07/task2.py @@ -1 +1,44 @@ -# ваш код (используйте функции или классы для решения данной задачи) +import json + +import matplotlib.pyplot as plt +import numpy as np + + +def download_data(path: str) -> tuple[np.ndarray, np.ndarray]: + with open(path, "r", encoding="utf-8") as file: + data = json.load(file) + before = np.array(data["before"]) + after = np.array(data["after"]) + return (before, after) + + +def count_stages(arr: np.ndarray) -> list[int]: + counts = [] + for stage in ["I", "II", "III", "IV"]: + mask = arr == stage + counts.append(sum(mask)) + return counts + + +def visualize_data(before: list[int], after: list[int]): + plt.style.use("ggplot") + stages = ["I", "II", "III", "IV"] + poses = np.arange(len(stages)) + width = 0.4 + + _, axes = plt.subplots(figsize=(9, 6)) + axes.bar( + poses - width / 2, before, width, label="before", color="cornflowerblue", edgecolor="blue" + ) + axes.bar(poses + width / 2, after, width, label="after", color="indianred", edgecolor="red") + axes.set_xticks(poses) + axes.set_xticklabels(stages) + axes.set_ylabel("Amount of people") + axes.set_title("Mitral disease stages") + axes.legend() + + +if __name__ == "__main__": + before, after = download_data(path="solutions/sem02/lesson07/data/medic_data.json") + visualize_data(count_stages(before), count_stages(after)) + plt.show() diff --git a/solutions/sem02/lesson08/task1.py b/solutions/sem02/lesson08/task1.py index 89f88572f..57e015998 100644 --- a/solutions/sem02/lesson08/task1.py +++ b/solutions/sem02/lesson08/task1.py @@ -1,34 +1,121 @@ from functools import partial +from typing import Callable import matplotlib.pyplot as plt import numpy as np - -from IPython.display import HTML from matplotlib.animation import FuncAnimation +def calculate_signal( + modulation: Callable | None, + fc: int, + num_frames: int, + plot_duration: float, + animation_step: float = 0.01, +) -> tuple[np.ndarray, np.ndarray]: + if modulation is None: + + def base_modulation(t: float) -> float: + return 1.0 + + modulation = base_modulation + total_time = num_frames * animation_step + plot_duration + t = np.arange(0, total_time, time_step) + s = modulation(t) * np.sin(2 * np.pi * fc * t) + return t, s + + def create_modulation_animation( - modulation, - fc, - num_frames, - plot_duration, - time_step=0.001, - animation_step=0.01, - save_path="" + modulation: Callable | None, + fc: int, + num_frames: int, + plot_duration: float, + time_step: float = 0.001, + animation_step: float = 0.01, + save_path: str = "", ) -> FuncAnimation: - # ваш код - return FuncAnimation() + if fc < 0: + raise ValueError("Frequency must not be negative") + if num_frames <= 0: + raise ValueError("Numbers of frames must ne positive") + if plot_duration <= 0: + raise ValueError("Plot duration must ne positive") + if time_step <= 0: + raise ValueError("Time step must ne positive") + if animation_step <= 0: + raise ValueError("Animation step must ne positive") + + plt.style.use("ggplot") + + t, s = calculate_signal( + modulation=modulation, + fc=fc, + num_frames=num_frames, + plot_duration=plot_duration, + animation_step=animation_step, + ) + + abscissa = np.arange(0, plot_duration, time_step) + + figure, axis = plt.subplots() + axis.set_xlabel("Время (с)") + axis.set_ylabel("Амплитуда") + axis.set_title("Анимация модулированного сигнала") + + axis.set_xlim(0, plot_duration) + axis.set_ylim(1.5 * s.min(), 1.5 * s.max()) + + line, *_ = axis.plot( + abscissa, + np.sin(abscissa), + c="royalblue", + label="Модулированный сигнал", + ) + axis.legend(loc="upper right") + + def update_frame( + frame_id: int, + *, + line: plt.Line2D, + plot_duration: float, + animation_step: float, + ) -> tuple[plt.Line2D]: + t_start = frame_id * animation_step + t_end = t_start + plot_duration + mask = (t >= t_start) & (t <= t_end) + t_curr = t[mask] + s_curr = s[mask] + line.set_data(t_curr, s_curr) + axis.set_xlim(t_start, t_end) + return (line,) + + animation = FuncAnimation( + figure, + partial( + update_frame, + line=line, + plot_duration=plot_duration, + animation_step=animation_step, + ), + frames=num_frames, + interval=animation_step, + blit=True, + ) + if save_path: + animation.save(save_path, writer="pillow", fps=24) + return animation if __name__ == "__main__": + def modulation_function(t): - return np.cos(t * 6) + return np.cos(t * 6) - num_frames = 100 - plot_duration = np.pi / 2 - time_step = 0.001 - animation_step = np.pi / 200 - fc = 50 + num_frames = 100 + plot_duration = np.pi / 2 + time_step = 0.001 + animation_step = np.pi / 200 + fc = 50 save_path_with_modulation = "modulated_signal.gif" animation = create_modulation_animation( @@ -38,6 +125,5 @@ def modulation_function(t): plot_duration=plot_duration, time_step=time_step, animation_step=animation_step, - save_path=save_path_with_modulation + save_path=save_path_with_modulation, ) - HTML(animation.to_jshtml()) \ No newline at end of file diff --git a/solutions/sem02/lesson08/task2.py b/solutions/sem02/lesson08/task2.py index b677c0702..43d11ac93 100644 --- a/solutions/sem02/lesson08/task2.py +++ b/solutions/sem02/lesson08/task2.py @@ -7,28 +7,26 @@ from matplotlib.animation import FuncAnimation - - def animate_wave_algorithm( - maze: np.ndarray, - start: tuple[int, int], - end: tuple[int, int], - save_path: str = "" -) -> FuncAnimation: + maze: np.ndarray, start: tuple[int, int], end: tuple[int, int], save_path: str = "" +) -> FuncAnimation: # ваш код return FuncAnimation() + if __name__ == "__main__": # Пример 1 - maze = np.array([ - [0, 0, 0, 0, 0, 0, 0], - [0, 1, 1, 1, 1, 1, 0], - [1, 1, 0, 1, 0, 1, 0], - [0, 0, 1, 1, 0, 1, 0], - [0, 0, 0, 0, 0, 1, 0], - [1, 1, 1, 1, 1, 1, 0], - [0, 0, 0, 0, 0, 0, 0], - ]) + maze = np.array( + [ + [0, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 1, 1, 1, 0], + [1, 1, 0, 1, 0, 1, 0], + [0, 0, 1, 1, 0, 1, 0], + [0, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 1, 1, 0], + [0, 0, 0, 0, 0, 0, 0], + ] + ) start = (2, 0) end = (5, 0) @@ -36,9 +34,9 @@ def animate_wave_algorithm( animation = animate_wave_algorithm(maze, start, end, save_path) HTML(animation.to_jshtml()) - + # Пример 2 - + maze_path = "./data/maze.npy" loaded_maze = np.load(maze_path) @@ -49,5 +47,3 @@ def animate_wave_algorithm( loaded_animation = animate_wave_algorithm(loaded_maze, start, end, loaded_save_path) HTML(loaded_animation.to_jshtml()) - - \ No newline at end of file diff --git a/solutions/sem02/lesson10/task1.ipynb b/solutions/sem02/lesson10/task1.ipynb index 4b4e9e335..25f72babc 100644 --- a/solutions/sem02/lesson10/task1.ipynb +++ b/solutions/sem02/lesson10/task1.ipynb @@ -34,12 +34,168 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 85, "id": "d7b00711", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
survivedpclasssexagesibspparchfareembarkedclasswhoadult_maledeckembark_townalivealone
36003male40.01427.9000SThirdmanTrueNaNSouthamptonnoFalse
21811female32.00076.2917CFirstwomanFalseDCherbourgyesTrue
21613female27.0007.9250SThirdwomanFalseNaNSouthamptonyesTrue
47403female22.0009.8375SThirdwomanFalseNaNSouthamptonnoTrue
84303male34.5006.4375CThirdmanTrueNaNCherbourgnoTrue
\n", + "
" + ], + "text/plain": [ + " survived pclass sex age sibsp parch fare embarked class \\\n", + "360 0 3 male 40.0 1 4 27.9000 S Third \n", + "218 1 1 female 32.0 0 0 76.2917 C First \n", + "216 1 3 female 27.0 0 0 7.9250 S Third \n", + "474 0 3 female 22.0 0 0 9.8375 S Third \n", + "843 0 3 male 34.5 0 0 6.4375 C Third \n", + "\n", + " who adult_male deck embark_town alive alone \n", + "360 man True NaN Southampton no False \n", + "218 woman False D Cherbourg yes True \n", + "216 woman False NaN Southampton yes True \n", + "474 woman False NaN Southampton no True \n", + "843 man True NaN Cherbourg no True " + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "import seaborn as sns\n", + "import pandas as pd\n", + "import numpy as np\n", "\n", "\n", "titanic_data = sns.load_dataset(\"titanic\")\n", @@ -66,12 +222,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 92, "id": "cd2f1773", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "survived 0\n", + "pclass 0\n", + "sex 0\n", + "age 0\n", + "sibsp 0\n", + "parch 0\n", + "fare 0\n", + "embarked 0\n", + "class 0\n", + "who 0\n", + "adult_male 0\n", + "embark_town 0\n", + "alive 0\n", + "alone 0\n", + "dtype: int64" + ] + }, + "execution_count": 92, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# ваш код" + "missed_data = pd.Series({col: titanic_data[col].isnull().sum() for col in titanic_data.columns})\n", + "missed_data" ] }, { @@ -88,12 +270,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 87, "id": "7e458447", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "titanic_data = titanic_data.dropna(axis=\"columns\", thresh=titanic_data.shape[0] // 2 + 1)\n", + "titanic_data = titanic_data.dropna(thresh=titanic_data.shape[1] // 2 + 1)" ] }, { @@ -111,12 +294,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 89, "id": "f7db5e99", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "fill_vals = titanic_data[\"who\"].map(\n", + " {\n", + " \"man\": titanic_data[titanic_data.who == \"man\"][\"age\"].median(),\n", + " \"woman\": titanic_data[titanic_data.who == \"woman\"][\"age\"].median(),\n", + " \"child\": titanic_data[titanic_data.who == \"child\"][\"age\"].median(),\n", + " }\n", + ")\n", + "titanic_data[\"age\"] = titanic_data[\"age\"].fillna(fill_vals)" ] }, { @@ -131,12 +321,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 91, "id": "67a0c6bc", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "titanic_data = titanic_data.dropna(thresh=len(titanic_data.columns) - 1)" ] }, { @@ -151,12 +341,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 93, "id": "6a2d0ae9", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "'Southampton'" + ] + }, + "execution_count": 93, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# ваш код" + "towns = titanic_data[\"embark_town\"].value_counts()\n", + "towns.index[0]" ] }, { @@ -171,12 +373,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 94, "id": "11acb4b4", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "38.25" + ] + }, + "execution_count": 94, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# ваш код" + "survivos_percent = (titanic_data[\"survived\"].mean() * 100).round(2)\n", + "survivos_percent" ] }, { @@ -191,12 +405,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 95, "id": "59ec7295", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "embark_town\n", + "Southampton 217\n", + "Cherbourg 93\n", + "Queenstown 30\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 95, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# ваш код" + "survivos_town = titanic_data[\"embark_town\"][titanic_data[\"survived\"] == 1].value_counts()\n", + "survivos_town" ] }, { @@ -211,12 +441,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 96, "id": "34daca28", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "class\n", + "First 62.62\n", + "Second 47.28\n", + "Third 24.24\n", + "Name: count, dtype: float64" + ] + }, + "execution_count": 96, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# ваш код" + "survivos_class = (\n", + " titanic_data[\"class\"][titanic_data[\"survived\"] == 1].value_counts()\n", + " / titanic_data[\"class\"].value_counts()\n", + " * 100\n", + ").round(2)\n", + "survivos_class" ] }, { @@ -231,12 +481,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 97, "id": "1fc0d667", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "73.58" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# ваш код" + "wealthy_percent = (titanic_data[titanic_data[\"fare\"] >= 100][\"survived\"].mean() * 100).round(2)\n", + "wealthy_percent" ] }, { @@ -251,12 +513,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 98, "id": "480352b6", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 98, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# ваш код" + "child_alone = titanic_data[(titanic_data[\"who\"] == \"child\") & (titanic_data[\"alone\"] == True)]\n", + "len(child_alone)" ] }, {