diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..23fd35f0e
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "editor.formatOnSave": true
+}
\ No newline at end of file
diff --git a/deprecated_tests/sem01/tests/test_lesson02_tasks.py b/deprecated_tests/sem01/tests/test_lesson02_tasks.py
index f11403f4d..b7febe4ba 100644
--- a/deprecated_tests/sem01/tests/test_lesson02_tasks.py
+++ b/deprecated_tests/sem01/tests/test_lesson02_tasks.py
@@ -10,7 +10,7 @@
@pytest.mark.parametrize(
- "num, result_expected",
+ "num, result_expected",
(
pytest.param(
0,
@@ -44,7 +44,7 @@ def test_get_factorial(num: int, result_expected: int) -> None:
@pytest.mark.parametrize(
- "num, result_expected",
+ "num, result_expected",
(
pytest.param(
0,
@@ -83,7 +83,7 @@ def test_get_doubled_factorial(num: int, result_expected: int) -> None:
@pytest.mark.parametrize(
- "num, result_expected",
+ "num, result_expected",
(
pytest.param(
1,
@@ -125,7 +125,7 @@ def test_get_amount_of_ways_to_climb(
@pytest.mark.parametrize(
- "num, result_expected",
+ "num, result_expected",
(
pytest.param(
1,
@@ -162,7 +162,7 @@ def test_get_multiplications_amount(
@pytest.mark.parametrize(
- "num1, num2, result_expected",
+ "num1, num2, result_expected",
(
pytest.param(
1,
@@ -229,7 +229,7 @@ def test_get_gcd(
@pytest.mark.parametrize(
- "num, result_expected",
+ "num, result_expected",
(
pytest.param(
1,
@@ -273,10 +273,10 @@ def test_get_sum_of_prime_divisors(num: int, result_expected: int) -> None:
@pytest.mark.parametrize(
- "num, result_expected",
+ "num, result_expected",
(
pytest.param(
- -10**10,
+ -(10**10),
False,
id="negative-ten-billion",
),
diff --git a/deprecated_tests/sem01/tests/test_lesson04_tasks.py b/deprecated_tests/sem01/tests/test_lesson04_tasks.py
index 4110bdcc0..9c9457ff2 100644
--- a/deprecated_tests/sem01/tests/test_lesson04_tasks.py
+++ b/deprecated_tests/sem01/tests/test_lesson04_tasks.py
@@ -1,13 +1,9 @@
-import pytest
-import random
-
-from solutions.sem01.lesson04.task1 import is_arithmetic_progression
-from solutions.sem01.lesson04.task2 import merge_intervals
-from solutions.sem01.lesson04.task3 import find_single_number
-from solutions.sem01.lesson04.task4 import move_zeros_to_end
-from solutions.sem01.lesson04.task5 import find_row_with_most_ones
+import pytest
+
from solutions.sem01.lesson04.task6 import count_cycles
+"""
+# 1
@pytest.mark.parametrize("lst, expected", [
pytest.param([], True, id="empty_list"),
pytest.param([5], True, id="single_element"),
@@ -20,8 +16,10 @@
pytest.param([1, 1, 1, 1], True, id="constant_sequence"),
pytest.param([1, 2, 3, 5], False, id="almost_ap_but_not"),
pytest.param([0, 0, 1], False, id="two_same_one_different"),
- pytest.param([10**5 + i*10**2 for i in range(1000)], True, id="long_list_true"),
- pytest.param([10**5 + i*10**2 for i in range(999)] + [1], False, id="long_list_false"),
+ pytest.param([10**5 + i*10**2 for i in range(1000)],
+ True, id="long_list_true"),
+ pytest.param([10**5 + i*10**2 for i in range(999)] +
+ [1], False, id="long_list_false"),
])
def test_is_arithmetic_progression_parametrized(lst, expected):
if len(lst) > 500:
@@ -29,19 +27,26 @@ def test_is_arithmetic_progression_parametrized(lst, expected):
assert is_arithmetic_progression(lst) == expected
+# 2
@pytest.mark.parametrize("intervals, expected", [
pytest.param([], [], id="empty"),
pytest.param([[1, 3]], [[1, 3]], id="single_interval"),
- pytest.param([[10, 13], [1, 3], [2, 6], [8, 10], [15, 18]], [[1, 6], [8, 13], [15, 18]], id="classic_merge"),
+ pytest.param([[10, 13], [1, 3], [2, 6], [8, 10], [15, 18]], [
+ [1, 6], [8, 13], [15, 18]], id="classic_merge"),
pytest.param([[1, 4], [4, 5]], [[1, 5]], id="touching_intervals"),
pytest.param([[1, 4], [2, 3]], [[1, 4]], id="nested_interval"),
- pytest.param([[5, 7], [1, 3], [15, 20], [0, 0], [2, 4], [6, 10], [0, 2]], [[0, 4], [5, 10], [15, 20]], id="unsorted_input"),
- pytest.param([[1, 2], [3, 4], [5, 6]], [[1, 2], [3, 4], [5, 6]], id="no_overlap"),
- pytest.param([[1, 10], [2, 3], [4, 5], [6, 7]], [[1, 10]], id="all_merged"),
+ pytest.param([[5, 7], [1, 3], [15, 20], [0, 0], [2, 4], [6, 10], [0, 2]], [
+ [0, 4], [5, 10], [15, 20]], id="unsorted_input"),
+ pytest.param([[1, 2], [3, 4], [5, 6]], [
+ [1, 2], [3, 4], [5, 6]], id="no_overlap"),
+ pytest.param([[1, 10], [2, 3], [4, 5], [6, 7]],
+ [[1, 10]], id="all_merged"),
])
def test_merge_intervals(intervals, expected):
assert merge_intervals(intervals) == expected
+
+# 3
@pytest.mark.parametrize("nums, expected", [
pytest.param([2, 2, 1], 1, id="simple_case"),
pytest.param([4, 1, 2, 1, 2], 4, id="middle_single"),
@@ -49,11 +54,14 @@ def test_merge_intervals(intervals, expected):
pytest.param([100, 200, 300, 200, 100], 300, id="large_numbers"),
pytest.param([0, 1, 0], 1, id="with_zero"),
pytest.param([7, 8, 9, 8, 7], 9, id="unsorted"),
- pytest.param([i + 10**5 for i in range(500)] + [i + 10**5 for i in range(500)] + [69], 69, id="long_list"),
+ pytest.param([i + 10**5 for i in range(500)] +
+ [i + 10**5 for i in range(500)] + [69], 69, id="long_list"),
])
def test_find_single_number(nums, expected):
assert find_single_number(nums) == expected
+
+# 4
@pytest.mark.parametrize("input_list, expected_list, expected_index", [
pytest.param([0, 1, 0, 3, 12], [1, 3, 12, 0, 0], 3, id="basic"),
pytest.param([0, 0, 1], [1, 0, 0], 1, id="zeros_first"),
@@ -71,6 +79,9 @@ def test_move_zeros_to_end_parametrized(input_list, expected_list, expected_inde
assert result_index == expected_index
+# 5
+
+
@pytest.mark.parametrize("matrix, expected_row", [
pytest.param(
[[0, 0, 1, 1],
@@ -119,8 +130,8 @@ def test_move_zeros_to_end_parametrized(input_list, expected_list, expected_inde
pytest.param(
[[0, 0, 1],
[0, 1, 1],
- [0, 1, 1]],
- 1,
+ [0, 1, 1]],
+ 1,
id="tie"
),
])
@@ -144,16 +155,22 @@ def test_find_row_with_most_ones_big_data():
assert find_row_with_most_ones(matrix) == 1
-@pytest.mark.parametrize("input_arr, expected", [
- pytest.param([0], 1, id="self_loop"),
- pytest.param([1, 0], 1, id="two_cycle"),
- pytest.param([1, 2, 0], 1, id="three_cycle"),
- pytest.param([0, 1, 2], 3, id="three_self_loops"),
- pytest.param([1, 0, 3, 2], 2, id="two_2_cycles"),
- pytest.param([2, 0, 1, 4, 3], 2, id="mixed_cycles"),
- pytest.param([10, 6, 2, 9, 4, 0, 3, 8, 7, 1, 5], 5, id="mixed_cycles"),
- pytest.param([], 0, id="empty"),
-])
+"""
+
+
+@pytest.mark.parametrize(
+ "input_arr, expected",
+ [
+ pytest.param([0], 1, id="self_loop"),
+ pytest.param([1, 0], 1, id="two_cycle"),
+ pytest.param([1, 2, 0], 1, id="three_cycle"),
+ pytest.param([0, 1, 2], 3, id="three_self_loops"),
+ pytest.param([1, 0, 3, 2], 2, id="two_2_cycles"),
+ pytest.param([2, 0, 1, 4, 3], 2, id="mixed_cycles"),
+ pytest.param([10, 6, 2, 9, 4, 0, 3, 8, 7, 1, 5], 5, id="mixed_cycles"),
+ pytest.param([], 0, id="empty"),
+ ],
+)
def test_count_cycles(input_arr, expected):
arr = input_arr[:]
assert count_cycles(arr) == expected
diff --git a/deprecated_tests/sem01/tests/test_lesson05_tasks.py b/deprecated_tests/sem01/tests/test_lesson05_tasks.py
index 72ad6bc8f..c4efc4959 100644
--- a/deprecated_tests/sem01/tests/test_lesson05_tasks.py
+++ b/deprecated_tests/sem01/tests/test_lesson05_tasks.py
@@ -1,12 +1,8 @@
-import pytest
+import pytest
-from solutions.sem01.lesson05.task1 import is_palindrome
-from solutions.sem01.lesson05.task2 import are_anagrams
-from solutions.sem01.lesson05.task3 import is_punctuation
-from solutions.sem01.lesson05.task4 import unzip
-from solutions.sem01.lesson05.task5 import reg_validator
from solutions.sem01.lesson05.task6 import simplify_path
+"""
@pytest.mark.parametrize("s, expected", [
pytest.param("", True, id="empty_string"),
pytest.param("a", True, id="single_char"),
@@ -27,6 +23,8 @@ def test_is_palindrome(s, expected):
assert is_palindrome(s) == expected
+
+
@pytest.mark.parametrize("w1, w2, expected", [
pytest.param("listen", "silent", True, id="classic_anagram"),
pytest.param("evil", "vile", True, id="another_anagram"),
@@ -61,6 +59,7 @@ def test_are_anagrams_linear(w1, w2, expected):
def test_is_only_punctuation(s, expected):
assert is_punctuation(s) == expected
+
@pytest.mark.parametrize("compressed, expected", [
pytest.param("AbcD*4 ef GhI*2", "AbcDAbcDAbcDAbcDefGhIGhI", id="example"),
pytest.param("a*3 b*2", "aaabb", id="simple_letters"),
@@ -75,6 +74,7 @@ def test_is_only_punctuation(s, expected):
def test_decompress(compressed, expected):
assert unzip(compressed) == expected
+
@pytest.mark.parametrize("regexp, s, expected", [
pytest.param("d", "123", True, id="d_valid_number"),
pytest.param("d", "0", True, id="d_zero"),
@@ -118,34 +118,39 @@ def test_decompress(compressed, expected):
pytest.param("s", "1a", True, id="s_digit_letter"),
pytest.param("s", "a!1", False, id="s_contains_exclamation"),
pytest.param("d-w-s", "123-abc-XY1Z23", True, id="d_w_s_valid"),
- pytest.param("d-w-s", "123-abc-XYZ_123", False, id="d_w_s_underscore_in_s"),
+ pytest.param("d-w-s", "123-abc-XYZ_123", False,
+ id="d_w_s_underscore_in_s"),
])
def test_match_pattern(regexp, s, expected):
assert reg_validator(regexp, s) == expected
+"""
-@pytest.mark.parametrize("path, expected", [
- pytest.param("/home/", "/home", id="trailing_slash"),
- pytest.param("/../", "", id="go_above_root"),
- pytest.param("/home//foo/", "/home/foo", id="double_slash"),
- pytest.param("/home/./foo/", "/home/foo", id="current_dir_dot"),
- pytest.param("/./././", "/", id="only_dots_and_slashes"),
- pytest.param("/a/./b/../../c/", "/c", id="complex_up_and_down"),
- pytest.param("/a/b/c/../../../", "/", id="back_to_root"),
- pytest.param("/", "/", id="root_only"),
- pytest.param("/.", "/", id="root_with_dot"),
- pytest.param("/..", "", id="root_with_double_dot"),
- pytest.param("/...", "/...", id="triple_dot_as_name"),
- pytest.param("/..a", "/..a", id="dot_dot_a_as_name"),
- pytest.param("/a.b/c.d", "/a.b/c.d", id="names_with_dots"),
- pytest.param("/a//b////c/d//././/..", "/a/b/c", id="messy_path"),
- pytest.param("/a/./b/./c/./d", "/a/b/c/d", id="dots_everywhere"),
- pytest.param("/a/./b/../../c/./d/", "/c/d", id="up_down_with_dots"),
- pytest.param("/../foo", "", id="up_then_valid"),
- pytest.param("/../../foo", "", id="multiple_up_then_valid"),
- pytest.param("/../../../", "", id="three_up_from_root"),
- pytest.param("/home/foo/./../../../", "", id="too_many_up"),
- pytest.param("/_a.b/c__1/..", "/_a.b", id="names_with_underscores_and_dots"),
-])
+@pytest.mark.parametrize(
+ "path, expected",
+ [
+ pytest.param("/home/", "/home", id="trailing_slash"),
+ pytest.param("/../", "", id="go_above_root"),
+ pytest.param("/home//foo/", "/home/foo", id="double_slash"),
+ pytest.param("/home/./foo/", "/home/foo", id="current_dir_dot"),
+ pytest.param("/./././", "/", id="only_dots_and_slashes"),
+ pytest.param("/a/./b/../../c/", "/c", id="complex_up_and_down"),
+ pytest.param("/a/b/c/../../../", "/", id="back_to_root"),
+ pytest.param("/", "/", id="root_only"),
+ pytest.param("/.", "/", id="root_with_dot"),
+ pytest.param("/..", "", id="root_with_double_dot"),
+ pytest.param("/...", "/...", id="triple_dot_as_name"),
+ pytest.param("/..a", "/..a", id="dot_dot_a_as_name"),
+ pytest.param("/a.b/c.d", "/a.b/c.d", id="names_with_dots"),
+ pytest.param("/a//b////c/d//././/..", "/a/b/c", id="messy_path"),
+ pytest.param("/a/./b/./c/./d", "/a/b/c/d", id="dots_everywhere"),
+ pytest.param("/a/./b/../../c/./d/", "/c/d", id="up_down_with_dots"),
+ pytest.param("/../foo", "", id="up_then_valid"),
+ pytest.param("/../../foo", "", id="multiple_up_then_valid"),
+ pytest.param("/../../../", "", id="three_up_from_root"),
+ pytest.param("/home/foo/./../../../", "", id="too_many_up"),
+ pytest.param("/_a.b/c__1/..", "/_a.b", id="names_with_underscores_and_dots"),
+ ],
+)
def test_simplify_path(path, expected):
- assert simplify_path(path) == expected
\ No newline at end of file
+ assert simplify_path(path) == expected
diff --git a/deprecated_tests/sem01/tests/test_lesson06_tasks.py b/deprecated_tests/sem01/tests/test_lesson06_tasks.py
index 707d6609f..e20a8dd81 100644
--- a/deprecated_tests/sem01/tests/test_lesson06_tasks.py
+++ b/deprecated_tests/sem01/tests/test_lesson06_tasks.py
@@ -1,4 +1,4 @@
-import pytest
+import pytest
from solutions.sem01.lesson06.task1 import int_to_roman
from solutions.sem01.lesson06.task2 import get_len_of_longest_substring
@@ -6,103 +6,119 @@
from solutions.sem01.lesson06.task4 import count_unique_words
-@pytest.mark.parametrize("num, expected", [
- pytest.param(1, "I", id="one"),
- pytest.param(2, "II", id="two"),
- pytest.param(3, "III", id="three"),
- pytest.param(4, "IV", id="four"),
- pytest.param(5, "V", id="five"),
- pytest.param(6, "VI", id="six"),
- pytest.param(9, "IX", id="nine"),
- pytest.param(10, "X", id="ten"),
- pytest.param(11, "XI", id="eleven"),
- pytest.param(14, "XIV", id="fourteen"),
- pytest.param(19, "XIX", id="nineteen"),
- pytest.param(27, "XXVII", id="twenty_seven"),
- pytest.param(40, "XL", id="forty"),
- pytest.param(44, "XLIV", id="forty_four"),
- pytest.param(50, "L", id="fifty"),
- pytest.param(58, "LVIII", id="fifty_eight"),
- pytest.param(90, "XC", id="ninety"),
- pytest.param(99, "XCIX", id="ninety_nine"),
- pytest.param(100, "C", id="hundred"),
- pytest.param(400, "CD", id="four_hundred"),
- pytest.param(500, "D", id="five_hundred"),
- pytest.param(900, "CM", id="nine_hundred"),
- pytest.param(1000, "M", id="thousand"),
- pytest.param(1994, "MCMXCIV", id="mcmxciv"),
- pytest.param(3999, "MMMCMXCIX", id="max_value"),
- pytest.param(2023, "MMXXIII", id="current_year"),
- pytest.param(1984, "MCMLXXXIV", id="classic"),
-])
+@pytest.mark.parametrize(
+ "num, expected",
+ [
+ pytest.param(1, "I", id="one"),
+ pytest.param(2, "II", id="two"),
+ pytest.param(3, "III", id="three"),
+ pytest.param(4, "IV", id="four"),
+ pytest.param(5, "V", id="five"),
+ pytest.param(6, "VI", id="six"),
+ pytest.param(9, "IX", id="nine"),
+ pytest.param(10, "X", id="ten"),
+ pytest.param(11, "XI", id="eleven"),
+ pytest.param(14, "XIV", id="fourteen"),
+ pytest.param(19, "XIX", id="nineteen"),
+ pytest.param(27, "XXVII", id="twenty_seven"),
+ pytest.param(40, "XL", id="forty"),
+ pytest.param(44, "XLIV", id="forty_four"),
+ pytest.param(50, "L", id="fifty"),
+ pytest.param(58, "LVIII", id="fifty_eight"),
+ pytest.param(90, "XC", id="ninety"),
+ pytest.param(99, "XCIX", id="ninety_nine"),
+ pytest.param(100, "C", id="hundred"),
+ pytest.param(400, "CD", id="four_hundred"),
+ pytest.param(500, "D", id="five_hundred"),
+ pytest.param(900, "CM", id="nine_hundred"),
+ pytest.param(1000, "M", id="thousand"),
+ pytest.param(1994, "MCMXCIV", id="mcmxciv"),
+ pytest.param(3999, "MMMCMXCIX", id="max_value"),
+ pytest.param(2023, "MMXXIII", id="current_year"),
+ pytest.param(1984, "MCMLXXXIV", id="classic"),
+ ],
+)
def test_int_to_roman(num, expected):
assert int_to_roman(num) == expected
-@pytest.mark.parametrize("s, expected", [
- pytest.param("", 0, id="empty_string"),
- pytest.param("a", 1, id="single_char"),
- pytest.param("aa", 1, id="two_same_chars"),
- pytest.param("ab", 2, id="two_different_chars"),
- pytest.param("abcabcbb", 3, id="classic_example_abc"),
- pytest.param("bbbbb", 1, id="all_same"),
- pytest.param("pwwkew", 3, id="pwwkew_example"),
- pytest.param("abcdef", 6, id="all_unique"),
- pytest.param("abcabcbbxyz", 4, id="long_tail_unique"),
- pytest.param("aab", 2, id="aab"),
- pytest.param("dvdf", 3, id="dvdf"),
- pytest.param(" ", 1, id="single_space"),
- pytest.param("a b c", 3, id="letters_and_spaces_unique"),
- pytest.param("a b a", 3, id="space_in_middle_with_repeat"),
- pytest.param("1234567890", 10, id="digits_all_unique"),
- pytest.param("112233", 2, id="repeating_digits"),
- pytest.param("abcdefghijklmnopqrstuvwxyz", 26, id="all_lowercase_letters"),
- pytest.param("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ", 63, id="max_unique_set"),
- pytest.param("a" * 10000, 1, id="ten_thousand_same"),
- pytest.param("abc" * 3333 + "d", 4, id="long_repeating_with_new_char"),
-])
+
+@pytest.mark.parametrize(
+ "s, expected",
+ [
+ pytest.param("", 0, id="empty_string"),
+ pytest.param("a", 1, id="single_char"),
+ pytest.param("aa", 1, id="two_same_chars"),
+ pytest.param("ab", 2, id="two_different_chars"),
+ pytest.param("abcabcbb", 3, id="classic_example_abc"),
+ pytest.param("bbbbb", 1, id="all_same"),
+ pytest.param("pwwkew", 3, id="pwwkew_example"),
+ pytest.param("abcdef", 6, id="all_unique"),
+ pytest.param("abcabcbbxyz", 4, id="long_tail_unique"),
+ pytest.param("aab", 2, id="aab"),
+ pytest.param("dvdf", 3, id="dvdf"),
+ pytest.param(" ", 1, id="single_space"),
+ pytest.param("a b c", 3, id="letters_and_spaces_unique"),
+ pytest.param("a b a", 3, id="space_in_middle_with_repeat"),
+ pytest.param("1234567890", 10, id="digits_all_unique"),
+ pytest.param("112233", 2, id="repeating_digits"),
+ pytest.param("abcdefghijklmnopqrstuvwxyz", 26, id="all_lowercase_letters"),
+ pytest.param(
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ",
+ 63,
+ id="max_unique_set",
+ ),
+ pytest.param("a" * 10000, 1, id="ten_thousand_same"),
+ pytest.param("abc" * 3333 + "d", 4, id="long_repeating_with_new_char"),
+ ],
+)
def test_get_len_of_longest_substring(s, expected):
assert get_len_of_longest_substring(s) == expected
-@pytest.mark.parametrize("nums, k, expected", [
- pytest.param([23, 2, 4, 6, 7], 6, True, id="subarray_2_4_sum_6"),
- pytest.param([23, 2, 6, 4, 7], 6, True, id="total_sum_42_div_by_6"),
- pytest.param([23, 2, 6, 4, 7], 13, False, id="no_valid_subarray"),
- pytest.param([0, 0], 1, True, id="two_zeros_any_k"),
- pytest.param([1, 0], 2, False, id="length_2_sum_1_not_div_by_2"),
- pytest.param([1, 2, 3], 5, True, id="subarray_2_3_sum_5"),
- pytest.param([1], 1, False, id="single_element_too_short"),
- pytest.param([5, 0, 0], 3, True, id="zeros_after_nonzero"),
- pytest.param([1, 2], 3, True, id="exact_sum_equals_k"),
- pytest.param([1, 2], 4, False, id="sum_not_divisible_by_k"),
- pytest.param([0], 1, False, id="single_zero_too_short"),
- pytest.param([1, 0, 2], 2, True, id="subarray_0_2_sum_2"),
- pytest.param([4, 2, 4], 6, True, id="first_two_sum_6"),
- pytest.param([1, 1, 1], 2, True, id="first_two_ones_sum_2"),
- pytest.param([1, 2, 4, 8], 8, False, id="no_subarray_divisible_by_8"),
- pytest.param([0, 1, 0], 2, False, id="zeros_with_one_sum_1"),
- pytest.param([0, 1, 0, 0], 2, True, id="last_two_zeros_sum_0_div_by_any"),
-])
+
+@pytest.mark.parametrize(
+ "nums, k, expected",
+ [
+ pytest.param([23, 2, 4, 6, 7], 6, True, id="subarray_2_4_sum_6"),
+ pytest.param([23, 2, 6, 4, 7], 6, True, id="total_sum_42_div_by_6"),
+ pytest.param([23, 2, 6, 4, 7], 13, False, id="no_valid_subarray"),
+ pytest.param([0, 0], 1, True, id="two_zeros_any_k"),
+ pytest.param([1, 0], 2, False, id="length_2_sum_1_not_div_by_2"),
+ pytest.param([1, 2, 3], 5, True, id="subarray_2_3_sum_5"),
+ pytest.param([1], 1, False, id="single_element_too_short"),
+ pytest.param([5, 0, 0], 3, True, id="zeros_after_nonzero"),
+ pytest.param([1, 2], 3, True, id="exact_sum_equals_k"),
+ pytest.param([1, 2], 4, False, id="sum_not_divisible_by_k"),
+ pytest.param([0], 1, False, id="single_zero_too_short"),
+ pytest.param([1, 0, 2], 2, True, id="subarray_0_2_sum_2"),
+ pytest.param([4, 2, 4], 6, True, id="first_two_sum_6"),
+ pytest.param([1, 1, 1], 2, True, id="first_two_ones_sum_2"),
+ pytest.param([1, 2, 4, 8], 8, False, id="no_subarray_divisible_by_8"),
+ pytest.param([0, 1, 0], 2, False, id="zeros_with_one_sum_1"),
+ pytest.param([0, 1, 0, 0], 2, True, id="last_two_zeros_sum_0_div_by_any"),
+ ],
+)
def test_is_there_any_good_subarray(nums, k, expected):
assert is_there_any_good_subarray(nums, k) == expected
-import pytest
-
-@pytest.mark.parametrize("text, expected", [
- pytest.param("", 0, id="empty_string"),
- pytest.param(" ", 0, id="only_spaces"),
- pytest.param("hello", 1, id="single_word"),
- pytest.param("Hello hello", 1, id="case_insensitive"),
- pytest.param("Hello, world!", 2, id="punctuation_around"),
- pytest.param("Hello, hello, world!", 2, id="duplicates_with_punct"),
- pytest.param("The quick brown fox jumps over the lazy dog.", 8, id="classic_pangram"),
- pytest.param("!!! ???", 0, id="only_punctuation"),
- pytest.param("word1 word2 word1", 2, id="digits_in_words"),
- pytest.param("Don't stop believing!", 3, id="apostrophe_inside"),
- pytest.param(" Hello , World ! ", 2, id="extra_whitespace"),
- pytest.param("A a A a", 1, id="repeated_case_variants"),
- pytest.param("word... word!!!", 1, id="multiple_punct_at_end"),
- pytest.param("123 456 123", 2, id="numbers_as_words"),
-])
+@pytest.mark.parametrize(
+ "text, expected",
+ [
+ pytest.param("", 0, id="empty_string"),
+ pytest.param(" ", 0, id="only_spaces"),
+ pytest.param("hello", 1, id="single_word"),
+ pytest.param("Hello hello", 1, id="case_insensitive"),
+ pytest.param("Hello, world!", 2, id="punctuation_around"),
+ pytest.param("Hello, hello, world!", 2, id="duplicates_with_punct"),
+ pytest.param("The quick brown fox jumps over the lazy dog.", 8, id="classic_pangram"),
+ pytest.param("!!! ???", 0, id="only_punctuation"),
+ pytest.param("word1 word2 word1", 2, id="digits_in_words"),
+ pytest.param("Don't stop believing!", 3, id="apostrophe_inside"),
+ pytest.param(" Hello , World ! ", 2, id="extra_whitespace"),
+ pytest.param("A a A a", 1, id="repeated_case_variants"),
+ pytest.param("word... word!!!", 1, id="multiple_punct_at_end"),
+ pytest.param("123 456 123", 2, id="numbers_as_words"),
+ ],
+)
def test_count_unique_words(text, expected):
- assert count_unique_words(text) == expected
\ No newline at end of file
+ assert count_unique_words(text) == expected
diff --git a/deprecated_tests/sem01/tests/test_lesson08_tasks.py b/deprecated_tests/sem01/tests/test_lesson08_tasks.py
index 962ba4bd2..06f04319d 100644
--- a/deprecated_tests/sem01/tests/test_lesson08_tasks.py
+++ b/deprecated_tests/sem01/tests/test_lesson08_tasks.py
@@ -1,10 +1,10 @@
-import pytest
import math
import time
from solutions.sem01.lesson08.task1 import make_averager
from solutions.sem01.lesson08.task2 import collect_statistic
+
def test_make_averager():
get_avg = make_averager(2)
@@ -15,6 +15,7 @@ def test_make_averager():
assert math.isclose(get_avg(5), 1)
assert math.isclose(get_avg(5), 5)
+
def test_make_averager2():
get_avg = make_averager(5)
@@ -27,6 +28,7 @@ def test_make_averager2():
assert math.isclose(get_avg(-7), 0)
assert math.isclose(get_avg(-2), -1)
+
def test_collect_statistic():
statistics: list[str, list[float, int]] = {}
@@ -37,7 +39,7 @@ def func1() -> None:
@collect_statistic(statistics)
def func2() -> None:
time.sleep(0.1)
-
+
for _ in range(3):
func1()
@@ -58,10 +60,11 @@ def test_collect_statistic_inout():
@collect_statistic(statistics)
def func(a, b, *, c, d):
return a + b + c + d
-
+
assert func(1, 2, c=3, d=4) == 10
assert statistics[func.__name__][1] == 1
+
def test_collect_statistic_count_call():
statistics: list[str, list[float, int]] = {}
@@ -76,7 +79,7 @@ def func():
count_call += 1
return func
-
+
func = func_fab()
func()
- assert statistics[func.__name__][1] == 1
\ No newline at end of file
+ assert statistics[func.__name__][1] == 1
diff --git a/deprecated_tests/sem01/tests/test_lesson11_tasks.py b/deprecated_tests/sem01/tests/test_lesson11_tasks.py
index d0cd02efc..941eed777 100644
--- a/deprecated_tests/sem01/tests/test_lesson11_tasks.py
+++ b/deprecated_tests/sem01/tests/test_lesson11_tasks.py
@@ -1,9 +1,8 @@
-import pytest
-
import math
import sys
from io import StringIO
+import pytest
from solutions.sem01.lesson11.task1 import Vector2D
@@ -84,13 +83,12 @@ def test_print():
sys.stdout = old_stdout
output = captured_output.getvalue()
assert (
- output == "Vector2D(abscissa=1, ordinate=-2)"
+ output == "Vector2D(abscissa=1, ordinate=-2)"
or output == "Vector2D(abscissa=1., ordinate=-2.)"
- or output == "Vector2D(abscissa=1.0, ordinate=-2.0)"
+ or output == "Vector2D(abscissa=1.0, ordinate=-2.0)"
)
-
@pytest.mark.parametrize(
"abscissa1, ordinate1, abscissa2, ordinate2, expected",
[
diff --git a/deprecated_tests/sem01/tests_hw/test_hw1_tasks.py b/deprecated_tests/sem01/tests_hw/test_hw1_tasks.py
index 0ecf8a108..c600f76d5 100644
--- a/deprecated_tests/sem01/tests_hw/test_hw1_tasks.py
+++ b/deprecated_tests/sem01/tests_hw/test_hw1_tasks.py
@@ -1,17 +1,15 @@
-import pytest
import uuid
-from unittest.mock import MagicMock, patch, Mock
+from unittest.mock import MagicMock, Mock, patch
+
+import pytest
-from homeworks.sem01.hw1.aggregate_segmentation import aggregate_segmentation, ALLOWED_TYPES
+from homeworks.sem01.hw1.aggregate_segmentation import ALLOWED_TYPES, aggregate_segmentation
from homeworks.sem01.hw1.backoff import backoff
from homeworks.sem01.hw1.cache import lru_cache
from homeworks.sem01.hw1.convert_exception import convert_exceptions_to_api_compitable_ones
-from .hw1_test_data.cache_test_data import (
- TESTCASE_DATA,
- TESTCASE_IDS,
-)
-NAME_BACKOFF_MODULE = "homeworks.hw1.backoff" # название модуля с backoff
+NAME_BACKOFF_MODULE = "homeworks.hw1.backoff" # название модуля с backoff
+
def test_valid_segments() -> None:
"""Тест: валидные сегменты."""
@@ -32,53 +30,53 @@ def test_valid_segments() -> None:
"segment_id": segment_id_1,
"segment_start": 0.0,
"segment_end": 1.0,
- "type": list_allow_types[0]
+ "type": list_allow_types[0],
},
{
"audio_id": audio_id_1,
"segment_id": segment_id_2,
"segment_start": 2.5,
"segment_end": 3.5,
- "type": list_allow_types[1]
+ "type": list_allow_types[1],
},
{
"audio_id": audio_id_2,
"segment_id": segment_id_3,
"segment_start": 4.5,
"segment_end": 4.6,
- "type": list_allow_types[0]
+ "type": list_allow_types[0],
},
{
"audio_id": audio_id_2,
"segment_id": segment_id_4,
"segment_start": 5.5,
"segment_end": 6.5,
- "type": list_allow_types[1]
+ "type": list_allow_types[1],
},
{
"audio_id": audio_id_3,
"segment_id": segment_id_5,
"segment_start": None,
"segment_end": None,
- "type": None
+ "type": None,
},
{
"audio_id": "audio3",
"segment_id": "seg5",
"segment_start": 0.0,
"segment_end": 1.0,
- "type": "invalid_type"
+ "type": "invalid_type",
},
]
expected_valid = {
audio_id_1: {
segment_id_1: {"start": 0.0, "end": 1.0, "type": list_allow_types[0]},
- segment_id_2: {"start": 2.5, "end": 3.5, "type": list_allow_types[1]}
+ segment_id_2: {"start": 2.5, "end": 3.5, "type": list_allow_types[1]},
},
audio_id_2: {
segment_id_3: {"start": 4.5, "end": 4.6, "type": list_allow_types[0]},
- segment_id_4: {"start": 5.5, "end": 6.5, "type": list_allow_types[1]}
+ segment_id_4: {"start": 5.5, "end": 6.5, "type": list_allow_types[1]},
},
audio_id_3: {},
}
@@ -88,6 +86,7 @@ def test_valid_segments() -> None:
assert result_valid == expected_valid
assert result_forbidden == expected_forbidden
+
def test_convert_matching_exception() -> None:
"""Тест: исключение заменяется на API-совместимое."""
@@ -97,7 +96,7 @@ class ApiValueError(Exception):
@convert_exceptions_to_api_compitable_ones({ValueError: ApiValueError})
def func():
raise ValueError("Внутренняя ошибка")
-
+
@convert_exceptions_to_api_compitable_ones({ValueError: ApiValueError})
def func2():
raise KeyError("Внутренняя ошибка")
@@ -108,7 +107,8 @@ def func2():
with pytest.raises(KeyError):
func2()
-@patch(NAME_BACKOFF_MODULE + '.sleep')
+
+@patch(NAME_BACKOFF_MODULE + ".sleep")
def test_exponential_backoff_and_jitter(mock_sleep: MagicMock) -> None:
"""Тест: задержки увеличиваются, но не выше timeout_max и к ним добавляется дрожь."""
attempts = 0
@@ -116,12 +116,7 @@ def test_exponential_backoff_and_jitter(mock_sleep: MagicMock) -> None:
retry_amount = 4
timeouts = [1, 2, 4, 4]
- @backoff(
- retry_amount=retry_amount,
- timeout_start=1,
- timeout_max=timeout_max,
- backoff_scale=2.0
- )
+ @backoff(retry_amount=retry_amount, timeout_start=1, timeout_max=timeout_max, backoff_scale=2.0)
def func():
nonlocal attempts
attempts += 1
@@ -138,22 +133,23 @@ def func():
for av_time, args in zip(timeouts, args_list):
count_more_av_time += args > av_time
assert av_time <= args <= av_time + 0.5
-
- assert count_more_av_time # есть добавление "дрожи"
+
+ assert count_more_av_time # есть добавление "дрожи"
+
def test_success() -> None:
capacity = 2
- call_args = [
+ call_args = [
(1, 2),
(1, 2),
(2, 2),
]
call_count_expected = 2
-
+
mock_func = Mock()
func_cached = lru_cache(capacity=capacity)(mock_func)
for args in call_args:
func_cached(args)
- assert mock_func.call_count == call_count_expected
\ No newline at end of file
+ assert mock_func.call_count == call_count_expected
diff --git a/deprecated_tests/sem02/tests/task4/test_lesson04_tasks.py b/deprecated_tests/sem02/tests/task4/test_lesson04_tasks.py
index 37d249b77..81312dea0 100644
--- a/deprecated_tests/sem02/tests/task4/test_lesson04_tasks.py
+++ b/deprecated_tests/sem02/tests/task4/test_lesson04_tasks.py
@@ -333,12 +333,8 @@ class TestTask2:
),
],
)
- def test_get_dominant_color_info(
- self, image, threshold, expected_color, expected_ratio
- ):
- color, ratio_percent = get_dominant_color_info(
- image.astype(np.uint8), threshold
- )
+ def test_get_dominant_color_info(self, image, threshold, expected_color, expected_ratio):
+ color, ratio_percent = get_dominant_color_info(image.astype(np.uint8), threshold)
assert color in expected_color
assert (abs(ratio_percent - expected_ratio * 100) < 1e-6) or (
diff --git a/deprecated_tests/sem02/tests/task5/test_lesson05_tasks.py b/deprecated_tests/sem02/tests/task5/test_lesson05_tasks.py
index aeb37ebcc..4cc9188d4 100644
--- a/deprecated_tests/sem02/tests/task5/test_lesson05_tasks.py
+++ b/deprecated_tests/sem02/tests/task5/test_lesson05_tasks.py
@@ -89,9 +89,7 @@ class TestTask1:
),
],
)
- def test_can_satisfy_demand(
- self, costs, resource_amounts, demand_expected, expected
- ):
+ def test_can_satisfy_demand(self, costs, resource_amounts, demand_expected, expected):
assert can_satisfy_demand(costs, resource_amounts, demand_expected) == expected
def test_can_satisfy_demand_validate(self):
@@ -172,9 +170,7 @@ class TestTask2:
),
],
)
- def test_get_projections_components(
- self, matrix, vector, proj_expected, orth_expected
- ):
+ def test_get_projections_components(self, matrix, vector, proj_expected, orth_expected):
projections, orthogonals = get_projections_components(matrix, vector)
if proj_expected is None:
diff --git a/homeworks/sem01/hw1/aggregate_segmentation.py b/homeworks/sem01/hw1/aggregate_segmentation.py
index 1cdc176af..80bbcfb4d 100644
--- a/homeworks/sem01/hw1/aggregate_segmentation.py
+++ b/homeworks/sem01/hw1/aggregate_segmentation.py
@@ -5,6 +5,29 @@
}
+def is_valid_segment(audio_segment):
+ segment_id = audio_segment.get("segment_id")
+ type_val = audio_segment.get("type")
+ start_val = audio_segment.get("segment_start")
+ end_val = audio_segment.get("segment_end")
+
+ if segment_id is None:
+ return False
+
+ if type_val is None and start_val is None and end_val is None:
+ return True
+
+ if not (
+ isinstance(type_val, str) and isinstance(start_val, float) and isinstance(end_val, float)
+ ):
+ return False
+
+ if type_val not in ALLOWED_TYPES:
+ 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 +47,52 @@ def aggregate_segmentation(
Список `audio_id` (str), которые требуют переразметки.
"""
- # ваш код
- return {}, []
+ result_dict = {}
+ wrong_audio = set()
+ segment_info = {}
+
+ for audio_segment in segmentation_data:
+ audio_id = audio_segment.get("audio_id")
+ segment_id = audio_segment.get("segment_id")
+
+ if audio_id is None:
+ continue
+
+ if not is_valid_segment(audio_segment):
+ wrong_audio.add(audio_id)
+ continue
+
+ key = (audio_id, segment_id)
+
+ curr_val = (
+ audio_segment.get("segment_start"),
+ audio_segment.get("segment_end"),
+ audio_segment.get("type"),
+ )
+
+ if key in segment_info:
+ if segment_info[key] != curr_val:
+ wrong_audio.add(audio_id)
+ else:
+ segment_info[key] = curr_val
+
+ for audio_segment in segmentation_data:
+ audio_id = audio_segment.get("audio_id")
+ segment_id = audio_segment.get("segment_id")
+ type_val = audio_segment.get("type")
+ start_val = audio_segment.get("segment_start")
+ end_val = audio_segment.get("segment_end")
+
+ if audio_id is None:
+ continue
+ if audio_id in wrong_audio:
+ continue
+
+ if audio_id not in result_dict:
+ result_dict[audio_id] = {}
+
+ if type_val is None and start_val is None and end_val is None:
+ continue
+
+ result_dict[audio_id][segment_id] = {"type": type_val, "start": start_val, "end": end_val}
+ return result_dict, list(wrong_audio)
diff --git a/homeworks/sem01/hw1/backoff.py b/homeworks/sem01/hw1/backoff.py
index 696ffa73a..f52f67bd5 100644
--- a/homeworks/sem01/hw1/backoff.py
+++ b/homeworks/sem01/hw1/backoff.py
@@ -10,6 +10,24 @@
R = TypeVar("R")
+def is_validate(retry_amount, timeout_start, timeout_max, backoff_scale):
+ check_type = (
+ isinstance(retry_amount, int)
+ and isinstance(timeout_start, (int, float))
+ and isinstance(timeout_max, (int, float))
+ and isinstance(backoff_scale, (int, float))
+ )
+
+ check_value = (
+ (1 <= retry_amount <= 100)
+ and (0 < timeout_start <= 10)
+ and (0 < timeout_max <= 10)
+ and (0 < backoff_scale <= 10)
+ )
+
+ return check_type and check_value
+
+
def backoff(
retry_amount: int = 3,
timeout_start: float = 0.5,
@@ -34,5 +52,33 @@ def backoff(
ValueError, если были переданы невозможные аргументы.
"""
- # ваш код
- pass
+ if not is_validate(retry_amount, timeout_start, timeout_max, backoff_scale):
+ raise ValueError
+
+ def decorator(func):
+ def wrapper(*args, **kwargs):
+ curr_delay = timeout_start
+ attempts = 0
+
+ while attempts <= retry_amount:
+ try:
+ return func(*args, **kwargs)
+ except Exception as exc:
+ if not any(isinstance(exc, trigger) for trigger in backoff_triggers):
+ raise exc from None
+
+ attempts += 1
+ if attempts > retry_amount:
+ raise exc from None
+
+ delay = min(curr_delay, timeout_max)
+ jitter_time = uniform(0, 0.5)
+ delay += jitter_time
+ sleep(delay)
+ curr_delay *= backoff_scale
+
+ raise
+
+ return wrapper
+
+ return decorator
diff --git a/homeworks/sem01/hw1/cache.py b/homeworks/sem01/hw1/cache.py
index 9eb1d5d2d..d8a7a84dd 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,35 @@ def lru_cache(capacity: int) -> Callable[[Callable[P, R]], Callable[P, R]]:
для получения целого числа.
ValueError, если после округления capacity - число, меньшее 1.
"""
- # ваш код
- pass
+ try:
+ max_size = round(capacity)
+ except TypeError:
+ raise TypeError
+ if max_size < 1:
+ raise ValueError
+
+ def decorator(func: Callable[P, R]) -> Callable[P, R]:
+ cache = dict()
+
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ key = (args, tuple(sorted(kwargs.items())))
+
+ if key in cache:
+ val = cache[key]
+ del cache[key]
+ cache[key] = val
+ return cache[key]
+
+ res = func(*args, **kwargs)
+ cache[key] = res
+
+ if len(cache) > max_size:
+ first_key = next(iter(cache))
+ del cache[first_key]
+
+ return res
+
+ return wrapper
+
+ return decorator
diff --git a/homeworks/sem01/hw1/convert_exception.py b/homeworks/sem01/hw1/convert_exception.py
index fe5c770fd..94de06988 100644
--- a/homeworks/sem01/hw1/convert_exception.py
+++ b/homeworks/sem01/hw1/convert_exception.py
@@ -24,5 +24,24 @@ def convert_exceptions_to_api_compitable_ones(
Декоратор для непосредственного использования.
"""
- # ваш код
- pass
+ def decorator(func):
+ def wrapper(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except Exception as exc:
+ exc_type = type(exc)
+
+ if exc_type in exception_to_api_exception:
+ api_exc = exception_to_api_exception.get(exc_type)
+
+ if isinstance(api_exc, type):
+ raise api_exc() from None
+ else:
+ raise api_exc from None
+
+ else:
+ raise
+
+ return wrapper
+
+ return decorator
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 000000000..443d0f088
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,82 @@
+numpy==2.4.2
+matplotlib==3.8.0
+pandas
+ipykernelasttokens==3.0.1
+colorama==0.4.6
+comm==0.2.3
+contourpy==1.3.3
+cycler==0.12.1
+debugpy==1.8.20
+decorator==5.2.1
+executing==2.2.1
+fonttools==4.61.1
+ipykernel==7.2.0
+ipython==9.10.0
+ipython_pygments_lexers==1.1.1
+jedi==0.19.2
+jupyter_client==8.8.0
+jupyter_core==5.9.1
+kiwisolver==1.4.9
+matplotlib==3.10.8
+matplotlib-inline==0.2.1
+nest-asyncio==1.6.0
+numpy==2.4.2
+packaging==26.0
+pandas==3.0.0
+parso==0.8.5
+pillow==12.1.0
+platformdirs==4.5.1
+prompt_toolkit==3.0.52
+psutil==7.2.2
+pure_eval==0.2.3
+Pygments==2.19.2
+pyparsing==3.3.2
+python-dateutil==2.9.0.post0
+pyzmq==27.1.0
+six==1.17.0
+stack-data==0.6.3
+tornado==6.5.4
+traitlets==5.14.3
+tzdata==2025.3
+wcwidth==0.6.0
+asttokens==3.0.1
+colorama==0.4.6
+comm==0.2.3
+contourpy==1.3.3
+cycler==0.12.1
+debugpy==1.8.20
+decorator==5.2.1
+executing==2.2.1
+fonttools==4.61.1
+ipykernel==7.2.0
+ipython==9.10.0
+ipython_pygments_lexers==1.1.1
+jedi==0.19.2
+jupyter_client==8.8.0
+jupyter_core==5.9.1
+kiwisolver==1.4.9
+matplotlib==3.10.8
+matplotlib-inline==0.2.1
+nest-asyncio==1.6.0
+numpy==2.4.2
+packaging==26.0
+pandas==3.0.0
+parso==0.8.5
+pillow==12.1.0
+platformdirs==4.5.1
+prompt_toolkit==3.0.52
+psutil==7.2.2
+pure_eval==0.2.3
+Pygments==2.19.2
+pyparsing==3.3.2
+python-dateutil==2.9.0.post0
+pyzmq==27.1.0
+six==1.17.0
+stack-data==0.6.3
+tornado==6.5.4
+traitlets==5.14.3
+tzdata==2025.3
+wcwidth==0.6.0
+pytest==8.4.2
+pytest-cov==7.0.0
+ruff==0.13.0
\ No newline at end of file
diff --git a/solutions/sem01/lesson02/task1.py b/solutions/sem01/lesson02/task1.py
index c782dcd88..bb484d934 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(1, num + 1):
+ factorial *= i
return factorial
diff --git a/solutions/sem01/lesson02/task2.py b/solutions/sem01/lesson02/task2.py
index b91420c56..4d68f6812 100644
--- a/solutions/sem01/lesson02/task2.py
+++ b/solutions/sem01/lesson02/task2.py
@@ -1,4 +1,7 @@
def get_doubled_factorial(num: int) -> int:
factorial = 1
- # ваш код
+ if num <= 1:
+ return 1
+ for i in range(num, 1, -2):
+ factorial *= i
return factorial
diff --git a/solutions/sem01/lesson02/task3.py b/solutions/sem01/lesson02/task3.py
index ee2a84ecf..1f29ccbd5 100644
--- a/solutions/sem01/lesson02/task3.py
+++ b/solutions/sem01/lesson02/task3.py
@@ -1,4 +1,10 @@
def get_amount_of_ways_to_climb(stair_amount: int) -> int:
step_prev, step_curr = 1, 1
- # ваш код
+ if stair_amount <= 1:
+ return 1
+
+ for i in range(2, stair_amount + 1):
+ time_step_curr = step_curr
+ step_curr = step_prev + step_curr
+ step_prev = time_step_curr
return step_curr
diff --git a/solutions/sem01/lesson02/task4.py b/solutions/sem01/lesson02/task4.py
index 45ff4bb42..29035caae 100644
--- a/solutions/sem01/lesson02/task4.py
+++ b/solutions/sem01/lesson02/task4.py
@@ -1,4 +1,12 @@
def get_multiplications_amount(num: int) -> int:
multiplications_amount = 0
- # ваш код
+ if num == 1:
+ return 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 8fb9a048d..a9f19c77f 100644
--- a/solutions/sem01/lesson02/task5.py
+++ b/solutions/sem01/lesson02/task5.py
@@ -1,3 +1,17 @@
def get_gcd(num1: int, num2: int) -> int:
- # ваш код
- return num1
+ if num1 > num2:
+ mx = num1
+ mn = num2
+ else:
+ mx = num2
+ mn = num1
+ balance = mx % mn
+
+ if balance == 0:
+ return mn
+
+ while balance != 0:
+ balance_old = balance
+ balance = mn % balance_old
+ if balance == 0:
+ return balance_old
diff --git a/solutions/sem01/lesson02/task6.py b/solutions/sem01/lesson02/task6.py
index bec4b6cd9..dfb4c4cda 100644
--- a/solutions/sem01/lesson02/task6.py
+++ b/solutions/sem01/lesson02/task6.py
@@ -1,4 +1,22 @@
+def is_prime(num):
+ if num == 2 or num == 3:
+ return True
+ if num <= 1 or num % 2 == 0:
+ return False
+ for i in range(3, int(num**0.5) + 1, 2):
+ print(num / i)
+ if num % i == 0:
+ return False
+ return True
+
+
def get_sum_of_prime_divisors(num: int) -> int:
sum_of_divisors = 0
- # ваш код
+ if num >= 2:
+ for i in range(2, int(num**0.5) + 1):
+ print(is_prime(num))
+ if num % i == 0 and is_prime(i):
+ sum_of_divisors += i
+ if is_prime(num):
+ sum_of_divisors += num
return sum_of_divisors
diff --git a/solutions/sem01/lesson02/task7.py b/solutions/sem01/lesson02/task7.py
index 4b2d73beb..05646b37b 100644
--- a/solutions/sem01/lesson02/task7.py
+++ b/solutions/sem01/lesson02/task7.py
@@ -1,5 +1,11 @@
def is_palindrome(num: int) -> bool:
- num_reversed = 0
- num_origin = num
- # ваш код
- return num_origin == num_reversed
+ pal = 0
+ old_num = num
+ if num < 0:
+ return False
+ if 0 <= num < 10:
+ return True
+ while num > 0:
+ pal = pal * 10 + num % 10
+ num //= 10
+ return pal == old_num
diff --git a/solutions/sem01/lesson03/task1.py b/solutions/sem01/lesson03/task1.py
index f1d8fe26b..d7fdb5ddc 100644
--- a/solutions/sem01/lesson03/task1.py
+++ b/solutions/sem01/lesson03/task1.py
@@ -1,3 +1,5 @@
def flip_bits_in_range(num: int, left_bit: int, right_bit: int) -> int:
- # ваш код
- return num
\ No newline at end of file
+ for i in range(left_bit, right_bit + 1):
+ mask = 1 << (i - 1)
+ num = num ^ mask
+ return num
diff --git a/solutions/sem01/lesson03/task2.py b/solutions/sem01/lesson03/task2.py
index a3a738c2a..a3ea7c271 100644
--- a/solutions/sem01/lesson03/task2.py
+++ b/solutions/sem01/lesson03/task2.py
@@ -1,3 +1,29 @@
def get_cube_root(n: float, eps: float) -> float:
- # ваш код
- return n
\ No newline at end of file
+ if n == 0:
+ return 0.0
+
+ if n > 0:
+ left = 0.0
+ if n > 1:
+ right = n
+ else:
+ right = 1.0
+
+ else:
+ right = 0.0
+ if n < -1:
+ left = n
+ else:
+ left = -1.0
+
+ ave = (right + left) / 2
+ ave_cube = ave * ave * ave
+
+ while abs(ave_cube - n) >= eps:
+ if ave_cube > n:
+ right = ave
+ else:
+ left = ave
+ ave = (right + left) / 2
+ ave_cube = ave * ave * ave
+ return (right + left) / 2
diff --git a/solutions/sem01/lesson03/task3.py b/solutions/sem01/lesson03/task3.py
index 5e91a6ac5..c10f3d6b7 100644
--- a/solutions/sem01/lesson03/task3.py
+++ b/solutions/sem01/lesson03/task3.py
@@ -1,3 +1,22 @@
def get_nth_digit(num: int) -> int:
- # ваш код
- return 0
+ len = 1
+ count = 5
+ start = 0
+
+ while num > len * count:
+ num -= len * count
+ len += 1
+ if len == 2:
+ count = 45
+ start = 10
+ else:
+ count *= 10
+ start *= 10
+
+ num_ind = (num - 1) // len
+ dig_ind = (num - 1) % len
+ numb = start + num_ind * 2
+
+ pos = len - 1 - dig_ind
+ digit = (numb // (10**pos)) % 10
+ return digit
diff --git a/solutions/sem01/lesson04/task1.py b/solutions/sem01/lesson04/task1.py
index 47384423a..85e7ab0bc 100644
--- a/solutions/sem01/lesson04/task1.py
+++ b/solutions/sem01/lesson04/task1.py
@@ -1,3 +1,7 @@
def is_arithmetic_progression(lst: list[list[int]]) -> bool:
- # ваш код
- return False
\ No newline at end of file
+ if len(lst) <= 2:
+ return True
+ lst = sorted(lst)
+ if all((lst[i] - lst[i - 1]) == (lst[i + 1] - lst[i]) for i in range(1, len(lst) - 1)):
+ return True
+ return False
diff --git a/solutions/sem01/lesson04/task2.py b/solutions/sem01/lesson04/task2.py
index 4591d0a3e..0c8ee2a6b 100644
--- a/solutions/sem01/lesson04/task2.py
+++ b/solutions/sem01/lesson04/task2.py
@@ -1,3 +1,18 @@
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()
+ sublist = intervals[0]
+ new_list = []
+
+ for i in range(1, len(intervals)):
+ if sublist[1] >= intervals[i][0]:
+ sublist = [sublist[0], max(sublist[1], intervals[i][1])]
+
+ else:
+ new_list.append(sublist)
+ sublist = intervals[i]
+
+ new_list.append(sublist)
+ return new_list
diff --git a/solutions/sem01/lesson04/task3.py b/solutions/sem01/lesson04/task3.py
index 7253f6cbd..028efaf46 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
+ res = 0
+ for i in nums:
+ res ^= i
+ return res
diff --git a/solutions/sem01/lesson04/task4.py b/solutions/sem01/lesson04/task4.py
index b21bc5a39..d45fc2864 100644
--- a/solutions/sem01/lesson04/task4.py
+++ b/solutions/sem01/lesson04/task4.py
@@ -1,3 +1,14 @@
def move_zeros_to_end(nums: list[int]) -> list[int]:
- # ваш код
- return 0
\ No newline at end of file
+ if all(nums[i] == 0 for i in range(len(nums))):
+ return 0
+ if all(nums[i] != 0 for i in range(len(nums))):
+ return len(nums)
+ divisors_lst = list()
+ zero_lst = list()
+ for i in range(len(nums)):
+ if nums[i] == 0:
+ zero_lst.append(nums[i])
+ if nums[i] != 0:
+ divisors_lst.append(nums[i])
+ nums[:] = divisors_lst + zero_lst
+ return nums.index(0)
diff --git a/solutions/sem01/lesson04/task5.py b/solutions/sem01/lesson04/task5.py
index 02d7742bb..745992164 100644
--- a/solutions/sem01/lesson04/task5.py
+++ b/solutions/sem01/lesson04/task5.py
@@ -1,3 +1,21 @@
def find_row_with_most_ones(matrix: list[list[int]]) -> int:
- # ваш код
- return 0
\ No newline at end of file
+ if matrix == []:
+ return 0
+
+ max_one = 0
+ index = 0
+
+ for i in range(len(matrix)):
+ sub_matrix = matrix[i]
+ count_one = 0
+
+ for j in range(len(sub_matrix) - 1, -1, -1):
+ if sub_matrix[j] == 1:
+ count_one += 1
+ else:
+ break
+
+ if count_one > max_one:
+ max_one = count_one
+ index = i
+ return index
diff --git a/solutions/sem01/lesson04/task6.py b/solutions/sem01/lesson04/task6.py
index 16df27ca6..df25f493e 100644
--- a/solutions/sem01/lesson04/task6.py
+++ b/solutions/sem01/lesson04/task6.py
@@ -1,3 +1,11 @@
-def count_cycles(arr: list[int]) -> int:
- # ваш код
- return 0
\ No newline at end of file
+def count_cycles(arr: list[int]) -> int:
+ visited = [0] * len(arr)
+ cycles = 0
+ for i in range(len(arr)):
+ if not visited[i]:
+ curr = i
+ while not visited[curr]:
+ visited[curr] = 1
+ curr = arr[curr]
+ cycles += 1
+ return cycles
diff --git a/solutions/sem01/lesson05/task1.py b/solutions/sem01/lesson05/task1.py
index 9a17211e5..8d94d0acb 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 367503802..15dd6f7ee 100644
--- a/solutions/sem01/lesson05/task2.py
+++ b/solutions/sem01/lesson05/task2.py
@@ -1,3 +1,15 @@
def are_anagrams(word1: str, word2: str) -> bool:
- # ваш код
- return False
\ No newline at end of file
+ if len(word1) != len(word2):
+ return False
+
+ char_count = [0] * 256
+
+ for char in word1:
+ char_count[ord(char)] += 1
+
+ for char in word2:
+ char_count[ord(char)] -= 1
+ if char_count[ord(char)] < 0:
+ return False
+
+ return all(count == 0 for count in char_count)
diff --git a/solutions/sem01/lesson05/task3.py b/solutions/sem01/lesson05/task3.py
index e368e2f49..7c5687db0 100644
--- a/solutions/sem01/lesson05/task3.py
+++ b/solutions/sem01/lesson05/task3.py
@@ -1,3 +1,10 @@
def is_punctuation(text: str) -> bool:
- # ваш код
- return False
+ if text == "":
+ return False
+ str1 = '!"#$%&'
+ str2 = "'()*+,-./:;<=>?@[\\]^_{|}~`"
+ str = str1 + str2
+ if all(i in str for i in text):
+ return True
+ else:
+ return False
diff --git a/solutions/sem01/lesson05/task4.py b/solutions/sem01/lesson05/task4.py
index 4c4e9086e..effc737d9 100644
--- a/solutions/sem01/lesson05/task4.py
+++ b/solutions/sem01/lesson05/task4.py
@@ -1,3 +1,11 @@
def unzip(compress_text: str) -> str:
- # ваш код
- return compress_text
\ No newline at end of file
+ compress_text_split = compress_text.split()
+ lst = []
+ for sub_str in compress_text_split:
+ if "*" in sub_str:
+ zvezd_index = sub_str.find("*")
+ lst.append(sub_str[:zvezd_index:] * int(sub_str[zvezd_index + 1 : :]))
+ else:
+ lst.append(sub_str)
+ compress_text = "".join(lst)
+ return compress_text
diff --git a/solutions/sem01/lesson05/task5.py b/solutions/sem01/lesson05/task5.py
index 076c5bb6c..de8f25eb5 100644
--- a/solutions/sem01/lesson05/task5.py
+++ b/solutions/sem01/lesson05/task5.py
@@ -1,3 +1,33 @@
-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:
+ i, j = 0, 0
+ while i < len(reg_expr) and j < len(text):
+ reg_literal = reg_expr[i]
+
+ if reg_literal == "d":
+ if not text[j].isdigit():
+ return False
+ while j < len(text) and text[j].isdigit():
+ j += 1
+ i += 1
+
+ elif reg_literal == "w":
+ if not text[j].isalpha():
+ return False
+ while j < len(text) and text[j].isalpha():
+ j += 1
+ i += 1
+
+ elif reg_literal == "s":
+ if not text[j].isalnum():
+ return False
+ while j < len(text) and text[j].isalnum():
+ j += 1
+ i += 1
+
+ else:
+ if j >= len(text) or text[j] != reg_literal:
+ return False
+ j += 1
+ i += 1
+
+ return i == len(reg_expr) and j == len(text)
diff --git a/solutions/sem01/lesson05/task6.py b/solutions/sem01/lesson05/task6.py
index 1b914ada7..2d223b955 100644
--- a/solutions/sem01/lesson05/task6.py
+++ b/solutions/sem01/lesson05/task6.py
@@ -1,3 +1,19 @@
def simplify_path(path: str) -> str:
- # ваш код
- return path
\ No newline at end of file
+ sub_path = path.split("/")
+ way = []
+
+ for i in sub_path:
+ if i == "" or i == ".":
+ continue
+ if i == "..":
+ if len(way) > 0:
+ way.pop()
+ else:
+ return ""
+ continue
+ way.append(i)
+ if not way:
+ return "/"
+
+ res = "/" + "/".join(way)
+ return res
diff --git a/solutions/sem01/lesson06/task1.py b/solutions/sem01/lesson06/task1.py
index 2d1e30e96..ea48d99a1 100644
--- a/solutions/sem01/lesson06/task1.py
+++ b/solutions/sem01/lesson06/task1.py
@@ -1,3 +1,23 @@
def int_to_roman(num: int) -> str:
- # ваш код
- return ""
\ No newline at end of file
+ rim_digits = {
+ 1000: "M",
+ 900: "CM",
+ 500: "D",
+ 400: "CD",
+ 100: "C",
+ 90: "XC",
+ 50: "L",
+ 40: "XL",
+ 10: "X",
+ 9: "IX",
+ 5: "V",
+ 4: "IV",
+ 1: "I",
+ }
+ res = []
+ for i in rim_digits:
+ while num >= i:
+ num -= i
+ res.append(rim_digits.get(i))
+
+ return "".join(res)
diff --git a/solutions/sem01/lesson06/task2.py b/solutions/sem01/lesson06/task2.py
index f535b5a0c..741458fc2 100644
--- a/solutions/sem01/lesson06/task2.py
+++ b/solutions/sem01/lesson06/task2.py
@@ -1,3 +1,19 @@
def get_len_of_longest_substring(text: str) -> int:
- # ваш код
- return 0
\ No newline at end of file
+ if not text:
+ return 0
+
+ result = []
+ sub_str = []
+
+ for i in range(len(text)):
+ if text[i] not in sub_str:
+ sub_str.append(text[i])
+ else:
+ result.append(sub_str)
+ dupl = sub_str.index(text[i])
+ sub_str = sub_str[dupl + 1 :]
+ sub_str.append(text[i])
+
+ result.append(sub_str)
+ longest = max(result, key=len)
+ return len(longest)
diff --git a/solutions/sem01/lesson06/task3.py b/solutions/sem01/lesson06/task3.py
index 7449a1e72..2ebc13680 100644
--- a/solutions/sem01/lesson06/task3.py
+++ b/solutions/sem01/lesson06/task3.py
@@ -2,6 +2,13 @@ def is_there_any_good_subarray(
nums: list[int],
k: int,
) -> bool:
-
- # ваш код
+ dictionary = {0: -1}
+ curr = 0
+ for i in range(len(nums)):
+ curr = (curr + nums[i]) % k
+ if curr in dictionary:
+ if i - dictionary[curr] >= 2:
+ return True
+ else:
+ dictionary[curr] = i
return False
diff --git a/solutions/sem01/lesson06/task4.py b/solutions/sem01/lesson06/task4.py
index 5b75a110c..e3668af2f 100644
--- a/solutions/sem01/lesson06/task4.py
+++ b/solutions/sem01/lesson06/task4.py
@@ -1,3 +1,11 @@
def count_unique_words(text: str) -> int:
- # ваш код
- return 0
\ No newline at end of file
+ if len(text) == 0:
+ return 0
+ text = text.lower()
+ for i in text:
+ if i.isalpha() or i == " " or i.isdigit():
+ continue
+ else:
+ text = text.replace(i, "")
+ res = set(text.split())
+ return len(res)
diff --git a/solutions/sem01/lesson08/task1.py b/solutions/sem01/lesson08/task1.py
index 4390f6c84..6f9252b5d 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
+ history_money = []
+
+ def get_avg(profit):
+ history_money.append(profit)
+ if len(history_money) > accumulation_period:
+ history_money.pop(0)
+ return sum(history_money) / len(history_money)
+
+ return get_avg
diff --git a/solutions/sem01/lesson08/task2.py b/solutions/sem01/lesson08/task2.py
index 6e4af8707..d6d460578 100644
--- a/solutions/sem01/lesson08/task2.py
+++ b/solutions/sem01/lesson08/task2.py
@@ -1,10 +1,26 @@
+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) -> Callable[[T], T]:
+ def timeit(func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ time_start = time.time()
+ result = func(*args, **kwargs)
+ times = time.time() - time_start
+ func_name = func.__name__
+ if func_name in statistics:
+ curr_avg, call_count = statistics[func_name]
+ avg_new_time = (curr_avg * call_count + times) / (call_count + 1)
+ statistics[func_name] = [avg_new_time, call_count + 1]
+ else:
+ statistics[func_name] = [times, 1]
+ return result
+
+ return wrapper
+
+ return timeit
diff --git a/solutions/sem01/lesson11/task1.py b/solutions/sem01/lesson11/task1.py
index 6a15f31fb..b572bf295 100644
--- a/solutions/sem01/lesson11/task1.py
+++ b/solutions/sem01/lesson11/task1.py
@@ -1,10 +1,148 @@
+import math
+from numbers import Real
+
+
class Vector2D:
+ def __init__(self, abscissa=0.0, ordinate=0.0):
+ self._abscissa = float(abscissa)
+ self._ordinate = float(ordinate)
+
+ @property
+ def abscissa(self) -> float:
+ return self._abscissa
+
+ @property
+ def ordinate(self) -> float:
+ return self._ordinate
+
+ def __repr__(self):
+ return f"Vector2D(abscissa={self._abscissa}, ordinate={self._ordinate})"
+
+ def __eq__(self, other: "Vector2D") -> bool:
+ if not isinstance(other, Vector2D):
+ return NotImplemented
+ return math.isclose(self._abscissa, other._abscissa) and math.isclose(
+ self._ordinate, other._ordinate
+ )
+
+ def __ne__(self, other: "Vector2D") -> bool:
+ if not isinstance(other, Vector2D):
+ return NotImplemented
+ return not self.__eq__(other)
+
+ def __gt__(self, other: "Vector2D") -> bool:
+ if not isinstance(other, Vector2D):
+ return NotImplemented
+
+ if self.__eq__(other):
+ return False
+
+ if not math.isclose(self._abscissa, other._abscissa):
+ return self._abscissa > other._abscissa
+
+ return self._ordinate > other._ordinate
+
+ def __lt__(self, other: "Vector2D") -> bool:
+ if not isinstance(other, Vector2D):
+ return NotImplemented
+
+ if self.__eq__(other):
+ return False
+
+ if not math.isclose(self._abscissa, other._abscissa):
+ return self._abscissa < other._abscissa
+
+ return self._ordinate < other._ordinate
+
+ def __ge__(self, other: "Vector2D") -> bool:
+ if not isinstance(other, Vector2D):
+ return NotImplemented
+ return self.__eq__(other) or self.__gt__(other)
+
+ def __le__(self, other: "Vector2D") -> bool:
+ if not isinstance(other, Vector2D):
+ return NotImplemented
+ return self.__eq__(other) or self.__lt__(other)
+
+ def __abs__(self) -> float:
+ return math.sqrt(self._abscissa**2 + self._ordinate**2)
+
+ def __bool__(self) -> bool:
+ return not (
+ math.isclose(self._abscissa, 0, abs_tol=1e-14)
+ and math.isclose(self._ordinate, 0, abs_tol=1e-14)
+ )
+
+ def __mul__(self, numb: Real) -> "Vector2D":
+ if not isinstance(numb, Real):
+ return NotImplemented
+
+ return Vector2D(self._abscissa * numb, self._ordinate * numb)
+
+ def __rmul__(self, numb: Real) -> "Vector2D":
+ return self.__mul__(numb)
+
+ def __truediv__(self, numb: Real) -> "Vector2D":
+ if not isinstance(numb, Real):
+ return NotImplemented
+
+ return Vector2D(self._abscissa * (1 / numb), self._ordinate * (1 / numb))
+
+ def __add__(self, other: "Vector2D | Real") -> "Vector2D":
+ if isinstance(other, Real):
+ return Vector2D(self._abscissa + other, self._ordinate + other)
+ elif isinstance(other, Vector2D):
+ return Vector2D(self._abscissa + other._abscissa, self._ordinate + other._ordinate)
+ else:
+ return NotImplemented
+
+ def __radd__(self, other: "Vector2D | Real") -> "Vector2D":
+ return self.__add__(other)
+
+ def __sub__(self, other: "Vector2D | Real") -> "Vector2D":
+ if isinstance(other, Real):
+ return Vector2D(self._abscissa - other, self._ordinate - other)
+ elif isinstance(other, Vector2D):
+ return Vector2D(self._abscissa - other._abscissa, self._ordinate - other._ordinate)
+ else:
+ return NotImplemented
+
+ def __neg__(self) -> "Vector2D":
+ return Vector2D(-self._abscissa, -self._ordinate)
+
+ def __int__(self) -> int:
+ return int(abs(self))
+
+ def __float__(self) -> float:
+ return float(abs(self))
+
+ def __complex__(self):
+ return complex(real=self._abscissa, imag=self._ordinate)
+
+ def __matmul__(self, other: "Vector2D") -> float:
+ if not isinstance(other, Vector2D):
+ return NotImplemented
+ scalar = self._abscissa * other._abscissa + self._ordinate * other._ordinate
+ return scalar
+
+ def __rmatmul__(self, other: "Vector2D") -> float:
+ if not isinstance(other, Vector2D):
+ return NotImplemented
+ return self @ other
+
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 (self._abscissa == 0 and self._ordinate == 0) or (
+ other._abscissa == 0 and other._ordinate == 0
+ ):
+ raise ValueError("Расчет угла между данным вектором и нулевым вектором невозможен")
- # ваш код
+ cos_angle = (self @ other) / (abs(self) * abs(other))
+ cos_angle = max(-1.0, min(1.0, cos_angle))
+ angle = math.acos(cos_angle)
+ return angle
diff --git a/solutions/sem01/lesson12/task1.py b/solutions/sem01/lesson12/task1.py
index d1bb828c1..144fcee2f 100644
--- a/solutions/sem01/lesson12/task1.py
+++ b/solutions/sem01/lesson12/task1.py
@@ -1,6 +1,20 @@
from typing import Any, Generator, Iterable
-def chunked(iterable: Iterable, size: int) -> Generator[tuple[Any], None, None]:
- # ваш код
- ...
+def chunked(iterable: Iterable[Any], size: int) -> Generator[tuple[Any, ...], None, None]:
+ iterator = iter(iterable)
+
+ while True:
+ chunk = []
+
+ for _ in range(size):
+ try:
+ element = next(iterator)
+ chunk.append(element)
+ except StopIteration:
+ break
+
+ if chunk:
+ yield tuple(chunk)
+ else:
+ break
diff --git a/solutions/sem01/lesson12/task2.py b/solutions/sem01/lesson12/task2.py
index 3ad802ee7..921423d7f 100644
--- a/solutions/sem01/lesson12/task2.py
+++ b/solutions/sem01/lesson12/task2.py
@@ -2,5 +2,23 @@
def circle(iterable: Iterable) -> Generator[Any, None, None]:
- # ваш код
- ...
+ iterator = iter(iterable)
+ cache = []
+ i = 0
+ while True:
+ if i < len(cache):
+ yield cache[i]
+
+ else:
+ try:
+ elem = next(iterator)
+ cache.append(elem)
+ yield cache[i]
+
+ except StopIteration:
+ try:
+ yield cache[i % len(cache)]
+
+ except ZeroDivisionError:
+ return 0
+ i += 1
diff --git a/solutions/sem01/lesson12/task3.py b/solutions/sem01/lesson12/task3.py
index 64c112ccc..814bb7fa2 100644
--- a/solutions/sem01/lesson12/task3.py
+++ b/solutions/sem01/lesson12/task3.py
@@ -6,7 +6,22 @@ def __init__(
self,
path_to_file: str,
) -> None:
- # ваш код
- ...
+ self.file_path = path_to_file
+ self.file = None
+ self.old_stdout = None
- # ваш код
+ def __enter__(self):
+ self.old_stdout = sys.stdout
+ self.file = open(self.file_path, "w")
+ sys.stdout = self.file
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ sys.stdout = self.old_stdout
+
+ if self.file:
+ try:
+ self.file.close()
+ except Exception:
+ pass
+ return False
diff --git a/solutions/sem02/lesson03/task1.py b/solutions/sem02/lesson03/task1.py
index 2c3fc0b58..ca499b621 100644
--- a/solutions/sem02/lesson03/task1.py
+++ b/solutions/sem02/lesson03/task1.py
@@ -8,13 +8,23 @@ class ShapeMismatchError(Exception):
def sum_arrays_vectorized(
lhs: np.ndarray,
rhs: np.ndarray,
-) -> np.ndarray: ...
+) -> np.ndarray:
+ if lhs.size != rhs.size:
+ raise ShapeMismatchError
+ return np.add(lhs, rhs, out=lhs)
-def compute_poly_vectorized(abscissa: np.ndarray) -> np.ndarray: ...
+
+def compute_poly_vectorized(abscissa: np.ndarray) -> np.ndarray:
+ return 3 * (abscissa**2) + 2 * abscissa + 1
def get_mutual_l2_distances_vectorized(
lhs: np.ndarray,
rhs: np.ndarray,
-) -> np.ndarray: ...
+) -> np.ndarray:
+ if lhs.shape[1] != rhs.shape[1]:
+ raise ShapeMismatchError
+
+ tenz = lhs[:, np.newaxis, :] - rhs[np.newaxis, :, :]
+ return np.sqrt(np.sum(tenz**2, axis=2))
diff --git a/solutions/sem02/lesson03/task2.py b/solutions/sem02/lesson03/task2.py
index fc823c1d6..0477b301c 100644
--- a/solutions/sem02/lesson03/task2.py
+++ b/solutions/sem02/lesson03/task2.py
@@ -9,11 +9,27 @@ 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 (distances.shape == azimuth.shape == inclination.shape):
+ raise ShapeMismatchError
+
+ x = distances * np.sin(inclination) * np.cos(azimuth)
+ y = distances * np.sin(inclination) * np.sin(azimuth)
+ z = distances * np.cos(inclination)
+ return x, y, z
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 (abscissa.shape == ordinates.shape == applicates.shape):
+ raise ShapeMismatchError
+
+ dist = np.sqrt(abscissa**2 + ordinates**2)
+
+ distances = np.sqrt(abscissa**2 + ordinates**2 + applicates**2)
+ azimuth = np.arctan2(ordinates, abscissa)
+ inclination = np.arctan2(dist, applicates)
+ return distances, azimuth, inclination
diff --git a/solutions/sem02/lesson03/task3.py b/solutions/sem02/lesson03/task3.py
index 477acd0ce..f633ea23e 100644
--- a/solutions/sem02/lesson03/task3.py
+++ b/solutions/sem02/lesson03/task3.py
@@ -3,4 +3,13 @@
def get_extremum_indices(
ordinates: np.ndarray,
-) -> tuple[np.ndarray, np.ndarray]: ...
+) -> tuple[np.ndarray, np.ndarray]:
+ if ordinates.size < 3:
+ raise ValueError
+
+ indexes = np.arange(len(ordinates))
+
+ mask_max = (ordinates[1:-1] > ordinates[:-2]) & (ordinates[1:-1] > ordinates[2:])
+ mask_min = (ordinates[1:-1] < ordinates[:-2]) & (ordinates[1:-1] < ordinates[2:])
+
+ return indexes[1:-1][mask_min], indexes[1:-1][mask_max]
diff --git a/solutions/sem02/lesson04/task1.py b/solutions/sem02/lesson04/task1.py
index 1b5526c1f..430880197 100644
--- a/solutions/sem02/lesson04/task1.py
+++ b/solutions/sem02/lesson04/task1.py
@@ -2,16 +2,66 @@
def pad_image(image: np.ndarray, pad_size: int) -> np.ndarray:
- # ваш код
- return image
+ if pad_size < 1:
+ raise ValueError
+
+ if image.ndim == 2:
+ height = image.shape[0]
+ lenght = image.shape[1]
+
+ with_padding = np.zeros((height + 2 * pad_size, lenght + 2 * pad_size), dtype=np.uint8)
+ with_padding[pad_size : height + pad_size, pad_size : lenght + pad_size] = image
+
+ elif image.ndim == 3:
+ height = image.shape[0]
+ lenght = image.shape[1]
+ width = image.shape[2]
+
+ with_padding = np.zeros(
+ (height + 2 * pad_size, lenght + 2 * pad_size, width), dtype=np.uint8
+ )
+ with_padding[pad_size : height + pad_size, pad_size : lenght + pad_size, :] = image
+
+ return with_padding
def blur_image(
image: np.ndarray,
kernel_size: int,
) -> np.ndarray:
- # ваш код
- return image
+ if kernel_size % 2 == 0 or kernel_size < 1:
+ raise ValueError
+
+ if kernel_size == 1:
+ return image
+
+ if image.ndim == 2:
+ height = image.shape[0]
+ lenght = image.shape[1]
+ answer = np.zeros((height, lenght), dtype=image.dtype)
+
+ new_image = pad_image(image, kernel_size // 2)
+
+ for i in range(height):
+ for j in range(lenght):
+ window = new_image[i : i + kernel_size, j : j + kernel_size]
+ answer[i, j] = int(np.mean(window))
+
+ return answer
+
+ elif image.ndim == 3:
+ height, lenght, width = image.shape[0], image.shape[1], image.shape[2]
+ answer = np.zeros((height, lenght, width), dtype=np.uint8)
+
+ new_image = pad_image(image, kernel_size // 2)
+
+ for i in range(height):
+ for j in range(lenght):
+ for k in range(width):
+ window = new_image[i : i + kernel_size, j : j + kernel_size, k]
+ answer[i, j, k] = int(np.mean(window))
+
+ return answer
if __name__ == "__main__":
diff --git a/solutions/sem02/lesson04/task2.py b/solutions/sem02/lesson04/task2.py
index be9a2288f..1ac7cbe9b 100644
--- a/solutions/sem02/lesson04/task2.py
+++ b/solutions/sem02/lesson04/task2.py
@@ -5,6 +5,35 @@ def get_dominant_color_info(
image: np.ndarray[np.uint8],
threshold: int = 5,
) -> tuple[np.uint8, float]:
- # ваш код
+ if threshold < 1:
+ raise ValueError("threshold must be positive")
- return 0, 0
+ counts = np.zeros(256, dtype=int)
+ for pixel in image.ravel():
+ counts[pixel] += 1
+
+ res_color = 0
+ max_count = 0
+
+ for i in range(256):
+ if counts[i] == 0:
+ continue
+
+ left = max(0, i - threshold + 1)
+ right = min(255, i + threshold - 1)
+ current_sum = 0
+
+ for j in range(left, right + 1):
+ current_sum += counts[j]
+
+ if current_sum > max_count:
+ max_count = current_sum
+ res_color = i
+
+ elif current_sum == max_count:
+ if counts[i] > counts[res_color]:
+ res_color = i
+
+ all_pixels = image.shape[0] * image.shape[1]
+
+ return np.uint8(res_color), float((max_count / all_pixels) * 100)
diff --git a/solutions/sem02/lesson05/task1.py b/solutions/sem02/lesson05/task1.py
index e9c7c3c56..dd114e523 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.shape[0] != resource_amounts.shape[0] or costs.shape[1] != demand_expected.shape[0]:
+ raise ShapeMismatchError
+
+ costs_demand_expected = np.multiply(costs, demand_expected)
+ resource_demand_expected = costs_demand_expected.sum(axis=1)
+ answer = resource_demand_expected <= resource_amounts
+
+ return np.all(answer)
diff --git a/solutions/sem02/lesson05/task2.py b/solutions/sem02/lesson05/task2.py
index be1fb9d2b..91f6c3c57 100644
--- a/solutions/sem02/lesson05/task2.py
+++ b/solutions/sem02/lesson05/task2.py
@@ -8,4 +8,16 @@ 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]:
+ if matrix.shape[0] != matrix.shape[1] or matrix.shape[1] != vector.shape[0]:
+ raise ShapeMismatchError
+
+ if np.linalg.slogdet(matrix)[0] == 0:
+ return None, None
+
+ scalar_prod = matrix @ vector
+ module_sqrt = np.sum(matrix**2, axis=1)
+ scalar_projection = scalar_prod / module_sqrt
+ projection = scalar_projection[:, np.newaxis] * matrix
+
+ return projection, vector - projection
diff --git a/solutions/sem02/lesson05/task3.py b/solutions/sem02/lesson05/task3.py
index 0c66906cb..913f8b70e 100644
--- a/solutions/sem02/lesson05/task3.py
+++ b/solutions/sem02/lesson05/task3.py
@@ -9,4 +9,18 @@ def adaptive_filter(
Vs: np.ndarray,
Vj: np.ndarray,
diag_A: np.ndarray,
-) -> np.ndarray: ...
+) -> np.ndarray:
+ M, N = Vs.shape
+ Mj, K = Vj.shape
+
+ if M != Mj or K != len(diag_A):
+ raise ShapeMismatchError
+
+ Vj_H = (Vj.real - 1j * Vj.imag).T
+
+ staples = np.eye(K) + (Vj_H @ Vj) * diag_A
+ staples_inv = np.linalg.inv(staples)
+
+ right_prod = Vj_H @ Vs
+
+ return Vs - Vj @ (staples_inv @ right_prod)
diff --git a/solutions/sem02/lesson07/medic_hist.png b/solutions/sem02/lesson07/medic_hist.png
new file mode 100644
index 000000000..a432dd288
Binary files /dev/null and b/solutions/sem02/lesson07/medic_hist.png differ
diff --git a/solutions/sem02/lesson07/task1.py b/solutions/sem02/lesson07/task1.py
index 3a505d89b..81f5fbd01 100644
--- a/solutions/sem02/lesson07/task1.py
+++ b/solutions/sem02/lesson07/task1.py
@@ -3,26 +3,97 @@
import matplotlib.pyplot as plt
import numpy as np
+plt.style.use("ggplot")
+
class ShapeMismatchError(Exception):
pass
+def apply_custom_style(ax):
+ ax.set_facecolor("#F0F0F0")
+ ax.grid(True, color="#6E6E6E", linestyle="-", linewidth=0.5)
+ ax.set_axisbelow(True)
+
+
+def draw_hist(fig, grid, labels, colors):
+ ax = fig.add_subplot(grid[:-1, 1:])
+ apply_custom_style(ax)
+ ax.hist(abscissa, bins=50, alpha=0.5, label=labels[0], color=colors[0])
+ ax.hist(ordinates, bins=50, alpha=0.5, label=labels[1], color=colors[1])
+ ax.set_title("Гистограмма")
+ ax.legend()
+
+
+def draw_violin(fig, grid, labels, colors):
+ ax = fig.add_subplot(grid[:-1, 0])
+ apply_custom_style(ax)
+ violin_parts = ax.violinplot([abscissa, ordinates], vert=True, showmedians=True)
+
+ for i, body in enumerate(violin_parts["bodies"]):
+ body.set_facecolor(colors[i])
+ body.set_edgecolor(colors[i])
+ body.set_alpha(0.6)
+
+ for part_name in violin_parts:
+ if part_name != "bodies":
+ violin_parts[part_name].set_edgecolor("black")
+ violin_parts[part_name].set_linewidth(1.5)
+
+ violin_parts["cmedians"].set_linewidth(2.5)
+ ax.set_xticks([1, 2])
+ ax.set_xticklabels(labels)
+ ax.set_title("Скрипичная диаграмма")
+
+
+def draw_box(fig, grid, labels, colors):
+ ax = fig.add_subplot(grid[-1, 1:])
+ apply_custom_style(ax)
+ box_parts = ax.boxplot(
+ [abscissa, ordinates], labels=labels, vert=False, patch_artist=True, notch=True
+ )
+
+ for patch, color in zip(box_parts["boxes"], colors):
+ patch.set_facecolor(color)
+ patch.set_alpha(0.7)
+ ax.set_title("Ящик с усами")
+
+
def visualize_diagrams(
abscissa: np.ndarray,
ordinates: np.ndarray,
diagram_type: Any,
) -> None:
- # ваш код
- pass
+ if abscissa.shape != ordinates.shape:
+ raise ShapeMismatchError
+
+ if diagram_type not in ["hist", "violin", "box", "all"]:
+ raise ValueError
+
+ colors = ["#0A29C2", "#EAC90F"]
+ labels = ["X data", "Y data"]
+ space = 0.4
+
+ fig = plt.figure(figsize=(12, 10))
+ grid = plt.GridSpec(4, 4, wspace=space, hspace=2 * space, height_ratios=[1, 1, 1, 1.5])
+
+ types_to_draw = ["hist", "violin", "box"] if diagram_type == "all" else [diagram_type]
+
+ for d_type in types_to_draw:
+ if d_type == "hist":
+ draw_hist(fig, grid, labels, colors)
+
+ if d_type == "violin":
+ draw_violin(fig, grid, labels, colors)
+
+ if d_type == "box":
+ draw_box(fig, grid, labels, colors)
if __name__ == "__main__":
mean = [2, 3]
cov = [[1, 1], [1, 2]]
- space = 0.2
-
abscissa, ordinates = np.random.multivariate_normal(mean, cov, size=1000).T
- visualize_diagrams(abscissa, ordinates, "hist")
+ visualize_diagrams(abscissa, ordinates, "all")
plt.show()
diff --git a/solutions/sem02/lesson07/task2.py b/solutions/sem02/lesson07/task2.py
index decd607ef..47632d548 100644
--- a/solutions/sem02/lesson07/task2.py
+++ b/solutions/sem02/lesson07/task2.py
@@ -1 +1,51 @@
-# ваш код (используйте функции или классы для решения данной задачи)
+import json
+
+import matplotlib.pyplot as plt
+import numpy as np
+
+plt.style.use("ggplot")
+
+
+def apply_custom_style(ax):
+ ax.set_facecolor("#F0F0F0")
+ ax.grid(True, color="#A5A5A51B", linestyle="-", linewidth=0.5)
+ ax.set_axisbelow(True)
+
+
+def draw_mitral_diagram(ax: plt.Axes, categories: list[str], before: list[int], after: list[int]):
+ x = np.arange(len(categories))
+ width = 0.4
+ colors = ["#F772C6", "#1CEED2", "#080808"]
+ labels = ["До установки импланта", "После установки импланта"]
+ apply_custom_style(ax)
+
+ column1 = ax.bar(x - width / 2, before, width, label=labels[0], color=colors[0])
+ column2 = ax.bar(x + width / 2, after, width, label=labels[1], color=colors[1])
+
+ ax.set_title("Эффективность импланта при митральной недостаточности")
+ ax.set_ylabel("Количество пациентов", color=colors[2])
+ ax.set_xticks(x)
+ ax.set_xticklabels(categories)
+ ax.legend()
+
+ ax.bar_label(column1)
+ ax.bar_label(column2)
+
+
+def visualize_medic_data(f_path: str):
+ with open(f_path, "r") as f:
+ data = json.load(f)
+
+ deg_mitral_reg = ["I", "II", "III", "IV"]
+ before_impl_ins = [data["before"].count(i) for i in deg_mitral_reg]
+ after_impl_ins = [data["after"].count(i) for i in deg_mitral_reg]
+
+ fig, ax = plt.subplots(figsize=(10, 6))
+ draw_mitral_diagram(ax, deg_mitral_reg, before_impl_ins, after_impl_ins)
+
+ fig.savefig("solutions/sem02/lesson07/medic_hist.png", bbox_inches="tight")
+ plt.show()
+
+
+if __name__ == "__main__":
+ visualize_medic_data("solutions/sem02/lesson07/data/medic_data.json")
diff --git a/solutions/sem02/lesson08/labyrinth.gif b/solutions/sem02/lesson08/labyrinth.gif
new file mode 100644
index 000000000..3a6696b08
Binary files /dev/null and b/solutions/sem02/lesson08/labyrinth.gif differ
diff --git a/solutions/sem02/lesson08/loaded_labyrinth.gif b/solutions/sem02/lesson08/loaded_labyrinth.gif
new file mode 100644
index 000000000..2e03b7c97
Binary files /dev/null and b/solutions/sem02/lesson08/loaded_labyrinth.gif differ
diff --git a/solutions/sem02/lesson08/modulated_signal.gif b/solutions/sem02/lesson08/modulated_signal.gif
new file mode 100644
index 000000000..e5ff770da
Binary files /dev/null and b/solutions/sem02/lesson08/modulated_signal.gif differ
diff --git a/solutions/sem02/lesson08/task1.py b/solutions/sem02/lesson08/task1.py
index 89f88572f..53ecac015 100644
--- a/solutions/sem02/lesson08/task1.py
+++ b/solutions/sem02/lesson08/task1.py
@@ -1,35 +1,60 @@
-from functools import partial
-
import matplotlib.pyplot as plt
import numpy as np
-
from IPython.display import HTML
from matplotlib.animation import FuncAnimation
def create_modulation_animation(
- modulation,
- fc,
- num_frames,
- plot_duration,
- time_step=0.001,
- animation_step=0.01,
- save_path=""
+ modulation, fc, num_frames, plot_duration, time_step=0.001, animation_step=0.01, save_path=""
) -> FuncAnimation:
- # ваш код
- return FuncAnimation()
+ fig, ax = plt.subplots()
+ (line,) = ax.plot([], [], lw=1, color="#058D29")
+
+ ax.set_xlim(0, plot_duration)
+ ax.set_ylim(-1.5, 1.5)
+ ax.set_xlabel("Время (с)")
+ ax.set_ylabel("Амплитуда")
+ ax.set_title("Амплитудная модуляция" if modulation else "Несущий сигнал")
+ ax.grid(True)
+
+ def update(frame):
+ start_time = frame * animation_step
+ end_time = start_time + plot_duration
+
+ t = np.arange(start_time, end_time, time_step)
+ carrier = np.sin(2 * np.pi * fc * t)
+
+ if modulation is not None:
+ m_t = modulation(t)
+ signal = m_t * carrier
+ else:
+ signal = carrier
+
+ line.set_data(t, signal)
+ ax.set_xlim(start_time, end_time)
+
+ return (line,)
+
+ anim = FuncAnimation(fig, update, frames=num_frames, interval=50, blit=True)
+
+ if save_path:
+ anim.save(save_path, writer="pillow")
+
+ plt.close(fig)
+ return anim
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
- save_path_with_modulation = "modulated_signal.gif"
+ num_frames = 100
+ plot_duration = np.pi / 2
+ time_step = 0.001
+ animation_step = np.pi / 200
+ fc = 50
+ save_path_with_modulation = "solutions/sem02/lesson08/modulated_signal.gif"
animation = create_modulation_animation(
modulation=modulation_function,
@@ -38,6 +63,6 @@ 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
+ HTML(animation.to_jshtml())
diff --git a/solutions/sem02/lesson08/task2.py b/solutions/sem02/lesson08/task2.py
index b677c0702..0f75990f5 100644
--- a/solutions/sem02/lesson08/task2.py
+++ b/solutions/sem02/lesson08/task2.py
@@ -1,53 +1,120 @@
-from functools import partial
-
import matplotlib.pyplot as plt
import numpy as np
-
from IPython.display import HTML
from matplotlib.animation import FuncAnimation
+def animate_wave_algorithm(
+ maze: np.ndarray, start: tuple[int, int], end: tuple[int, int], save_path: str = ""
+) -> FuncAnimation:
+ rows, cols = maze.shape
+ grid = maze.copy()
+ grid[:] = -1
+ grid[start] = 0
+ current = 0
+ found = False
+ frames = []
+ frames.append(grid.copy())
+
+ while np.any(current == grid):
+ front = current == grid
+ if grid[end] != -1:
+ found = True
+ break
+
+ neighbors = np.zeros(shape=front.shape, dtype=front.dtype)
+ neighbors[1:, :] |= front[:-1, :]
+ neighbors[:-1, :] |= front[1:, :]
+ neighbors[:, 1:] |= front[:, :-1]
+ neighbors[:, :-1] |= front[:, 1:]
+
+ new_point = neighbors & (maze == 1) & (grid == -1)
+
+ grid[new_point] = current + 1
+ frames.append(grid.copy())
+
+ current += 1
+
+ if not found:
+ print("Пути не существует")
+ return 0
+
+ fig, ax = plt.subplots(figsize=(rows, cols))
+
+ def prepare_data(data):
+ display = data.astype(float)
+ display[maze == 0] = -10
+ display[(maze == 1) & (data == -1)] = -5
+ return display
+
+ im = ax.imshow(prepare_data(frames[0]), cmap="viridis")
+
+ ax.set_xticks(np.arange(-0.5, cols, 1), minor=True)
+ ax.set_yticks(np.arange(-0.5, rows, 1), minor=True)
+ ax.grid(which="minor", color="#FFF200FF", linestyle="-", linewidth=0.5)
+
+ text_objects = [
+ [
+ ax.text(j, i, "", ha="center", va="center", fontsize=12, fontweight="bold")
+ for j in range(cols)
+ ]
+ for i in range(rows)
+ ]
+
+ def update(frame_idx):
+ data = frames[frame_idx]
+ im.set_array(prepare_data(data))
+
+ for i in range(rows):
+ for j in range(cols):
+ val = data[i, j]
+ if val >= 0:
+ text_objects[i][j].set_text(str(val))
+ text_objects[i][j].set_color("black")
+ else:
+ text_objects[i][j].set_text("")
+ return [im]
+
+ ani = FuncAnimation(fig, update, frames=len(frames), interval=150, blit=False)
+
+ if save_path:
+ ani.save(save_path, writer="pillow")
+
+ # plt.show()
+ return ani
-def animate_wave_algorithm(
- 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)
- save_path = "labyrinth.gif" # Укажите путь для сохранения анимации
+ save_path = "solutions/sem02/lesson08/labyrinth.gif" # Укажите путь для сохранения анимации
animation = animate_wave_algorithm(maze, start, end, save_path)
HTML(animation.to_jshtml())
-
+
# Пример 2
-
- maze_path = "./data/maze.npy"
+
+ maze_path = "solutions/sem02/lesson08/data/maze.npy"
loaded_maze = np.load(maze_path)
# можете поменять, если захотите запустить из других точек
start = (2, 0)
end = (5, 0)
- loaded_save_path = "loaded_labyrinth.gif"
+ loaded_save_path = "solutions/sem02/lesson08/loaded_labyrinth.gif"
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..78e9f27da 100644
--- a/solutions/sem02/lesson10/task1.ipynb
+++ b/solutions/sem02/lesson10/task1.ipynb
@@ -34,14 +34,167 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 293,
"id": "d7b00711",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " survived | \n",
+ " pclass | \n",
+ " sex | \n",
+ " age | \n",
+ " sibsp | \n",
+ " parch | \n",
+ " fare | \n",
+ " embarked | \n",
+ " class | \n",
+ " who | \n",
+ " adult_male | \n",
+ " deck | \n",
+ " embark_town | \n",
+ " alive | \n",
+ " alone | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 133 | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " female | \n",
+ " 29.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 26.0000 | \n",
+ " S | \n",
+ " Second | \n",
+ " woman | \n",
+ " False | \n",
+ " NaN | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 519 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 32.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.8958 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " NaN | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 499 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 24.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.7958 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " NaN | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 568 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " NaN | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.2292 | \n",
+ " C | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " NaN | \n",
+ " Cherbourg | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 484 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " male | \n",
+ " 25.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 91.0792 | \n",
+ " C | \n",
+ " First | \n",
+ " man | \n",
+ " True | \n",
+ " B | \n",
+ " Cherbourg | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " survived pclass sex age sibsp parch fare embarked class \\\n",
+ "133 1 2 female 29.0 1 0 26.0000 S Second \n",
+ "519 0 3 male 32.0 0 0 7.8958 S Third \n",
+ "499 0 3 male 24.0 0 0 7.7958 S Third \n",
+ "568 0 3 male NaN 0 0 7.2292 C Third \n",
+ "484 1 1 male 25.0 1 0 91.0792 C First \n",
+ "\n",
+ " who adult_male deck embark_town alive alone \n",
+ "133 woman False NaN Southampton yes False \n",
+ "519 man True NaN Southampton no True \n",
+ "499 man True NaN Southampton no True \n",
+ "568 man True NaN Cherbourg no True \n",
+ "484 man True B Cherbourg yes False "
+ ]
+ },
+ "execution_count": 293,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"import seaborn as sns\n",
"\n",
- "\n",
"titanic_data = sns.load_dataset(\"titanic\")\n",
"titanic_data.sample(5)"
]
@@ -66,12 +219,89 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "cd2f1773",
+ "execution_count": 294,
+ "id": "0b59361c",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " survived | \n",
+ " pclass | \n",
+ " sex | \n",
+ " age | \n",
+ " sibsp | \n",
+ " parch | \n",
+ " fare | \n",
+ " embarked | \n",
+ " class | \n",
+ " who | \n",
+ " adult_male | \n",
+ " deck | \n",
+ " embark_town | \n",
+ " alive | \n",
+ " alone | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 177 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 688 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " survived pclass sex age sibsp parch fare embarked class who \\\n",
+ "0 0 0 0 177 0 0 0 2 0 0 \n",
+ "\n",
+ " adult_male deck embark_town alive alone \n",
+ "0 0 688 2 0 0 "
+ ]
+ },
+ "execution_count": 294,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# ваш код"
+ "from pandas import isna\n",
+ "\n",
+ "amount_missed_td = isna(titanic_data).sum(axis=\"rows\").to_frame()\n",
+ "amount_missed_td.T"
]
},
{
@@ -88,12 +318,659 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "7e458447",
+ "execution_count": 295,
+ "id": "2f933706",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Numbers of rows: 891\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " survived | \n",
+ " pclass | \n",
+ " sex | \n",
+ " age | \n",
+ " sibsp | \n",
+ " parch | \n",
+ " fare | \n",
+ " embarked | \n",
+ " class | \n",
+ " who | \n",
+ " adult_male | \n",
+ " embark_town | \n",
+ " alive | \n",
+ " alone | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 22.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 7.2500 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 38.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 71.2833 | \n",
+ " C | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Cherbourg | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " female | \n",
+ " 26.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.9250 | \n",
+ " S | \n",
+ " Third | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 35.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 53.1000 | \n",
+ " S | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 35.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 8.0500 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 886 | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " male | \n",
+ " 27.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 13.0000 | \n",
+ " S | \n",
+ " Second | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 887 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 19.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30.0000 | \n",
+ " S | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 888 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " female | \n",
+ " NaN | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 23.4500 | \n",
+ " S | \n",
+ " Third | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " no | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 889 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " male | \n",
+ " 26.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30.0000 | \n",
+ " C | \n",
+ " First | \n",
+ " man | \n",
+ " True | \n",
+ " Cherbourg | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 890 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 32.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.7500 | \n",
+ " Q | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Queenstown | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
891 rows × 14 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " survived pclass sex age sibsp parch fare embarked class \\\n",
+ "0 0 3 male 22.0 1 0 7.2500 S Third \n",
+ "1 1 1 female 38.0 1 0 71.2833 C First \n",
+ "2 1 3 female 26.0 0 0 7.9250 S Third \n",
+ "3 1 1 female 35.0 1 0 53.1000 S First \n",
+ "4 0 3 male 35.0 0 0 8.0500 S Third \n",
+ ".. ... ... ... ... ... ... ... ... ... \n",
+ "886 0 2 male 27.0 0 0 13.0000 S Second \n",
+ "887 1 1 female 19.0 0 0 30.0000 S First \n",
+ "888 0 3 female NaN 1 2 23.4500 S Third \n",
+ "889 1 1 male 26.0 0 0 30.0000 C First \n",
+ "890 0 3 male 32.0 0 0 7.7500 Q Third \n",
+ "\n",
+ " who adult_male embark_town alive alone \n",
+ "0 man True Southampton no False \n",
+ "1 woman False Cherbourg yes False \n",
+ "2 woman False Southampton yes True \n",
+ "3 woman False Southampton yes False \n",
+ "4 man True Southampton no True \n",
+ ".. ... ... ... ... ... \n",
+ "886 man True Southampton no True \n",
+ "887 woman False Southampton yes True \n",
+ "888 woman False Southampton no False \n",
+ "889 man True Cherbourg yes True \n",
+ "890 man True Queenstown no True \n",
+ "\n",
+ "[891 rows x 14 columns]"
+ ]
+ },
+ "execution_count": 295,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "len_rows = len(titanic_data)\n",
+ "col_without_nan_td = titanic_data.dropna(axis=\"columns\", thresh=len_rows / 2)\n",
+ "print(f\"Numbers of rows: {len_rows}\")\n",
+ "col_without_nan_td"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 296,
+ "id": "52dbd9ff",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Numbers of columns: 14\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " survived | \n",
+ " pclass | \n",
+ " sex | \n",
+ " age | \n",
+ " sibsp | \n",
+ " parch | \n",
+ " fare | \n",
+ " embarked | \n",
+ " class | \n",
+ " who | \n",
+ " adult_male | \n",
+ " embark_town | \n",
+ " alive | \n",
+ " alone | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 22.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 7.2500 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 38.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 71.2833 | \n",
+ " C | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Cherbourg | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " female | \n",
+ " 26.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.9250 | \n",
+ " S | \n",
+ " Third | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 35.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 53.1000 | \n",
+ " S | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 35.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 8.0500 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 886 | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " male | \n",
+ " 27.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 13.0000 | \n",
+ " S | \n",
+ " Second | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 887 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 19.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30.0000 | \n",
+ " S | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 888 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " female | \n",
+ " NaN | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 23.4500 | \n",
+ " S | \n",
+ " Third | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " no | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 889 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " male | \n",
+ " 26.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30.0000 | \n",
+ " C | \n",
+ " First | \n",
+ " man | \n",
+ " True | \n",
+ " Cherbourg | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 890 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 32.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.7500 | \n",
+ " Q | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Queenstown | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
891 rows × 14 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " survived pclass sex age sibsp parch fare embarked class \\\n",
+ "0 0 3 male 22.0 1 0 7.2500 S Third \n",
+ "1 1 1 female 38.0 1 0 71.2833 C First \n",
+ "2 1 3 female 26.0 0 0 7.9250 S Third \n",
+ "3 1 1 female 35.0 1 0 53.1000 S First \n",
+ "4 0 3 male 35.0 0 0 8.0500 S Third \n",
+ ".. ... ... ... ... ... ... ... ... ... \n",
+ "886 0 2 male 27.0 0 0 13.0000 S Second \n",
+ "887 1 1 female 19.0 0 0 30.0000 S First \n",
+ "888 0 3 female NaN 1 2 23.4500 S Third \n",
+ "889 1 1 male 26.0 0 0 30.0000 C First \n",
+ "890 0 3 male 32.0 0 0 7.7500 Q Third \n",
+ "\n",
+ " who adult_male embark_town alive alone \n",
+ "0 man True Southampton no False \n",
+ "1 woman False Cherbourg yes False \n",
+ "2 woman False Southampton yes True \n",
+ "3 woman False Southampton yes False \n",
+ "4 man True Southampton no True \n",
+ ".. ... ... ... ... ... \n",
+ "886 man True Southampton no True \n",
+ "887 woman False Southampton yes True \n",
+ "888 woman False Southampton no False \n",
+ "889 man True Cherbourg yes True \n",
+ "890 man True Queenstown no True \n",
+ "\n",
+ "[891 rows x 14 columns]"
+ ]
+ },
+ "execution_count": 296,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "len_columns = len(col_without_nan_td.columns)\n",
+ "rows_without_nan_td = col_without_nan_td.dropna(axis=\"rows\", thresh=len_columns / 2)\n",
+ "print(f\"Numbers of columns: {len_columns}\")\n",
+ "rows_without_nan_td"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 297,
+ "id": "f5f4fdbf",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " survived | \n",
+ " pclass | \n",
+ " sex | \n",
+ " age | \n",
+ " sibsp | \n",
+ " parch | \n",
+ " fare | \n",
+ " embarked | \n",
+ " class | \n",
+ " who | \n",
+ " adult_male | \n",
+ " embark_town | \n",
+ " alive | \n",
+ " alone | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 177 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " survived pclass sex age sibsp parch fare embarked class who \\\n",
+ "0 0 0 0 177 0 0 0 2 0 0 \n",
+ "\n",
+ " adult_male embark_town alive alone \n",
+ "0 0 2 0 0 "
+ ]
+ },
+ "execution_count": 297,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# ваш код"
+ "from pandas import isna\n",
+ "\n",
+ "titanic_data = rows_without_nan_td\n",
+ "\n",
+ "amount_missed_td = isna(titanic_data).sum(axis=\"rows\").to_frame()\n",
+ "amount_missed_td.T"
]
},
{
@@ -111,12 +988,302 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "f7db5e99",
+ "execution_count": 298,
+ "id": "42e4e723",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Average age of men: 33\n",
+ "Average age of women: 32 \n",
+ "Average age of children: 6\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " survived | \n",
+ " pclass | \n",
+ " sex | \n",
+ " age | \n",
+ " sibsp | \n",
+ " parch | \n",
+ " fare | \n",
+ " embarked | \n",
+ " class | \n",
+ " who | \n",
+ " adult_male | \n",
+ " embark_town | \n",
+ " alive | \n",
+ " alone | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 22.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 7.2500 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 38.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 71.2833 | \n",
+ " C | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Cherbourg | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " female | \n",
+ " 26.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.9250 | \n",
+ " S | \n",
+ " Third | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 35.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 53.1000 | \n",
+ " S | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 35.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 8.0500 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 886 | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " male | \n",
+ " 27.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 13.0000 | \n",
+ " S | \n",
+ " Second | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 887 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 19.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30.0000 | \n",
+ " S | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 888 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " female | \n",
+ " 32.0 | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 23.4500 | \n",
+ " S | \n",
+ " Third | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " no | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 889 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " male | \n",
+ " 26.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30.0000 | \n",
+ " C | \n",
+ " First | \n",
+ " man | \n",
+ " True | \n",
+ " Cherbourg | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 890 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 32.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.7500 | \n",
+ " Q | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Queenstown | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
891 rows × 14 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " survived pclass sex age sibsp parch fare embarked class \\\n",
+ "0 0 3 male 22.0 1 0 7.2500 S Third \n",
+ "1 1 1 female 38.0 1 0 71.2833 C First \n",
+ "2 1 3 female 26.0 0 0 7.9250 S Third \n",
+ "3 1 1 female 35.0 1 0 53.1000 S First \n",
+ "4 0 3 male 35.0 0 0 8.0500 S Third \n",
+ ".. ... ... ... ... ... ... ... ... ... \n",
+ "886 0 2 male 27.0 0 0 13.0000 S Second \n",
+ "887 1 1 female 19.0 0 0 30.0000 S First \n",
+ "888 0 3 female 32.0 1 2 23.4500 S Third \n",
+ "889 1 1 male 26.0 0 0 30.0000 C First \n",
+ "890 0 3 male 32.0 0 0 7.7500 Q Third \n",
+ "\n",
+ " who adult_male embark_town alive alone \n",
+ "0 man True Southampton no False \n",
+ "1 woman False Cherbourg yes False \n",
+ "2 woman False Southampton yes True \n",
+ "3 woman False Southampton yes False \n",
+ "4 man True Southampton no True \n",
+ ".. ... ... ... ... ... \n",
+ "886 man True Southampton no True \n",
+ "887 woman False Southampton yes True \n",
+ "888 woman False Southampton no False \n",
+ "889 man True Cherbourg yes True \n",
+ "890 man True Queenstown no True \n",
+ "\n",
+ "[891 rows x 14 columns]"
+ ]
+ },
+ "execution_count": 298,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# ваш код"
+ "man_td = titanic_data[titanic_data[\"who\"] == \"man\"]\n",
+ "woman_td = titanic_data[titanic_data[\"who\"] == \"woman\"]\n",
+ "child_td = titanic_data[titanic_data[\"who\"] == \"child\"]\n",
+ "\n",
+ "avg_age_man_td = round(man_td[\"age\"].mean())\n",
+ "avg_age_woman_td = round(woman_td[\"age\"].mean())\n",
+ "avg_age_child_td = round(child_td[\"age\"].mean())\n",
+ "\n",
+ "avg_age_td = {\"man\": avg_age_man_td, \"woman\": avg_age_woman_td, \"child\": avg_age_child_td}\n",
+ "\n",
+ "\n",
+ "titanic_data[\"age\"] = titanic_data[\"age\"].fillna(titanic_data[\"who\"].map(avg_age_td))\n",
+ "print(\n",
+ " f\"Average age of men: {avg_age_man_td}\\nAverage age of women: {avg_age_woman_td}\\\n",
+ " \\nAverage age of children: {avg_age_child_td}\"\n",
+ ")\n",
+ "titanic_data"
]
},
{
@@ -131,12 +1298,290 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "67a0c6bc",
+ "execution_count": 299,
+ "id": "924ca3ef",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Numbers of rows: 891\n",
+ "Numbers of rows after clear: 889\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " survived | \n",
+ " pclass | \n",
+ " sex | \n",
+ " age | \n",
+ " sibsp | \n",
+ " parch | \n",
+ " fare | \n",
+ " embarked | \n",
+ " class | \n",
+ " who | \n",
+ " adult_male | \n",
+ " embark_town | \n",
+ " alive | \n",
+ " alone | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 22.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 7.2500 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 38.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 71.2833 | \n",
+ " C | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Cherbourg | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 2 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " female | \n",
+ " 26.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.9250 | \n",
+ " S | \n",
+ " Third | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 3 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 35.0 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 53.1000 | \n",
+ " S | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 4 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 35.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 8.0500 | \n",
+ " S | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " | 886 | \n",
+ " 0 | \n",
+ " 2 | \n",
+ " male | \n",
+ " 27.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 13.0000 | \n",
+ " S | \n",
+ " Second | \n",
+ " man | \n",
+ " True | \n",
+ " Southampton | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 887 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " female | \n",
+ " 19.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30.0000 | \n",
+ " S | \n",
+ " First | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 888 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " female | \n",
+ " 32.0 | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 23.4500 | \n",
+ " S | \n",
+ " Third | \n",
+ " woman | \n",
+ " False | \n",
+ " Southampton | \n",
+ " no | \n",
+ " False | \n",
+ "
\n",
+ " \n",
+ " | 889 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " male | \n",
+ " 26.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30.0000 | \n",
+ " C | \n",
+ " First | \n",
+ " man | \n",
+ " True | \n",
+ " Cherbourg | \n",
+ " yes | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ " | 890 | \n",
+ " 0 | \n",
+ " 3 | \n",
+ " male | \n",
+ " 32.0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 7.7500 | \n",
+ " Q | \n",
+ " Third | \n",
+ " man | \n",
+ " True | \n",
+ " Queenstown | \n",
+ " no | \n",
+ " True | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
889 rows × 14 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " survived pclass sex age sibsp parch fare embarked class \\\n",
+ "0 0 3 male 22.0 1 0 7.2500 S Third \n",
+ "1 1 1 female 38.0 1 0 71.2833 C First \n",
+ "2 1 3 female 26.0 0 0 7.9250 S Third \n",
+ "3 1 1 female 35.0 1 0 53.1000 S First \n",
+ "4 0 3 male 35.0 0 0 8.0500 S Third \n",
+ ".. ... ... ... ... ... ... ... ... ... \n",
+ "886 0 2 male 27.0 0 0 13.0000 S Second \n",
+ "887 1 1 female 19.0 0 0 30.0000 S First \n",
+ "888 0 3 female 32.0 1 2 23.4500 S Third \n",
+ "889 1 1 male 26.0 0 0 30.0000 C First \n",
+ "890 0 3 male 32.0 0 0 7.7500 Q Third \n",
+ "\n",
+ " who adult_male embark_town alive alone \n",
+ "0 man True Southampton no False \n",
+ "1 woman False Cherbourg yes False \n",
+ "2 woman False Southampton yes True \n",
+ "3 woman False Southampton yes False \n",
+ "4 man True Southampton no True \n",
+ ".. ... ... ... ... ... \n",
+ "886 man True Southampton no True \n",
+ "887 woman False Southampton yes True \n",
+ "888 woman False Southampton no False \n",
+ "889 man True Cherbourg yes True \n",
+ "890 man True Queenstown no True \n",
+ "\n",
+ "[889 rows x 14 columns]"
+ ]
+ },
+ "execution_count": 299,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# ваш код"
+ "len_columns = len(titanic_data.columns)\n",
+ "clear_rows_td = titanic_data.dropna(axis=\"rows\", thresh=len_columns - 1)\n",
+ "print(f\"Numbers of rows: {len(titanic_data)}\")\n",
+ "print(f\"Numbers of rows after clear: {len(clear_rows_td)}\")\n",
+ "titanic_data = clear_rows_td\n",
+ "titanic_data"
]
},
{
@@ -151,12 +1596,42 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "6a2d0ae9",
+ "execution_count": 300,
+ "id": "a1ccba52",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "['Southampton', 'Cherbourg', 'Queenstown']\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "'Southampton'"
+ ]
+ },
+ "execution_count": 300,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# ваш код"
+ "towns_td = list(titanic_data[\"embark_town\"].unique())\n",
+ "print(towns_td)\n",
+ "\n",
+ "south_amount_td = (titanic_data[\"embark_town\"] == \"Southampton\").sum()\n",
+ "cherb_amount_td = (titanic_data[\"embark_town\"] == \"Cherbourg\").sum()\n",
+ "queen_amount_td = (titanic_data[\"embark_town\"] == \"Queenstown\").sum()\n",
+ "\n",
+ "passagers = {\n",
+ " \"Southampton\": south_amount_td,\n",
+ " \"Cherbourg\": cherb_amount_td,\n",
+ " \"Queenstown\": queen_amount_td,\n",
+ "}\n",
+ "max(passagers)"
]
},
{
@@ -171,12 +1646,22 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "11acb4b4",
+ "execution_count": 303,
+ "id": "8bae941d",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Percent of survived people: 38.25\n"
+ ]
+ }
+ ],
"source": [
- "# ваш код"
+ "survived_td = len(titanic_data[titanic_data[\"survived\"] > 0])\n",
+ "survived_percent_td = round(survived_td / len(titanic_data) * 100, 2)\n",
+ "print(f\"Percent of survived people: {survived_percent_td}\")"
]
},
{
@@ -191,12 +1676,37 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 304,
"id": "59ec7295",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "embark_town\n",
+ "Southampton 217\n",
+ "Cherbourg 93\n",
+ "Queenstown 30\n",
+ "Name: count, dtype: int64"
+ ]
+ },
+ "execution_count": 304,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# ваш код"
+ "is_survive = titanic_data[\"survived\"] > 0\n",
+ "survived_people_td = titanic_data[is_survive][\"embark_town\"].value_counts()\n",
+ "print(type(survived_people_td))\n",
+ "survived_people_td"
]
},
{
@@ -211,12 +1721,39 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 305,
"id": "34daca28",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "class\n",
+ "First 62.62\n",
+ "Second 47.28\n",
+ "Third 24.24\n",
+ "Name: count, dtype: float64"
+ ]
+ },
+ "execution_count": 305,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# ваш код"
+ "is_survive = titanic_data[\"survived\"] > 0\n",
+ "surv_people_td = (\n",
+ " titanic_data[is_survive][\"class\"].value_counts() / titanic_data[\"class\"].value_counts() * 100\n",
+ ")\n",
+ "print(type(surv_people_td))\n",
+ "round(surv_people_td, 2)"
]
},
{
@@ -231,12 +1768,26 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 306,
"id": "1fc0d667",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "73.58"
+ ]
+ },
+ "execution_count": 306,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# ваш код"
+ "is_rich = titanic_data[\"fare\"] >= 100\n",
+ "is_survive = titanic_data[\"survived\"] > 0\n",
+ "surv_rich_people = len(titanic_data[(is_rich) & (is_survive)]) / len(titanic_data[is_rich]) * 100\n",
+ "round(surv_rich_people, 2)"
]
},
{
@@ -251,12 +1802,26 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 307,
"id": "480352b6",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0"
+ ]
+ },
+ "execution_count": 307,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "# ваш код"
+ "is_child = titanic_data[\"who\"] == \"child\"\n",
+ "is_alone = titanic_data[\"alone\"] == \"True\"\n",
+ "child_alone_td = len(titanic_data[is_child & is_alone])\n",
+ "child_alone_td"
]
},
{
@@ -266,11 +1831,19 @@
"source": [
"Какие выводы вы можете сделать о выживших пассажирах Титаника? "
]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "623cb5f3",
+ "metadata": {},
+ "source": [
+ "Дети одни не путешествуют, ну и большая часть богатых выжила, видимо, большинство было из Southampton - оттуда больше всего человек выжило"
+ ]
}
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "venv",
"language": "python",
"name": "python3"
},
@@ -284,7 +1857,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.9"
+ "version": "3.12.5"
}
},
"nbformat": 4,