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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
survivedpclasssexagesibspparchfareembarkedclasswhoadult_maledeckembark_townalivealone
13312female29.01026.0000SSecondwomanFalseNaNSouthamptonyesFalse
51903male32.0007.8958SThirdmanTrueNaNSouthamptonnoTrue
49903male24.0007.7958SThirdmanTrueNaNSouthamptonnoTrue
56803maleNaN007.2292CThirdmanTrueNaNCherbourgnoTrue
48411male25.01091.0792CFirstmanTrueBCherbourgyesFalse
\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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
survivedpclasssexagesibspparchfareembarkedclasswhoadult_maledeckembark_townalivealone
00001770002000688200
\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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
survivedpclasssexagesibspparchfareembarkedclasswhoadult_maleembark_townalivealone
003male22.0107.2500SThirdmanTrueSouthamptonnoFalse
111female38.01071.2833CFirstwomanFalseCherbourgyesFalse
213female26.0007.9250SThirdwomanFalseSouthamptonyesTrue
311female35.01053.1000SFirstwomanFalseSouthamptonyesFalse
403male35.0008.0500SThirdmanTrueSouthamptonnoTrue
.............................................
88602male27.00013.0000SSecondmanTrueSouthamptonnoTrue
88711female19.00030.0000SFirstwomanFalseSouthamptonyesTrue
88803femaleNaN1223.4500SThirdwomanFalseSouthamptonnoFalse
88911male26.00030.0000CFirstmanTrueCherbourgyesTrue
89003male32.0007.7500QThirdmanTrueQueenstownnoTrue
\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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
survivedpclasssexagesibspparchfareembarkedclasswhoadult_maleembark_townalivealone
003male22.0107.2500SThirdmanTrueSouthamptonnoFalse
111female38.01071.2833CFirstwomanFalseCherbourgyesFalse
213female26.0007.9250SThirdwomanFalseSouthamptonyesTrue
311female35.01053.1000SFirstwomanFalseSouthamptonyesFalse
403male35.0008.0500SThirdmanTrueSouthamptonnoTrue
.............................................
88602male27.00013.0000SSecondmanTrueSouthamptonnoTrue
88711female19.00030.0000SFirstwomanFalseSouthamptonyesTrue
88803femaleNaN1223.4500SThirdwomanFalseSouthamptonnoFalse
88911male26.00030.0000CFirstmanTrueCherbourgyesTrue
89003male32.0007.7500QThirdmanTrueQueenstownnoTrue
\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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
survivedpclasssexagesibspparchfareembarkedclasswhoadult_maleembark_townalivealone
00001770002000200
\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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
survivedpclasssexagesibspparchfareembarkedclasswhoadult_maleembark_townalivealone
003male22.0107.2500SThirdmanTrueSouthamptonnoFalse
111female38.01071.2833CFirstwomanFalseCherbourgyesFalse
213female26.0007.9250SThirdwomanFalseSouthamptonyesTrue
311female35.01053.1000SFirstwomanFalseSouthamptonyesFalse
403male35.0008.0500SThirdmanTrueSouthamptonnoTrue
.............................................
88602male27.00013.0000SSecondmanTrueSouthamptonnoTrue
88711female19.00030.0000SFirstwomanFalseSouthamptonyesTrue
88803female32.01223.4500SThirdwomanFalseSouthamptonnoFalse
88911male26.00030.0000CFirstmanTrueCherbourgyesTrue
89003male32.0007.7500QThirdmanTrueQueenstownnoTrue
\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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
survivedpclasssexagesibspparchfareembarkedclasswhoadult_maleembark_townalivealone
003male22.0107.2500SThirdmanTrueSouthamptonnoFalse
111female38.01071.2833CFirstwomanFalseCherbourgyesFalse
213female26.0007.9250SThirdwomanFalseSouthamptonyesTrue
311female35.01053.1000SFirstwomanFalseSouthamptonyesFalse
403male35.0008.0500SThirdmanTrueSouthamptonnoTrue
.............................................
88602male27.00013.0000SSecondmanTrueSouthamptonnoTrue
88711female19.00030.0000SFirstwomanFalseSouthamptonyesTrue
88803female32.01223.4500SThirdwomanFalseSouthamptonnoFalse
88911male26.00030.0000CFirstmanTrueCherbourgyesTrue
89003male32.0007.7500QThirdmanTrueQueenstownnoTrue
\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,