diff --git a/.coverage b/.coverage new file mode 100644 index 00000000..d7376cf5 Binary files /dev/null and b/.coverage differ diff --git a/.github/workflows/trying.ipynb b/.github/workflows/trying.ipynb new file mode 100644 index 00000000..908a1b10 --- /dev/null +++ b/.github/workflows/trying.ipynb @@ -0,0 +1,1616 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "08c46c22", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "9999999999\n" + ] + } + ], + "source": [ + "def get_sum_of_prime_divisors(num: int) -> int:\n", + " n = num\n", + " sum_of_divisors = 0\n", + " for i in range(2, int(num**0.5) + 1):\n", + " if num % i == 0:\n", + " sum_of_divisors += i\n", + " while num % i == 0:\n", + " num //= i\n", + " if sum_of_divisors == 0:\n", + " return n\n", + " return sum_of_divisors\n", + "\n", + "\n", + "print(get_sum_of_prime_divisors(10000000000 - 1))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "9abf76e1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2]\n", + "[1, 2, 3]\n", + "[2, 3]\n", + "True\n" + ] + } + ], + "source": [ + "def is_there_any_good_subarray(nums: list[int], k: int) -> bool:\n", + " if len(nums) < 2:\n", + " return False\n", + " elif len(nums) == 2:\n", + " sum = 0\n", + " for subarr in nums:\n", + " sum+=subarr\n", + " if sum%k==0:\n", + " return True\n", + " else:\n", + " return False\n", + " for i in range(0,len(nums) - 1):\n", + " for j in range(i+2, len(nums)+1):\n", + " sum=0\n", + " print(nums[i:j])\n", + " for subarr in nums[i:j]:\n", + " sum += subarr\n", + " if sum % k == 0:\n", + " return True\n", + " return False\n", + "print(is_there_any_good_subarray([1, 2, 3], 5))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "fd7d5d7d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "21\n" + ] + } + ], + "source": [ + "def get_gcd(num1: int, num2: int) -> int:\n", + " while max(num1, num2) % min(num1, num2) != 0:\n", + " if num1 > num2:\n", + " num1 = num1 % num2\n", + " else:\n", + " num2 = num2 % num1\n", + " return min(num1, num2)\n", + "\n", + "\n", + "print(get_gcd(1071, 147))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a62ad6c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{2, 3}\n", + "5\n" + ] + } + ], + "source": [ + "def IsPrime(num: int) -> bool:\n", + " d = 2\n", + " while num % d != 0:\n", + " d += 1\n", + " return d == num\n", + "\n", + "\n", + "def get_sum_of_prime_divisors(num: int) -> int:\n", + " sum_of_divisors = 0\n", + " divisors = []\n", + " i = 2\n", + " while num != 1:\n", + " if num % i == 0:\n", + " if IsPrime(i):\n", + " divisors.append(i)\n", + " num //= i\n", + " i = 2\n", + "\n", + " else:\n", + " i += 1\n", + " divisors = set(divisors)\n", + " for i in divisors:\n", + " sum_of_divisors += i\n", + " return sum_of_divisors\n", + "\n", + "\n", + "print(get_sum_of_prime_divisors(12))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "4fd42f4f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "def is_palindrome(num: int) -> bool:\n", + " if num < 0:\n", + " return False\n", + " num_reversed = 0\n", + " num_reversed += num % 10\n", + " num_current = num\n", + " num_current //= 10\n", + " while num_current > 0:\n", + " num_reversed *= 10\n", + " num_reversed += num_current % 10\n", + " num_current //= 10\n", + " return num == num_reversed\n", + "\n", + "\n", + "print(is_palindrome(121))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "047df546", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1001\n" + ] + } + ], + "source": [ + "num = 9\n", + "answer = 0\n", + "position = 1\n", + "while num > 0:\n", + " answer = answer + position * (num % 2)\n", + " position *= 10\n", + " num //= 2\n", + "print(answer)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8b93d7a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1001\n", + "9\n" + ] + }, + { + "ename": "", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31mThe Kernel crashed while executing code in the current cell or a previous cell. \n", + "\u001b[1;31mPlease review the code in the cell(s) to identify a possible cause of the failure. \n", + "\u001b[1;31mClick here for more info. \n", + "\u001b[1;31mView Jupyter log for further details." + ] + } + ], + "source": [ + "def flip_bits_in_range(num: int, left_bit: int, right_bit: int) -> int:\n", + " answer = 0\n", + " position = 1\n", + " curr_bit = 1\n", + " while num > 0:\n", + " if curr_bit >= left_bit and curr_bit <= right_bit:\n", + " if num % 2 == 1:\n", + " answer = answer + position * 0\n", + " else:\n", + " answer = answer + position * 1\n", + " else:\n", + " answer = answer + position * (num % 2)\n", + " position *= 10\n", + " num //= 2\n", + " curr_bit += 1\n", + " num = 0\n", + " power = 0\n", + " print(answer)\n", + " while answer > 0:\n", + " digit = answer % 10\n", + " num += digit * (2**power)\n", + " answer //= 10\n", + " power += 1\n", + " return num\n", + "\n", + "\n", + "print(flip_bits_in_range(0b1011, 2, 2))" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "693fdb92", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def get_nth_digit(num: int) -> int:\n", + " count_digit = 1\n", + " flag_finish = False\n", + " answer = 0\n", + " i = 0\n", + " while True:\n", + " k = i * 2\n", + " while k > 0:\n", + " if num == count_digit:\n", + " answer = k % 10\n", + " flag_finish = True\n", + " break\n", + " k //= 10\n", + " count_digit += 1\n", + " if flag_finish:\n", + " break\n", + " i += 1\n", + " return answer\n", + "\n", + "\n", + "get_nth_digit(5)" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "570f59c2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1, 4]]\n" + ] + } + ], + "source": [ + "def merge_intervals(intervals: list[list[int, int]]) -> list[list[int, int]]:\n", + " intervals.sort(key=lambda x: x[0])\n", + " if len(intervals) == 0:\n", + " return []\n", + " newintervals = []\n", + " start, finish = intervals[0][0], intervals[0][1]\n", + " flag1 = True\n", + " for i in intervals:\n", + " if flag1:\n", + " flag1 = False\n", + " continue # скип первого элемента(костыль)\n", + " if start < i[0] and finish > i[1]:\n", + " continue\n", + " elif finish >= i[0] and start <= i[0]:\n", + " finish = i[1]\n", + " else:\n", + " newintervals.append([start, finish])\n", + " start = i[0]\n", + " finish = i[1]\n", + " newintervals.append([start, finish])\n", + " return newintervals\n", + "\n", + "\n", + "print(merge_intervals([[1, 4], [2, 3], [1, 4]]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb839bd5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "def is_punctuation(text: str) -> bool:\n", + " for i in text:\n", + " numb_code = ord(i)\n", + " if not (\n", + " (numb_code >= 32 and numb_code <= 47)\n", + " or (numb_code >= 160 and numb_code <= 255)\n", + " or (numb_code >= 8192 and numb_code <= 8303)\n", + " or (numb_code >=ё 11776 and numb_code <= 11903)\n", + " or (numb_code >= 12288 and numb_code <= 12351)\n", + " )\n", + " return False\n", + " return True\n", + "\n", + "\n", + "print(is_punctuation(\"!!!!!;q';\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "c55fc9ef", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "def unzip(compress_text: str) -> str:\n", + " result = \"\"\n", + " compress_text = compress_text.split(\" \")\n", + " for i in compress_text:\n", + " if \"*\" not in i:\n", + " result += i\n", + " else:\n", + " result += i[:-2] * int(i[-1])\n", + " return result\n", + "\n", + "\n", + "print(unzip(\"a*10\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "66072e10", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "False\n" + ] + } + ], + "source": [ + "def reg_validator(reg_expr: str, text: str) -> bool:\n", + " i, j = 0, 0\n", + " while i < len(reg_expr) and j < len(text):\n", + " symbol = reg_expr[i]\n", + " if symbol == \"d\":\n", + " if not text[j].isdigit():\n", + " print(i)\n", + " return False\n", + " while j < len(text) and text[j].isdigit():\n", + " j += 1\n", + " elif symbol == \"p\":\n", + " if not text[j].isalpha():\n", + " return False\n", + " while j < len(text) and text[j].isalpha():\n", + " j += 1\n", + " elif symbol == \"s\":\n", + " if not (text[j].isalpha() or text[j].isdigit()):\n", + " return False\n", + " while j < len(text) and (text[j].isalpha() or text[j].isdigit()):\n", + " j += 1\n", + " else:\n", + " if text[j] != symbol:\n", + " return False\n", + " j += 1\n", + " i += 1\n", + "\n", + " return i == len(reg_expr) and j == len(text)\n", + "\n", + "\n", + "print(reg_validator(\"w\", \"hello\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "7a1295ce", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n" + ] + } + ], + "source": [ + "def get_sum_of_prime_divisors(num: int) -> int:\n", + " n = num\n", + " if n == 1:\n", + " return 0\n", + " sum_of_divisors = 0\n", + " for i in range(2, int(num**0.5) + 1):\n", + " if num % i == 0:\n", + " sum_of_divisors += i\n", + " while num % i == 0:\n", + " num //= i\n", + " if sum_of_divisors == 0:\n", + " return n\n", + " return sum_of_divisors\n", + "print(get_sum_of_prime_divisors(26))" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "f34569a9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10\n", + "XL\n" + ] + } + ], + "source": [ + "def int_to_roman(num: int) -> str:\n", + " roman_numbers = { 1000 : \"M\", 500 : \"D\", 100 : \"C\", \n", + " 50 : \"L\", 10 : \"X\", 5 : \"V\", 1 : \"I\"}\n", + " roman_digits = [1000, 500, 100, 50, 10, 5, 1]\n", + " index = 0\n", + " result = ''\n", + " flag_close = False\n", + " while index < len(roman_digits) and num > 0:\n", + " if not flag_close and (num - roman_digits[index]) < 0:\n", + " flag_close = True\n", + " elif not flag_close:\n", + " result += roman_numbers[roman_digits[index]]\n", + " num -= roman_digits[index]\n", + " elif flag_close:\n", + " if (index == 0 or index == 2 or index == 4) and (num - (roman_digits[index] - 10 ** ((str(roman_digits[index]).count('0')) - 1))) >= 0:\n", + " num -= (roman_digits[index] - 10 ** ((str(roman_digits[index]).count('0')) - 1))\n", + " result += roman_numbers[10 ** ((str(roman_digits[index]).count('0')) - 1)]+roman_numbers[roman_digits[index]]\n", + " flag_close = False\n", + " index+=1 \n", + " elif index != 2 and index!= 0 and index != 4 and (num - (roman_digits[index] - 10 ** str(roman_digits[index]).count('0'))) >= 0:\n", + " print( 10 ** str(roman_digits[index]).count('0'))\n", + " result += roman_numbers[10 ** str(roman_digits[index]).count('0')]+roman_numbers[roman_digits[index]]\n", + " num -= (roman_digits[index] - 10 ** str(roman_digits[index]).count('0'))\n", + " flag_close = False\n", + " index+=1\n", + " else:\n", + " flag_close = False\n", + " index+=1\n", + " return result\n", + "print(int_to_roman(40))" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "2ae168bc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(set('pwwwkew'))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "fbde457b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "18.329926258226045 0.06225318726752254\n" + ] + } + ], + "source": [ + "rad = float(input())\n", + "i = 5.1*10**(-4)*(1453*2+576.02)*(rad**2) - 5.5\n", + "progri = i * (4*(0.005/rad)**2 + (1/(1453+1453+576.02))**2+0.002**2)**0.5\n", + "print(i, progri)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "114c276f", + "metadata": {}, + "outputs": [ + { + "ename": "ImportError", + "evalue": "cannot import name 'NoneType' from 'typing' (c:\\Users\\Shanechka\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\typing.py)", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mImportError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[3], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mtyping\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m NoneType\n\u001b[0;32m 2\u001b[0m test \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 3\u001b[0m \u001b[38;5;28misinstance\u001b[39m(test, NoneType)\n", + "\u001b[1;31mImportError\u001b[0m: cannot import name 'NoneType' from 'typing' (c:\\Users\\Shanechka\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\typing.py)" + ] + } + ], + "source": [ + "test = None\n", + "isinstance(test, NoneType)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "f6c933fd", + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "Vector2D.__init__() missing 2 required positional arguments: '_Vector2D__abscissa' and '_Vector2D__ordinate'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[15], line 41\u001b[0m\n\u001b[0;32m 37\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;241m0\u001b[39m\n\u001b[0;32m 39\u001b[0m \u001b[38;5;66;03m# ваш код\u001b[39;00m\n\u001b[1;32m---> 41\u001b[0m vec\u001b[38;5;241m=\u001b[39m\u001b[43mVector2D\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 42\u001b[0m \u001b[38;5;28mprint\u001b[39m(vec)\n", + "\u001b[1;31mTypeError\u001b[0m: Vector2D.__init__() missing 2 required positional arguments: '_Vector2D__abscissa' and '_Vector2D__ordinate'" + ] + } + ], + "source": [ + "class Vector2D:\n", + " __abscissa : float = 0.0\n", + " __ordinate : float = 0.0\n", + " def __init__(self, abscissa: float, ordinate: float):\n", + " self.abscissa = abscissa\n", + " self.ordinate = ordinate\n", + " def get_x(self):\n", + " return self.abscissa\n", + " def get_y(self):\n", + " return self.ordinate\n", + " property(get_x)\n", + " property(get_y)\n", + " def conj(self) -> \"Vector2D\":\n", + " # ваш код\n", + " return Vector2D()\n", + " def __repr__(self):\n", + " return f\"Vector2D(abscissa={self.abscissa}, ordinate={self.ordinate})\"\n", + " def __eq__(self, other: \"Vector2D\"):\n", + " return self.abscissa == other.abscissa and self.ordinate == other.ordinate\n", + " def __ne__(self, other: \"Vector2D\"):\n", + " return self.abscissa != other.abscissa or self.ordinate != other.ordinate\n", + " def __lt__(self, other: \"Vector2D\"):\n", + " return self.abscissa < other.abscissa or (self.ordinate < other.ordinate and self.abscissa == other.abscissa)\n", + " def __gt__(self, other: \"Vector2D\"):\n", + " return self.abscissa > other.abscissa or (self.ordinate > other.ordinate and self.abscissa == other.abscissa)\n", + " def __le__(self, other: \"Vector2D\"):\n", + " return not (self > other)\n", + " def __ge__(self, other: \"Vector2D\"):\n", + " return not (self < other)\n", + " def __abs__(self):\n", + " return (self.absciss**2 + self.ordinate**2) ** 0.5\n", + " def __bool__(self):\n", + " return abs(self) != 0\n", + " \n", + " def get_angle(self, other: \"Vector2D\") -> float:\n", + " # ваш код\n", + " return 0\n", + "\n", + "vec=Vector2D()\n", + "print(vec)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "750d5ad3", + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'function' object has no attribute '__mro__'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[28], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mdataclasses\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m dataclass\n\u001b[1;32m----> 2\u001b[0m \u001b[38;5;28;43;01mclass\u001b[39;49;00m\u001b[38;5;250;43m \u001b[39;49m\u001b[38;5;21;43;01mVector2D\u001b[39;49;00m\u001b[43m:\u001b[49m\n\u001b[0;32m 3\u001b[0m \u001b[43m \u001b[49m\u001b[43m__abscissa\u001b[49m\u001b[43m \u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mfloat\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0.0\u001b[39;49m\n\u001b[0;32m 4\u001b[0m \u001b[43m \u001b[49m\u001b[43m__ordinate\u001b[49m\u001b[43m \u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mfloat\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0.0\u001b[39;49m\n", + "Cell \u001b[1;32mIn[28], line 5\u001b[0m, in \u001b[0;36mVector2D\u001b[1;34m()\u001b[0m\n\u001b[0;32m 3\u001b[0m __abscissa : \u001b[38;5;28mfloat\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.0\u001b[39m\n\u001b[0;32m 4\u001b[0m __ordinate : \u001b[38;5;28mfloat\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.0\u001b[39m\n\u001b[1;32m----> 5\u001b[0m \u001b[43m\u001b[49m\u001b[38;5;129;43m@dataclass\u001b[39;49m\n\u001b[0;32m 6\u001b[0m \u001b[43m\u001b[49m\u001b[38;5;28;43;01mdef\u001b[39;49;00m\u001b[38;5;250;43m \u001b[39;49m\u001b[38;5;21;43m__init__\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mabscissa\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mfloat\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mordinate\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mfloat\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[0;32m 7\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__abscissa\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mabscissa\u001b[49m\n\u001b[0;32m 8\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__ordinate\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mordinate\u001b[49m\n", + "File \u001b[1;32mc:\\Users\\Shanechka\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\dataclasses.py:1305\u001b[0m, in \u001b[0;36mdataclass\u001b[1;34m(cls, init, repr, eq, order, unsafe_hash, frozen, match_args, kw_only, slots, weakref_slot)\u001b[0m\n\u001b[0;32m 1302\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m wrap\n\u001b[0;32m 1304\u001b[0m \u001b[38;5;66;03m# We're called as @dataclass without parens.\u001b[39;00m\n\u001b[1;32m-> 1305\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mwrap\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mcls\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32mc:\\Users\\Shanechka\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\dataclasses.py:1295\u001b[0m, in \u001b[0;36mdataclass..wrap\u001b[1;34m(cls)\u001b[0m\n\u001b[0;32m 1294\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mwrap\u001b[39m(\u001b[38;5;28mcls\u001b[39m):\n\u001b[1;32m-> 1295\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_process_class\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mcls\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43minit\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mrepr\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43meq\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43morder\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43munsafe_hash\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1296\u001b[0m \u001b[43m \u001b[49m\u001b[43mfrozen\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmatch_args\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkw_only\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mslots\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1297\u001b[0m \u001b[43m \u001b[49m\u001b[43mweakref_slot\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32mc:\\Users\\Shanechka\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\dataclasses.py:961\u001b[0m, in \u001b[0;36m_process_class\u001b[1;34m(cls, init, repr, eq, order, unsafe_hash, frozen, match_args, kw_only, slots, weakref_slot)\u001b[0m\n\u001b[0;32m 959\u001b[0m all_frozen_bases \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m 960\u001b[0m has_dataclass_bases \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m--> 961\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m b \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;18;43m__mro__\u001b[39;49m[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m:\u001b[38;5;241m0\u001b[39m:\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m]:\n\u001b[0;32m 962\u001b[0m \u001b[38;5;66;03m# Only process classes that have been processed by our\u001b[39;00m\n\u001b[0;32m 963\u001b[0m \u001b[38;5;66;03m# decorator. That is, they have a _FIELDS attribute.\u001b[39;00m\n\u001b[0;32m 964\u001b[0m base_fields \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mgetattr\u001b[39m(b, _FIELDS, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[0;32m 965\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m base_fields \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "\u001b[1;31mAttributeError\u001b[0m: 'function' object has no attribute '__mro__'" + ] + } + ], + "source": [ + "from dataclasses import dataclass\n", + "class Vector2D:\n", + " __abscissa : float = 0.0\n", + " __ordinate : float = 0.0\n", + " @dataclass\n", + " def __init__(self, abscissa: float, ordinate: float):\n", + " self.__abscissa = abscissa\n", + " self.__ordinate = ordinate\n", + " def get_x(self):\n", + " return self.__abscissa\n", + " def get_y(self):\n", + " return self.__ordinate\n", + " property(get_x)\n", + " property(get_y)\n", + " def conj(self) -> \"Vector2D\":\n", + " # ваш код\n", + " return Vector2D()\n", + " def __repr__(self):\n", + " return f\"Vector2D(__abscissa={self.__abscissa}, __ordinate={self.__ordinate})\"\n", + " def __eq__(self, other: \"Vector2D\"):\n", + " return self.__abscissa == other.__abscissa and self.__ordinate == other.__ordinate\n", + " def __ne__(self, other: \"Vector2D\"):\n", + " return self.__abscissa != other.__abscissa or self.__ordinate != other.__ordinate\n", + " def __lt__(self, other: \"Vector2D\"):\n", + " return self.__abscissa < other.__abscissa or (self.__ordinate < other.__ordinate and self.__abscissa == other.__abscissa)\n", + " def __gt__(self, other: \"Vector2D\"):\n", + " return self.__abscissa > other.__abscissa or (self.__ordinate > other.__ordinate and self.__abscissa == other.__abscissa)\n", + " def __le__(self, other: \"Vector2D\"):\n", + " return not (self > other)\n", + " def __ge__(self, other: \"Vector2D\"):\n", + " return not (self < other)\n", + " def __abs__(self):\n", + " return (self.__abscissa**2 + self.__ordinate**2) ** 0.5\n", + " def __bool__(self):\n", + " return abs(self) != 0\n", + " \n", + " def get_angle(self, other: \"Vector2D\") -> float:\n", + " # ваш код\n", + " return 0\n", + "\n", + " # ваш код\n", + "vec = Vector2D()\n", + "print(vec)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "27573b31", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Vector2D(abscissa=5, ordinate=25)\n" + ] + } + ], + "source": [ + "from dataclasses import dataclass\n", + "@dataclass\n", + "class Vector2D:\n", + " abscissa : float = 0.0\n", + " ordinate : float = 0.0\n", + " # def __init__(self, abscissa: float, ordinate: float):\n", + " # self.abscissa = abscissa\n", + " # self.ordinate = ordinate\n", + " # def __repr__(self):\n", + " # return f\"Vector2D(abscissa={self.abscissa}, ordinate={self.ordinate})\"\n", + " # def __eq__(self, other: \"Vector2D\"):\n", + " # return self.abscissa == other.abscissa and self.ordinate == other.ordinate\n", + " def get_x(self):\n", + " return self.abscissa\n", + " def get_y(self):\n", + " return self.ordinate\n", + " def conj(self) -> \"Vector2D\":\n", + " return Vector2D()\n", + "\n", + " property(get_x)\n", + " property(get_y)\n", + " def __ne__(self, other: \"Vector2D\"):\n", + " return self.abscissa != other.abscissa or self.ordinate != other.ordinate\n", + " def __lt__(self, other: \"Vector2D\"):\n", + " return self.abscissa < other.abscissa or (self.ordinate < other.ordinate and self.abscissa == other.abscissa)\n", + " def __gt__(self, other: \"Vector2D\"):\n", + " return self.abscissa > other.abscissa or (self.ordinate > other.ordinate and self.abscissa == other.abscissa)\n", + " def __le__(self, other: \"Vector2D\"):\n", + " return not (self > other)\n", + " def __ge__(self, other: \"Vector2D\"):\n", + " return not (self < other)\n", + " def __abs__(self):\n", + " return (self.abscissa**2 + self.ordinate**2) ** 0.5\n", + " def __bool__(self):\n", + " return abs(self) != 0\n", + " def __mul__ (self, mult_amount):\n", + " return Vector2D(self.abscissa * mult_amount, self.ordinate * mult_amount)\n", + " def __rmul__(self, mult_amount):\n", + " return self * mult_amount\n", + " \n", + " def get_angle(self, other: \"Vector2D\") -> float:\n", + " # ваш код\n", + " return 0\n", + " # ваш код\n", + "print( Vector2D(1,5) * 5)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "ca8141e7", + "metadata": {}, + "outputs": [ + { + "ename": "FrozenInstanceError", + "evalue": "cannot assign to field 'abscissa'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mFrozenInstanceError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[42], line 74\u001b[0m\n\u001b[0;32m 72\u001b[0m \u001b[38;5;66;03m# ваш код\u001b[39;00m\n\u001b[0;32m 73\u001b[0m vec \u001b[38;5;241m=\u001b[39m Vector2D(\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m2\u001b[39m)\n\u001b[1;32m---> 74\u001b[0m \u001b[43mvec\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mabscissa\u001b[49m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m2\u001b[39m\n", + "File \u001b[1;32m:11\u001b[0m, in \u001b[0;36m__setattr__\u001b[1;34m(self, name, value)\u001b[0m\n", + "\u001b[1;31mFrozenInstanceError\u001b[0m: cannot assign to field 'abscissa'" + ] + } + ], + "source": [ + "from dataclasses import dataclass\n", + "from math import isclose, acos, degrees\n", + "@dataclass(eq = False, frozen = True)\n", + "class Vector2D:\n", + " abscissa : float = 0.0\n", + " ordinate : float = 0.0\n", + " # def __init__(self, abscissa: float, ordinate: float):\n", + " # self.abscissa = abscissa\n", + " # self.ordinate = ordinate\n", + " # def __repr__(self):\n", + " # return f\"Vector2D(abscissa={self.abscissa}, ordinate={self.ordinate})\"\n", + " def __post_init__(self):\n", + " object.__setattr__(self, \"abscissa\", float(self.abscissa))\n", + " object.__setattr__(self, \"ordinate\", float(self.ordinate))\n", + " @property\n", + " def get_x(self):\n", + " return self.abscissa\n", + " @property\n", + " def get_y(self):\n", + " return self.ordinate\n", + " def __eq__(self, other: \"Vector2D\"):\n", + " \"\"\"We use float numbers so we want to check equality by using isclose() while dataclass is using ==\"\"\"\n", + " return isclose(self.abscissa, other.abscissa) and isclose(self.ordinate, other.ordinate)\n", + " def __ne__(self, other: \"Vector2D\"):\n", + " return not (self == other)\n", + " def __lt__(self, other: \"Vector2D\"):\n", + " return self.abscissa < other.abscissa or (self.ordinate < other.ordinate and self.abscissa == other.abscissa)\n", + " def __gt__(self, other: \"Vector2D\"):\n", + " return self.abscissa > other.abscissa or (self.ordinate > other.ordinate and self.abscissa == other.abscissa)\n", + " def __le__(self, other: \"Vector2D\"):\n", + " return not (self > other)\n", + " def __ge__(self, other: \"Vector2D\"):\n", + " return not (self < other)\n", + " def __abs__(self):\n", + " return (self.abscissa**2 + self.ordinate**2) ** 0.5\n", + " def __bool__(self):\n", + " return abs(self) != 0\n", + " def __mul__ (self: \"Vector2D\", mult_amount):\n", + " return Vector2D(self.abscissa * mult_amount, self.ordinate * mult_amount)\n", + " def __rmul__ (self, mult_amount):\n", + " return self * mult_amount\n", + " def __truediv__ (self, mult_amount):\n", + " return Vector2D(self.abscissa / mult_amount, self.ordinate / mult_amount)\n", + " def __add__(self, other: \"Vector2D\"):\n", + " return Vector2D(self.abscissa + other.abscissa, self.ordinate + other.ordinate) \n", + " def __add__(self, add_amount):\n", + " return Vector2D(self.abscissa + add_amount, self.ordinate + add_amount)\n", + " def __radd__(self, add_amount):\n", + " return self + add_amount\n", + " def __sub__(self, sub_amount):\n", + " return Vector2D(self.abscissa - sub_amount, self.ordinate - sub_amount)\n", + " def __sub__(self, other: \"Vector2D\"):\n", + " return Vector2D(self.abscissa - other.abscissa, self.ordinate - other.ordinate)\n", + " def __neg__(self):\n", + " return self * -1\n", + " def __float__(self):\n", + " return abs(self)\n", + " def __int__(self):\n", + " return int(abs(self))\n", + " def __complex__(self):\n", + " return complex(self.abscissa, self.ordinate)\n", + " def __matmul__(self, other: \"Vector2D\"): #@ skalar mult\n", + " return self.abscissa * other.abscissa + self.ordinate * other.ordinate\n", + "\n", + " def get_angle(self, other: \"Vector2D\") -> float:\n", + " if isclose(abs(other), 0):\n", + " raise ValueError(\"You cannot get angle in between given vector and a zero vector\")\n", + " return degrees(acos((self @ other) / (abs(self) * abs(other))))\n", + " def conj(self):\n", + " return Vector2D(self.abscissa, self.ordinate * -1)\n", + "\n", + " # ваш код\n", + "vec = Vector2D(1,2)\n", + "vec.abscissa = 2" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "134eb0ef", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Vector2D(abscissa=0.0, ordinate=0.0)\n" + ] + } + ], + "source": [ + "from dataclasses import dataclass\n", + "from math import isclose, acos, degrees\n", + "@dataclass(eq = False, frozen = True)\n", + "class Vector2D:\n", + " abscissa : float = 0.\n", + " ordinate : float = 0.\n", + " # def __init__(self, abscissa: float, ordinate: float):\n", + " # self.abscissa = abscissa\n", + " # self.ordinate = ordinate\n", + " # def __repr__(self):\n", + " # return f\"Vector2D(abscissa={self.abscissa}, ordinate={self.ordinate})\"\n", + " def __post_init__(self):\n", + " object.__setattr__(self, \"abscissa\", float(self.abscissa))\n", + " object.__setattr__(self, \"ordinate\", float(self.ordinate))\n", + " @property\n", + " def get_x(self):\n", + " return self.abscissa\n", + " @property\n", + " def get_y(self):\n", + " return self.ordinate\n", + " def __eq__(self, other: \"Vector2D\"):\n", + " \"\"\"We use float numbers so we want to check equality by using isclose() while dataclass is using ==\"\"\"\n", + " return isclose(self.abscissa, other.abscissa) and isclose(self.ordinate, other.ordinate)\n", + " def __ne__(self, other: \"Vector2D\"):\n", + " return not (self == other)\n", + " def __lt__(self, other: \"Vector2D\"):\n", + " return self.abscissa < other.abscissa or (self.ordinate < other.ordinate and self.abscissa == other.abscissa)\n", + " def __gt__(self, other: \"Vector2D\"):\n", + " return self.abscissa > other.abscissa or (self.ordinate > other.ordinate and self.abscissa == other.abscissa)\n", + " def __le__(self, other: \"Vector2D\"):\n", + " return not (self > other)\n", + " def __ge__(self, other: \"Vector2D\"):\n", + " return not (self < other)\n", + " def __abs__(self):\n", + " return (self.abscissa**2 + self.ordinate**2) ** 0.5\n", + " def __bool__(self):\n", + " return abs(self) != 0\n", + " def __mul__ (self: \"Vector2D\", mult_amount):\n", + " return Vector2D(self.abscissa * mult_amount, self.ordinate * mult_amount)\n", + " def __rmul__ (self, mult_amount):\n", + " return self * mult_amount\n", + " def __truediv__ (self, mult_amount):\n", + " return Vector2D(self.abscissa / mult_amount, self.ordinate / mult_amount)\n", + " def __add__(self, other: \"Vector2D\"):\n", + " return Vector2D(self.abscissa + other.abscissa, self.ordinate + other.ordinate) \n", + " def __add__(self, add_amount):\n", + " return Vector2D(self.abscissa + add_amount, self.ordinate + add_amount)\n", + " def __radd__(self, add_amount):\n", + " return self + add_amount\n", + " def __sub__(self, sub_amount):\n", + " return Vector2D(self.abscissa - sub_amount, self.ordinate - sub_amount)\n", + " def __sub__(self, other: \"Vector2D\"):\n", + " return Vector2D(self.abscissa - other.abscissa, self.ordinate - other.ordinate)\n", + " def __neg__(self):\n", + " return self * -1\n", + " def __float__(self):\n", + " return abs(self)\n", + " def __int__(self):\n", + " return int(abs(self))\n", + " def __complex__(self):\n", + " return complex(self.abscissa, self.ordinate)\n", + " def __matmul__(self, other: \"Vector2D\"): #@ skalar mult\n", + " return self.abscissa * other.abscissa + self.ordinate * other.ordinate\n", + "\n", + " def get_angle(self, other: \"Vector2D\") -> float:\n", + " if isclose(abs(other), 0):\n", + " raise ValueError(\"You cannot get angle in between given vector and a zero vector\")\n", + " return degrees(acos((self @ other) / (abs(self) * abs(other))))\n", + " def conj(self):\n", + " return Vector2D(self.abscissa, self.ordinate * -1)\n", + "\n", + " # ваш код\n", + "print(Vector2D())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "50ebd9a2", + "metadata": {}, + "outputs": [ + { + "ename": "RuntimeError", + "evalue": "'widget is not a recognised GUI loop or backend name", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "File \u001b[1;32mc:\\Users\\Shanechka\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\matplotlib\\backends\\registry.py:407\u001b[0m, in \u001b[0;36mBackendRegistry.resolve_gui_or_backend\u001b[1;34m(self, gui_or_backend)\u001b[0m\n\u001b[0;32m 406\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 407\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresolve_backend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mgui_or_backend\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 408\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m: \u001b[38;5;66;03m# KeyError ?\u001b[39;00m\n", + "File \u001b[1;32mc:\\Users\\Shanechka\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\matplotlib\\backends\\registry.py:369\u001b[0m, in \u001b[0;36mBackendRegistry.resolve_backend\u001b[1;34m(self, backend)\u001b[0m\n\u001b[0;32m 368\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m gui \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m--> 369\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mbackend\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m is not a recognised backend name\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m 371\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m backend, gui \u001b[38;5;28;01mif\u001b[39;00m gui \u001b[38;5;241m!=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mheadless\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "\u001b[1;31mRuntimeError\u001b[0m: 'widget' is not a recognised backend name", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[1;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[21], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mget_ipython\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_line_magic\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mmatplotlib\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mwidget\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python313\\site-packages\\IPython\\core\\interactiveshell.py:2482\u001b[0m, in \u001b[0;36mInteractiveShell.run_line_magic\u001b[1;34m(self, magic_name, line, _stack_depth)\u001b[0m\n\u001b[0;32m 2480\u001b[0m kwargs[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mlocal_ns\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_local_scope(stack_depth)\n\u001b[0;32m 2481\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbuiltin_trap:\n\u001b[1;32m-> 2482\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 2484\u001b[0m \u001b[38;5;66;03m# The code below prevents the output from being displayed\u001b[39;00m\n\u001b[0;32m 2485\u001b[0m \u001b[38;5;66;03m# when using magics with decorator @output_can_be_silenced\u001b[39;00m\n\u001b[0;32m 2486\u001b[0m \u001b[38;5;66;03m# when the last Python token in the expression is a ';'.\u001b[39;00m\n\u001b[0;32m 2487\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(fn, magic\u001b[38;5;241m.\u001b[39mMAGIC_OUTPUT_CAN_BE_SILENCED, \u001b[38;5;28;01mFalse\u001b[39;00m):\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python313\\site-packages\\IPython\\core\\magics\\pylab.py:103\u001b[0m, in \u001b[0;36mPylabMagics.matplotlib\u001b[1;34m(self, line)\u001b[0m\n\u001b[0;32m 98\u001b[0m \u001b[38;5;28mprint\u001b[39m(\n\u001b[0;32m 99\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAvailable matplotlib backends: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 100\u001b[0m \u001b[38;5;241m%\u001b[39m _list_matplotlib_backends_and_gui_loops()\n\u001b[0;32m 101\u001b[0m )\n\u001b[0;32m 102\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m--> 103\u001b[0m gui, backend \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshell\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43menable_matplotlib\u001b[49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgui\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 104\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_show_matplotlib_backend(args\u001b[38;5;241m.\u001b[39mgui, backend)\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python313\\site-packages\\IPython\\core\\interactiveshell.py:3667\u001b[0m, in \u001b[0;36mInteractiveShell.enable_matplotlib\u001b[1;34m(self, gui)\u001b[0m\n\u001b[0;32m 3664\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mmatplotlib_inline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mbackend_inline\u001b[39;00m\n\u001b[0;32m 3666\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mIPython\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcore\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m pylabtools \u001b[38;5;28;01mas\u001b[39;00m pt\n\u001b[1;32m-> 3667\u001b[0m gui, backend \u001b[38;5;241m=\u001b[39m \u001b[43mpt\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfind_gui_and_backend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mgui\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpylab_gui_select\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 3669\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m gui \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m 3670\u001b[0m \u001b[38;5;66;03m# If we have our first gui selection, store it\u001b[39;00m\n\u001b[0;32m 3671\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpylab_gui_select \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python313\\site-packages\\IPython\\core\\pylabtools.py:349\u001b[0m, in \u001b[0;36mfind_gui_and_backend\u001b[1;34m(gui, gui_select)\u001b[0m\n\u001b[0;32m 347\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m 348\u001b[0m gui \u001b[38;5;241m=\u001b[39m _convert_gui_to_matplotlib(gui)\n\u001b[1;32m--> 349\u001b[0m backend, gui \u001b[38;5;241m=\u001b[39m \u001b[43mbackend_registry\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresolve_gui_or_backend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mgui\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 351\u001b[0m gui \u001b[38;5;241m=\u001b[39m _convert_gui_from_matplotlib(gui)\n\u001b[0;32m 352\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m gui, backend\n", + "File \u001b[1;32mc:\\Users\\Shanechka\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages\\matplotlib\\backends\\registry.py:409\u001b[0m, in \u001b[0;36mBackendRegistry.resolve_gui_or_backend\u001b[1;34m(self, gui_or_backend)\u001b[0m\n\u001b[0;32m 407\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mresolve_backend(gui_or_backend)\n\u001b[0;32m 408\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m: \u001b[38;5;66;03m# KeyError ?\u001b[39;00m\n\u001b[1;32m--> 409\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\n\u001b[0;32m 410\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mgui_or_backend\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m is not a recognised GUI loop or backend name\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[1;31mRuntimeError\u001b[0m: 'widget is not a recognised GUI loop or backend name" + ] + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "37da7d5e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAg0AAAH5CAYAAAAC8w0GAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAGfhJREFUeJzt3QuMFeX9+OF3AVnEulADsqBUQazYqoBQEWJEIylWYjRprLcUJSrV1EaKrULTQrQ1tN5qtDRoGkubar0keKlaDEWNUSkoSESrRJQKKgtay1WFCvPPO8nuj1UuX/xzOLvL8yTj7pmdcd8z57D7Yc68h5qiKIoEALAL7Xa1AQBAJhoAgBDRAACEiAYAIEQ0AAAhogEACBENAEBIh9TGbN26Nb3//vvpwAMPTDU1NdUeDgC0aPntmtavX5969eqV2rVrt29FQw6G3r17V3sYANCqrFixIh166KH7VjTkMwyNd76urq7awwGAFm3dunXlX7Ybf3/uU9HQ+JJEDgbRAAAxkZf0XQgJAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIDqR8Ozzz6bzjzzzNSrV69UU1OTHn744V3u88wzz6Tjjz8+1dbWpn79+qUZM2ZUcogAQEuIho0bN6YBAwakadOmhbZftmxZGj16dDr11FPTokWL0vjx49Oll16annzyyUoOEwAI6JAq6Dvf+U65RE2fPj316dMn3XLLLeXto48+Oj333HPpt7/9bRo1alQFRwoAtKprGubOnZtGjhzZbF2Ohbx+RzZt2pTWrVvXbAEA2ng0NDQ0pB49ejRbl2/nEPjkk0+2u8/UqVNTly5dmpbevXvvpdECwL6lRUXDlzFp0qS0du3apmXFihXVHhIAtEkVvaZhd9XX16dVq1Y1W5dv19XVpf3333+7++RZFnkBAPahMw3Dhg1Lc+bMabZu9uzZ5XoAoA1Hw4YNG8qpk3lpnFKZP1++fHnTSwtjxoxp2v7yyy9Pb7/9drrmmmvSG2+8kX7/+9+nBx54IP34xz+u5DABgGpHw0svvZQGDRpULtmECRPKzydPnlzeXrlyZVNAZHm65eOPP16eXcjv75CnXv7hD38w3RIAWoCaoiiK1IbkmRZ5FkW+KDJfCwEA7Jnfmy3qmgYAoOUSDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAlhMN06ZNS4cffnjq1KlTGjp0aJo/f/4Ot50xY0aqqalptuT9AIA2Hg33339/mjBhQpoyZUpauHBhGjBgQBo1alRavXr1Dvepq6tLK1eubFreeeedSg8TAKh2NNx6663psssuS2PHjk3f+MY30vTp01Pnzp3T3XffvcN98tmF+vr6pqVHjx6VHiYAUM1o2Lx5c1qwYEEaOXLk/33Ddu3K23Pnzt3hfhs2bEiHHXZY6t27dzrrrLPSa6+9tsNtN23alNatW9dsAQBaWTR8+OGHacuWLV84U5BvNzQ0bHefo446qjwL8cgjj6S//OUvaevWrWn48OHp3Xff3e72U6dOTV26dGlacmgAAPvA7Ilhw4alMWPGpIEDB6YRI0akmTNnpu7du6c777xzu9tPmjQprV27tmlZsWLFXh8zAOwLOlTyf96tW7fUvn37tGrVqmbr8+18rULEfvvtlwYNGpSWLl263a/X1taWCwDQis80dOzYMQ0ePDjNmTOnaV1+uSHfzmcUIvLLG4sXL049e/as4EgBgKqeacjydMuLLrooDRkyJJ1wwgnptttuSxs3bixnU2T5pYhDDjmkvDYhu/7669OJJ56Y+vXrl9asWZNuuummcsrlpZdeWumhAgDVjIZzzz03ffDBB2ny5MnlxY/5WoVZs2Y1XRy5fPnyckZFo//+97/lFM287Ve/+tXyTMULL7xQTtcEAKqnpiiKIrUhecplnkWRL4rMbxIFAOyZ35stbvYEANAyiQYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQMuJhmnTpqXDDz88derUKQ0dOjTNnz9/p9s/+OCDqX///uX2xx57bHriiSf2xjABgGpGw/33358mTJiQpkyZkhYuXJgGDBiQRo0alVavXr3d7V944YV0/vnnp0suuSS9/PLL6eyzzy6XV199tdJDBQB2oqYoiiJVUD6z8K1vfSv97ne/K29v3bo19e7dO/3oRz9KEydO/ML25557btq4cWN67LHHmtadeOKJaeDAgWn69Om7/H7r1q1LXbp0SWvXrk11dXV7+N4AQNuyO783K3qmYfPmzWnBggVp5MiR//cN27Urb8+dO3e7++T1226f5TMTO9p+06ZN5R3edgEA9ryKRsOHH36YtmzZknr06NFsfb7d0NCw3X3y+t3ZfurUqWUhNS75LAYAsOe1+tkTkyZNKk+pNC4rVqyo9pAAoE3qUMn/ebdu3VL79u3TqlWrmq3Pt+vr67e7T16/O9vX1taWCwDQis80dOzYMQ0ePDjNmTOnaV2+EDLfHjZs2Hb3yeu33T6bPXv2DrcHANrAmYYsT7e86KKL0pAhQ9IJJ5yQbrvttnJ2xNixY8uvjxkzJh1yyCHltQnZVVddlUaMGJFuueWWNHr06HTfffell156Kd11112VHioAUM1oyFMoP/jggzR58uTyYsY8dXLWrFlNFzsuX768nFHRaPjw4enee+9NP//5z9PPfvazdOSRR6aHH344HXPMMZUeKgBQzfdp2Nu8TwMAtML3aQAA2g7RAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQPWj4aOPPkoXXnhhqqurS127dk2XXHJJ2rBhw073OeWUU1JNTU2z5fLLL6/kMAGAgA6pgnIwrFy5Ms2ePTv973//S2PHjk3jxo1L99577073u+yyy9L111/fdLtz586VHCYAUM1oeP3119OsWbPSiy++mIYMGVKuu+OOO9IZZ5yRbr755tSrV68d7psjob6+vlJDAwBa0ssTc+fOLV+SaAyGbOTIkaldu3Zp3rx5O933nnvuSd26dUvHHHNMmjRpUvr44493uO2mTZvSunXrmi0AQCs609DQ0JAOPvjg5t+sQ4d00EEHlV/bkQsuuCAddthh5ZmIV155JV177bVpyZIlaebMmdvdfurUqem6667b4+MHAP4/o2HixInpN7/5zS5fmviy8jUPjY499tjUs2fPdNppp6W33norHXHEEV/YPp+JmDBhQtPtfKahd+/eX/r7AwB7KBquvvrqdPHFF+90m759+5bXJKxevbrZ+s8++6ycUbE71ysMHTq0/Lh06dLtRkNtbW25AAAtLBq6d+9eLrsybNiwtGbNmrRgwYI0ePDgct1TTz2Vtm7d2hQCEYsWLSo/5jMOAEAbvBDy6KOPTqeffno5fXL+/Pnp+eefT1deeWU677zzmmZOvPfee6l///7l17P8EsQvf/nLMjT+/e9/p0cffTSNGTMmnXzyyem4446r1FABgGq/uVOeBZGjIF+TkKdannTSSemuu+5q+np+74Z8kWPj7IiOHTumf/zjH+nb3/52uV9+KeS73/1u+tvf/lbJYQIAATVFURSpDckXQnbp0iWtXbu2fCdKAGDP/N70b08AACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwBQ3Wi44YYb0vDhw1Pnzp1T165dQ/sURZEmT56cevbsmfbff/80cuTI9Oabb1ZqiABAS4iGzZs3p3POOSddccUV4X1uvPHGdPvtt6fp06enefPmpQMOOCCNGjUqffrpp5UaJgAQVFPkv95X0IwZM9L48ePTmjVrdrpdHkavXr3S1VdfnX7yk5+U69auXZt69OhR/j/OO++80Pdbt25d6tKlS7lvXV3dHrkPANBW7c7vzRZzTcOyZctSQ0ND+ZJEo3wnhg4dmubOnbvD/TZt2lTe4W0XAGDPazHRkIMhy2cWtpVvN35te6ZOnVrGRePSu3fvio8VAPZFuxUNEydOTDU1NTtd3njjjbQ3TZo0qTyl0risWLFir35/ANhXdNidjfP1BhdffPFOt+nbt++XGkh9fX35cdWqVeXsiUb59sCBA3e4X21tbbkAAC0oGrp3714uldCnT58yHObMmdMUCfn6hDyLYndmYAAAreyahuXLl6dFixaVH7ds2VJ+npcNGzY0bdO/f//00EMPlZ/nlzbyLItf/epX6dFHH02LFy9OY8aMKWdUnH322ZUaJgBQiTMNuyO/SdOf/vSnptuDBg0qPz799NPplFNOKT9fsmRJeR1Co2uuuSZt3LgxjRs3rpyiedJJJ6VZs2alTp06VWqYAEBLeZ+Gvc37NABAG3+fBgCgZRMNAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACGiAQAIEQ0AQIhoAABCRAMAECIaAIAQ0QAAhIgGACBENAAAIaIBAAgRDQBAiGgAAEJEAwAQIhoAgBDRAACEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAIR0SG1MURTlx3Xr1lV7KADQ4jX+vmz8/blPRcP69evLj7179672UACgVf3+7NKly063qSkiadGKbN26Nb3//vvpwAMPTDU1Naml1VyOmRUrVqS6urpqD2ef4/hXl+NffR6D6lrXQo9/zoAcDL169Urt2rXbt8405Dt86KGHppYsP1la0hNmX+P4V5fjX30eg+qqa4HHf1dnGBq5EBIACBENAECIaNiLamtr05QpU8qP7H2Of3U5/tXnMaiu2jZw/NvchZAAQGU40wAAhIgGACBENAAAIaIBAAgRDQBAiGiosBtuuCENHz48de7cOXXt2jW0T57QMnny5NSzZ8+0//77p5EjR6Y333yz4mNtiz766KN04YUXlu++lo//JZdckjZs2LDTfU455ZTyLci3XS6//PK9NubWbNq0aenwww9PnTp1SkOHDk3z58/f6fYPPvhg6t+/f7n9sccem5544om9Nta2ancegxkzZnzhuZ73Y/c9++yz6cwzzyzfijkfx4cffniX+zzzzDPp+OOPL6dg9uvXr3w8WjrRUGGbN29O55xzTrriiivC+9x4443p9ttvT9OnT0/z5s1LBxxwQBo1alT69NNPKzrWtigHw2uvvZZmz56dHnvssfIP9rhx43a532WXXZZWrlzZtOTHhJ27//7704QJE8p56AsXLkwDBgwon7erV6/e7vYvvPBCOv/888uQe/nll9PZZ59dLq+++upeH/u++hhkOai3fa6/8847e3XMbcXGjRvL452jLWLZsmVp9OjR6dRTT02LFi1K48ePT5deeml68sknU4uW36eByvvjH/9YdOnSZZfbbd26taivry9uuummpnVr1qwpamtri7/+9a8VHmXb8q9//Su/B0nx4osvNq37+9//XtTU1BTvvffeDvcbMWJEcdVVV+2lUbYdJ5xwQvHDH/6w6faWLVuKXr16FVOnTt3u9t/73veK0aNHN1s3dOjQ4gc/+EHFx9pW7e5jEP25xO5JKRUPPfTQTre55pprim9+85vN1p177rnFqFGjipbMmYYWJtdnQ0ND+ZLEtv+QSD7NOHfu3KqOrbXJxyu/JDFkyJCmdfm45n/ULJ/B2Zl77rkndevWLR1zzDFp0qRJ6eOPP94LI27dZ9QWLFjQ7Hmbj3O+vaPnbV6/7fZZ/lux5/neewyy/HLdYYcdVv7ri2eddVZ5Zo7Km9tKn/9t7l+5bO1yMGQ9evRotj7fbvwaMfl4HXzwwc3WdejQIR100EE7PZYXXHBB+UM0vzb5yiuvpGuvvTYtWbIkzZw5cy+MunX68MMP05YtW7b7vH3jjTe2u09+DDzPq/sYHHXUUenuu+9Oxx13XFq7dm26+eaby2uwcji09H8tuLVr2MHzP//z2Z988kl5PVtL5EzDlzBx4sQvXDz0+WVHf0hp+cc/X/OQiz9fmJevifjzn/+cHnroofTWW2/t0fsB1TZs2LA0ZsyYNHDgwDRixIgyjLt3757uvPPOag+NFsqZhi/h6quvThdffPFOt+nbt++X+n/X19eXH1etWlXOnmiUb+c/2MSPfz6Wn78A7LPPPitnVDQe54j80lC2dOnSdMQRR3zJUbdt+aWc9u3bl8/TbeXbOzrWef3ubM+efww+b7/99kuDBg0qn+tUVv0Onv/5wtSWepYhEw1fQi7xvFRCnz59yifTnDlzmiIhn67Kr8HvzgyMtix6/PPfotasWVO+zjt48OBy3VNPPZW2bt3aFAIR+crmbNuIo7mOHTuWxzg/b/MMiCwf53z7yiuv3OHjk7+erxpvlGe55PXsncfg8/LLG4sXL05nnHFGhUfLsGHDvjDFuFU8/6t9JWZb98477xQvv/xycd111xVf+cpXys/zsn79+qZtjjrqqGLmzJlNt3/9618XXbt2LR555JHilVdeKc4666yiT58+xSeffFKle9F6nX766cWgQYOKefPmFc8991xx5JFHFueff37T1999993y+OevZ0uXLi2uv/764qWXXiqWLVtWPgZ9+/YtTj755Crei9bhvvvuK2f5zJgxo5y5Mm7cuPJ53NDQUH79+9//fjFx4sSm7Z9//vmiQ4cOxc0331y8/vrrxZQpU4r99tuvWLx4cRXvxb71GOSfS08++WTx1ltvFQsWLCjOO++8olOnTsVrr71WxXvROq1fv77p53v+1XrrrbeWn+ffAVk+7vn4N3r77beLzp07Fz/96U/L5/+0adOK9u3bF7NmzSpaMtFQYRdddFH5BPr88vTTTzdtk2/nqU/bTrv8xS9+UfTo0aP8AXDaaacVS5YsqdI9aN3+85//lJGQg62urq4YO3Zss2DLYbDt47F8+fIyEA466KDy2Pfr16/8Q7127doq3ovW44477ii+9rWvFR07diyn//3zn/9sNpU1/3nY1gMPPFB8/etfL7fP088ef/zxKox6330Mxo8f37Rt/nlzxhlnFAsXLqzSyFu3p59+ers/6xuPd/6Yj//n9xk4cGB5/PNfTrb9PdBS1eT/VPtsBwDQ8pk9AQCEiAYAIEQ0AAAhogEACBENAECIaAAAQkQDABAiGgCAENEAAISIBgAgRDQAACni/wG0ETR2GfNTBgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.animation import FuncAnimation\n", + "\n", + "L = 10.0\n", + "g = 9.81\n", + "Omega = 7.292115e-5\n", + "phi = np.deg2rad(55)\n", + "\n", + "omega0 = np.sqrt(g / L)\n", + "omega_p = Omega * np.sin(phi)\n", + "\n", + "dt = 0.05\n", + "t = np.arange(0, 500, dt)\n", + "\n", + "A = 1.0\n", + "x = A * np.cos(omega0 * t) * np.cos(omega_p * t)\n", + "y = A * np.cos(omega0 * t) * np.sin(omega_p * t)\n", + "\n", + "fig, ax = plt.subplots(figsize=(6, 6))\n", + "ax.set_aspect('equal')\n", + "ax.set_xlim(-1.2*A, 1.2*A)\n", + "ax.set_ylim(-1.2*A, 1.2*A)\n", + "\n", + "line, = ax.plot([], [], lw=2)\n", + "point, = ax.plot([], [], 'ro')\n", + "\n", + "trail_x, trail_y = [], []\n", + "\n", + "def update(frame):\n", + " trail_x.append(x[frame])\n", + " trail_y.append(y[frame])\n", + " line.set_data(trail_x, trail_y)\n", + " point.set_data([x[frame]], [y[frame]])\n", + " return line, point\n", + "\n", + "ani = FuncAnimation(fig, update, frames=len(t), interval=30)\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "b5f95296", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

ТЕСТ

" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from IPython.display import HTML\n", + "HTML(\"

ТЕСТ

\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea929ebd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Vector2D(abscissa=2, ordinate=1)\n" + ] + }, + { + "ename": "TypeError", + "evalue": "__str__ returned non-string (type NoneType)", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[1], line 118\u001b[0m\n\u001b[0;32m 115\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mconj\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[0;32m 116\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m Vector2D(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mabscissa, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mordinate \u001b[38;5;241m*\u001b[39m \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m)\n\u001b[1;32m--> 118\u001b[0m \u001b[38;5;28;43mprint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mVector2D\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m2\u001b[39;49m\u001b[43m,\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[1;31mTypeError\u001b[0m: __str__ returned non-string (type NoneType)" + ] + } + ], + "source": [ + "from dataclasses import dataclass\n", + "from math import acos, isclose\n", + "\n", + "\n", + "@dataclass(eq=False, init = False)\n", + "class Vector2D:\n", + " _abscissa: float\n", + " _ordinate: float \n", + "\n", + " def __init__(self, abscissa: float = 0., ordinate: float= 0.):\n", + " self._abscissa = abscissa\n", + " self._ordinate = ordinate\n", + " \n", + " \n", + " def __repr__(self):\n", + " return (f\"Vector2D(abscissa={self._abscissa}, ordinate={self._ordinate})\")\n", + "\n", + " @property\n", + " def abscissa(self):\n", + " return self._abscissa\n", + "\n", + " @property\n", + " def ordinate(self):\n", + " return self._ordinate\n", + "\n", + " def __ne__(self, other: \"Vector2D\"):\n", + " return not (self == other)\n", + "\n", + " def __eq__(self, other):\n", + " if not isinstance(other, Vector2D):\n", + " return NotImplemented\n", + " return isclose(self.abscissa, other.abscissa, rel_tol=1e-9, abs_tol=1e-10) and isclose(\n", + " self.ordinate, other.ordinate, rel_tol=1e-9, abs_tol=1e-10)\n", + "\n", + " def __lt__(self, other):\n", + " if not isinstance(other, Vector2D):\n", + " return NotImplemented\n", + " return (\n", + " self.abscissa < other.abscissa\n", + " and not (isclose(self.abscissa, other.abscissa, rel_tol=1e-9, abs_tol=1e-10))\n", + " ) or (\n", + " isclose(self.abscissa, other.abscissa, rel_tol=1e-9, abs_tol=1e-10)\n", + " and self.ordinate < other.ordinate\n", + " and not (isclose(self.ordinate, other.ordinate)))\n", + "\n", + " def __le__(self, other):\n", + " return self == other or self < other\n", + "\n", + " def __gt__(self, other):\n", + " return not (self <= other)\n", + "\n", + " def __ge__(self, other):\n", + " return not (self < other)\n", + "\n", + " def __abs__(self):\n", + " return (self.abscissa**2 + self.ordinate**2) ** 0.5\n", + "\n", + " def __bool__(self):\n", + " return not (isclose(abs(self), 0, abs_tol=1e-12))\n", + "\n", + " def __mul__(self, other):\n", + " if isinstance(other, (int, float)):\n", + " return Vector2D(self.abscissa * other, self.ordinate * other)\n", + " return NotImplemented\n", + "\n", + " def __rmul__(self, other):\n", + " return self * other\n", + "\n", + " def __truediv__(self, other):\n", + " if isinstance(other, (int, float)):\n", + " return Vector2D(self.abscissa / other, self.ordinate / other)\n", + " return NotImplemented\n", + "\n", + " def __add__(self, other):\n", + " if isinstance(other, Vector2D):\n", + " return Vector2D(self.abscissa + other.abscissa, self.ordinate + other.ordinate)\n", + " if isinstance(other, (int, float)):\n", + " return Vector2D(self.abscissa + other, self.ordinate + other)\n", + " return NotImplemented\n", + "\n", + " def __radd__(self, other):\n", + " return self + other\n", + "\n", + " def __sub__(self, other):\n", + " if isinstance(other, Vector2D):\n", + " return Vector2D(self.abscissa - other.abscissa, self.ordinate - other.ordinate)\n", + " if isinstance(other, (int, float)):\n", + " return Vector2D(self.abscissa - other, self.ordinate - other)\n", + " return NotImplemented\n", + "\n", + " def __neg__(self):\n", + " return self * -1\n", + "\n", + " def __float__(self):\n", + " return abs(self)\n", + "\n", + " def __int__(self):\n", + " return int(abs(self))\n", + "\n", + " def __complex__(self):\n", + " return complex(self.abscissa, self.ordinate)\n", + "\n", + " def __matmul__(self, other: \"Vector2D\"):\n", + " if not isinstance(other, Vector2D):\n", + " return NotImplemented\n", + " return self.abscissa * other.abscissa + self.ordinate * other.ordinate\n", + "\n", + " def get_angle(self, other: \"Vector2D\") -> float:\n", + " if not isinstance(other, Vector2D):\n", + " raise TypeError(\"Other must be Vector2D\")\n", + " if isclose(abs(other), 0) or isclose(abs(self), 0):\n", + " raise ValueError(\"You cannot get angle in between given vector and a zero vector\")\n", + " return acos((self @ other) / (abs(self) * abs(other)))\n", + "\n", + " def conj(self):\n", + " return Vector2D(self.abscissa, self.ordinate * -1)\n", + "\n", + "print(Vector2D(2,1))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "393c431a", + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "unsupported operand type(s) for /: 'str' and 'int'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[2], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mabcabcabc\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m/\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m3\u001b[39;49m\n", + "\u001b[1;31mTypeError\u001b[0m: unsupported operand type(s) for /: 'str' and 'int'" + ] + } + ], + "source": [ + "\"abcabcabc\" / 3" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "e10ab248", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'abc'" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "class Strdel(str):\n", + "\n", + " def __truediv__(self, other):\n", + " if not (isinstance(other, int)):\n", + " return NotImplemented\n", + " \n", + " if other <=0:\n", + " raise ValueError\n", + " \n", + " if not ((len(self)/ other).is_integer) or (len(self) // other) == 0:\n", + " return NotImplemented\n", + " \n", + " part = self[:len(self) // other]\n", + " if part * other == self:\n", + " return Strdel(part)\n", + " \n", + " return NotImplemented\n", + "stroka = Strdel(\"abcabc\")\n", + "stroka / 2" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "6f5aede6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'abcabcabcabc'" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "stroka * 2" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "044780de", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1\n", + "1 2\n", + "2 3\n", + "3 4\n" + ] + } + ], + "source": [ + "def ar(arrr):\n", + " arrr.append(4)\n", + "arr = [1,2,3]\n", + "ar(arr)\n", + "for i, j in enumerate(arr):\n", + " print(i,j)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "f4e7c72e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10\n" + ] + } + ], + "source": [ + "x = 10\n", + "\n", + "def func():\n", + " global x\n", + "\n", + " print(x) # Казалось бы, должна взяться глобальная x\n", + " x = 5 # НО: наличие этой строки делает x локальной во всей функции\n", + "func()\n", + "# Ошибка: UnboundLocalError: local variable 'x' referenced before assignment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3e7f0e78", + "metadata": {}, + "outputs": [], + "source": [ + "enumerate" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "e5ee788d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4: Алексей\n", + "5: Мария\n", + "6: Иван\n" + ] + } + ], + "source": [ + "class MyEnumerate:\n", + " def __init__(self, iterable, start=0):\n", + " # Сохраняем итератор из переданного объекта\n", + " self.iterator = iter(iterable)\n", + " self.count = start\n", + "\n", + " def __iter__(self):\n", + " # Итератор должен возвращать самого себя\n", + " return self\n", + "\n", + " def __next__(self):\n", + " # 1. Получаем следующее значение из вложенного итератора\n", + " # Если элементы закончатся, iter() сам выбросит StopIteration,\n", + " # и наш генератор тоже остановится.\n", + " value = next(self.iterator)\n", + " \n", + " # 2. Формируем текущий результат\n", + " result = (self.count, value)\n", + " \n", + " # 3. Увеличиваем счетчик для следующего шага\n", + " self.count += 1\n", + " \n", + " return result\n", + "\n", + "# Проверка:\n", + "names = [\"Алексей\", \"Мария\", \"Иван\"]\n", + "for idx, name in MyEnumerate(names, start=4):\n", + " print(f\"{idx}: {name}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7d8d1a8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n" + ] + } + ], + "source": [ + "def giga_any(iterable):\n", + " iterable = iter(iterable)\n", + " count = 0\n", + " for item in iterable:\n", + " count+=1\n", + " if item:\n", + " return item\n", + " if count == 0:\n", + " return False\n", + " return item\n", + "print(giga_any([0,1]))\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "id": "8e5dbb01", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "range(6)[1]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "487e59ab", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n", + "5\n" + ] + }, + { + "data": { + "text/plain": [ + "array([[[0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.]],\n", + "\n", + " [[0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.]],\n", + "\n", + " [[0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.]]])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "\n", + "# Создаем матрицу 3x5 (3 строки, 5 столбцов)\n", + "matrix = np.zeros((3, 5,5))\n", + "\n", + "print(matrix.shape[0]) # Выведет: 3 (строки)\n", + "print(matrix.shape[1]) \n", + "matrix # Выведет: 5 (столбцы)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "241b61a0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.True_" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "diagram_type = np.array([\"hist\",\"violin\",\"box\"])\n", + "arr2 = arr.copy()\n", + "diagram_type.sort()\n", + "(diagram_type == [\"hist\", \"box\", \"violin\"]).any()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "22c6a436", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "''" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4beb7c3d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc903181", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4cdde85", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/.gitignore b/.gitignore index cececc15..bd573544 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ __pycache__ # Python Files *solved.ipynb +.github\workflows\trying.ipynb.github\workflows\trying.ipynb \ No newline at end of file diff --git a/conditions/sem01/lesson05/tasks.md b/conditions/sem01/lesson05/tasks.md index a608c0dd..a3593355 100644 --- a/conditions/sem01/lesson05/tasks.md +++ b/conditions/sem01/lesson05/tasks.md @@ -5,7 +5,11 @@ Ваша задача — определить, является ли заданная строка палиндромом. +<<<<<<< HEAD:conditions/lesson05/tasks.md +Допишите код в файле [task1](https://github.com/EvgrafovMichail/python_mipt_dafe_tasks/blob/main/solutions/lesson05/task1.py) +======= Допишите код в файле [task1](https://github.com/EvgrafovMichail/python_mipt_dafe_tasks/blob/main/solutions/sem01/lesson05/task1.py). +>>>>>>> 7ba22f9a471a0b84a580183fed2466942f0104d2:conditions/sem01/lesson05/tasks.md **Входные данные:** - `text` — строка, состоящая из букв английского алфавита в верхнем и нижнем регистре длиной от 0 до 1000. diff --git a/conditions/sem01/lesson11/task.md b/conditions/sem01/lesson11/task.md index c783b137..d2a268ae 100644 --- a/conditions/sem01/lesson11/task.md +++ b/conditions/sem01/lesson11/task.md @@ -21,7 +21,7 @@ ``` - При использовании объекта типа `Vector2D` в качестве аргумента функции `print()` в консоль должна печататься строка, представляющая собой команду создания данного объекта. Пример: - ```python + ```pythonV vector = Vector2D(1, 3) print(vector) # Vector2D(abscissa=1, ordinate=3) diff --git a/deprecated_tests/sem01/tests/test_lesson02_tasks.py b/deprecated_tests/sem01/tests/test_lesson02_tasks.py index f11403f4..b7febe4b 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 4110bdcc..c98b6f22 100644 --- a/deprecated_tests/sem01/tests/test_lesson04_tasks.py +++ b/deprecated_tests/sem01/tests/test_lesson04_tasks.py @@ -1,6 +1,7 @@ -import pytest import random +import pytest + 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 @@ -8,62 +9,89 @@ from solutions.sem01.lesson04.task5 import find_row_with_most_ones from solutions.sem01.lesson04.task6 import count_cycles -@pytest.mark.parametrize("lst, expected", [ - pytest.param([], True, id="empty_list"), - pytest.param([5], True, id="single_element"), - pytest.param([1, 3], True, id="two_elements"), - pytest.param([3, 1], True, id="two_elements_unsorted"), - pytest.param([1, 3, 5, 7], True, id="already_sorted_ap"), - pytest.param([3, 1, 5, 7], True, id="unsorted_ap"), - pytest.param([1, 2, 4], False, id="not_ap"), - pytest.param([10, 5, 0, -5], True, id="negative_difference"), - 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.mark.parametrize( + "lst, expected", + [ + pytest.param([], True, id="empty_list"), + pytest.param([5], True, id="single_element"), + pytest.param([1, 3], True, id="two_elements"), + pytest.param([3, 1], True, id="two_elements_unsorted"), + pytest.param([1, 3, 5, 7], True, id="already_sorted_ap"), + pytest.param([3, 1, 5, 7], True, id="unsorted_ap"), + pytest.param([1, 2, 4], False, id="not_ap"), + pytest.param([10, 5, 0, -5], True, id="negative_difference"), + 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"), + ], +) def test_is_arithmetic_progression_parametrized(lst, expected): if len(lst) > 500: random.shuffle(lst) assert is_arithmetic_progression(lst) == expected -@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([[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.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([[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"), + ], +) def test_merge_intervals(intervals, expected): assert merge_intervals(intervals) == expected -@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"), - pytest.param([1], 1, id="single_element"), - 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.mark.parametrize( + "nums, expected", + [ + pytest.param([2, 2, 1], 1, id="simple_case"), + pytest.param([4, 1, 2, 1, 2], 4, id="middle_single"), + pytest.param([1], 1, id="single_element"), + 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", + ), + ], +) def test_find_single_number(nums, expected): assert find_single_number(nums) == expected -@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"), - pytest.param([1, 2, 3], [1, 2, 3], 3, id="no_zeros"), - pytest.param([0, 0, 0], [0, 0, 0], 0, id="all_zeros"), - pytest.param([1, 0, 2, 0, 3, 0], [1, 2, 3, 0, 0, 0], 3, id="interleaved"), - pytest.param([], [], 0, id="empty"), - pytest.param([0], [0], 0, id="single_zero"), - pytest.param([42], [42], 1, id="single_nonzero"), -]) + +@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"), + pytest.param([1, 2, 3], [1, 2, 3], 3, id="no_zeros"), + pytest.param([0, 0, 0], [0, 0, 0], 0, id="all_zeros"), + pytest.param([1, 0, 2, 0, 3, 0], [1, 2, 3, 0, 0, 0], 3, id="interleaved"), + pytest.param([], [], 0, id="empty"), + pytest.param([0], [0], 0, id="single_zero"), + pytest.param([42], [42], 1, id="single_nonzero"), + ], +) def test_move_zeros_to_end_parametrized(input_list, expected_list, expected_index): arr = input_list[:] result_index = move_zeros_to_end(arr) @@ -71,89 +99,54 @@ def test_move_zeros_to_end_parametrized(input_list, expected_list, expected_inde assert result_index == expected_index -@pytest.mark.parametrize("matrix, expected_row", [ - pytest.param( - [[0, 0, 1, 1], - [0, 1, 1, 1], - [0, 0, 0, 1], - [1, 1, 1, 1], - [0, 1, 1, 1]], - 3, - id="classic" - ), - pytest.param( - [[0, 0, 0], - [0, 0, 0], - [0, 0, 0]], - 0, - id="all_zeros" - ), - pytest.param( - [[1, 1, 1], - [1, 1, 1], - [1, 1, 1]], - 0, - id="all_ones_first" - ), - pytest.param( - [[0, 1], - [1, 1]], - 1, - id="two_rows" - ), - pytest.param( - [[0]], - 0, - id="single_zero" - ), - pytest.param( - [[1]], - 0, - id="single_one" - ), - pytest.param( - [], - 0, - id="empty_matrix" - ), - pytest.param( - [[0, 0, 1], - [0, 1, 1], - [0, 1, 1]], - 1, - id="tie" - ), -]) +@pytest.mark.parametrize( + "matrix, expected_row", + [ + pytest.param( + [[0, 0, 1, 1], [0, 1, 1, 1], [0, 0, 0, 1], [1, 1, 1, 1], [0, 1, 1, 1]], 3, id="classic" + ), + pytest.param([[0, 0, 0], [0, 0, 0], [0, 0, 0]], 0, id="all_zeros"), + pytest.param([[1, 1, 1], [1, 1, 1], [1, 1, 1]], 0, id="all_ones_first"), + pytest.param([[0, 1], [1, 1]], 1, id="two_rows"), + pytest.param([[0]], 0, id="single_zero"), + pytest.param([[1]], 0, id="single_one"), + pytest.param([], 0, id="empty_matrix"), + pytest.param([[0, 0, 1], [0, 1, 1], [0, 1, 1]], 1, id="tie"), + ], +) def test_find_row_with_most_ones(matrix, expected_row): assert find_row_with_most_ones(matrix) == expected_row def test_find_row_with_most_ones_big_data(): size = 10000 - matrix = [[0]*size for i in range(size)] - matrix[size-1][size-1] = 1 + matrix = [[0] * size for i in range(size)] + matrix[size - 1][size - 1] = 1 for i in range(50): assert find_row_with_most_ones(matrix) == 9999 size = 10000 - matrix = [[1]*size for i in range(size)] + matrix = [[1] * size for i in range(size)] matrix[0][0] = 0 for i in range(50): 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 72ad6bc8..a43a2a45 100644 --- a/deprecated_tests/sem01/tests/test_lesson05_tasks.py +++ b/deprecated_tests/sem01/tests/test_lesson05_tasks.py @@ -1,4 +1,4 @@ -import pytest +import pytest from solutions.sem01.lesson05.task1 import is_palindrome from solutions.sem01.lesson05.task2 import are_anagrams @@ -7,145 +7,166 @@ 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"), - pytest.param("aa", True, id="two_same"), - pytest.param("ab", False, id="two_different"), - pytest.param("aba", True, id="odd_palindrome"), - pytest.param("abba", True, id="even_palindrome"), - pytest.param("abcba", True, id="long_odd_palindrome"), - pytest.param("abccba", True, id="long_even_palindrome"), - pytest.param("abc", False, id="not_palindrome"), - pytest.param("Aa", True, id="case_sensitive_mismatch"), - pytest.param("Racecar", True, id="real_word_case_sensitive"), - pytest.param("aA", True, id="reverse_case"), - pytest.param("abcdefedcba", True, id="long_true"), - pytest.param("abcdefedcbx", False, id="long_false"), -]) + +@pytest.mark.parametrize( + "s, expected", + [ + pytest.param("", True, id="empty_string"), + pytest.param("a", True, id="single_char"), + pytest.param("aa", True, id="two_same"), + pytest.param("ab", False, id="two_different"), + pytest.param("aba", True, id="odd_palindrome"), + pytest.param("abba", True, id="even_palindrome"), + pytest.param("abcba", True, id="long_odd_palindrome"), + pytest.param("abccba", True, id="long_even_palindrome"), + pytest.param("abc", False, id="not_palindrome"), + pytest.param("Aa", True, id="case_sensitive_mismatch"), + pytest.param("Racecar", True, id="real_word_case_sensitive"), + pytest.param("aA", True, id="reverse_case"), + pytest.param("abcdefedcba", True, id="long_true"), + pytest.param("abcdefedcbx", False, id="long_false"), + ], +) 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"), - pytest.param("a", "a", True, id="single_char_same"), - pytest.param("A", "A", True, id="single_upper_same"), - pytest.param("A", "a", False, id="case_sensitive_diff"), - pytest.param("Listen", "Silent", False, id="mixed_case_not_anagram"), - pytest.param("Aa", "aA", True, id="same_chars_permuted"), - pytest.param("Ab", "ab", False, id="one_letter_case_diff"), - pytest.param("abc", "cba", True, id="permuted_same_case"), - pytest.param("abc", "Cba", False, id="case_breaks_anagram"), - pytest.param("aabbcc", "abcabc", True, id="repeated_letters"), - pytest.param("aabbcc", "aabbcd", False, id="extra_different_char"), -]) +@pytest.mark.parametrize( + "w1, w2, expected", + [ + pytest.param("listen", "silent", True, id="classic_anagram"), + pytest.param("evil", "vile", True, id="another_anagram"), + pytest.param("a", "a", True, id="single_char_same"), + pytest.param("A", "A", True, id="single_upper_same"), + pytest.param("A", "a", False, id="case_sensitive_diff"), + pytest.param("Listen", "Silent", False, id="mixed_case_not_anagram"), + pytest.param("Aa", "aA", True, id="same_chars_permuted"), + pytest.param("Ab", "ab", False, id="one_letter_case_diff"), + pytest.param("abc", "cba", True, id="permuted_same_case"), + pytest.param("abc", "Cba", False, id="case_breaks_anagram"), + pytest.param("aabbcc", "abcabc", True, id="repeated_letters"), + pytest.param("aabbcc", "aabbcd", False, id="extra_different_char"), + ], +) def test_are_anagrams_linear(w1, w2, expected): assert are_anagrams(w1, w2) == expected -@pytest.mark.parametrize("s, expected", [ - pytest.param("!!!", True, id="only_exclamations"), - pytest.param("...?", True, id="dots_and_question"), - pytest.param("", False, id="empty_string"), - pytest.param("a", False, id="letter"), - pytest.param("1", False, id="digit"), - pytest.param(" ! ", False, id="space_inside"), - pytest.param("!?.", True, id="symbols_only"), - pytest.param("!a!", False, id="letter_in_middle"), - pytest.param(" ", False, id="only_space"), - pytest.param(".,;", True, id="commas_dots_semicolons"), - pytest.param("", False, id="commas_dots_semicolons"), -]) +@pytest.mark.parametrize( + "s, expected", + [ + pytest.param("!!!", True, id="only_exclamations"), + pytest.param("...?", True, id="dots_and_question"), + pytest.param("", False, id="empty_string"), + pytest.param("a", False, id="letter"), + pytest.param("1", False, id="digit"), + pytest.param(" ! ", False, id="space_inside"), + pytest.param("!?.", True, id="symbols_only"), + pytest.param("!a!", False, id="letter_in_middle"), + pytest.param(" ", False, id="only_space"), + pytest.param(".,;", True, id="commas_dots_semicolons"), + pytest.param("", False, id="commas_dots_semicolons"), + ], +) 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"), - pytest.param("Hello", "Hello", id="star_one"), - pytest.param("xyz", "xyz", id="no_compression"), - pytest.param("", "", id="empty_input"), - pytest.param("Test*2 Space", "TestTestSpace", id="mixed"), - pytest.param("a*10", "aaaaaaaaaa", id="ten_a"), - pytest.param("x y z", "xyz", id="three_plain"), - pytest.param("Word word", "Wordword", id="case_sensitive"), -]) + +@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"), + pytest.param("Hello", "Hello", id="star_one"), + pytest.param("xyz", "xyz", id="no_compression"), + pytest.param("", "", id="empty_input"), + pytest.param("Test*2 Space", "TestTestSpace", id="mixed"), + pytest.param("a*10", "aaaaaaaaaa", id="ten_a"), + pytest.param("x y z", "xyz", id="three_plain"), + pytest.param("Word word", "Wordword", id="case_sensitive"), + ], +) 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"), - pytest.param("d", "abc", False, id="d_letters_instead_of_digits"), - pytest.param("d", "", False, id="d_empty_string"), - pytest.param("w", "hello", True, id="w_lowercase_word"), - pytest.param("w", "HelloWorld", True, id="w_mixed_case_word"), - pytest.param("w", "hello123", False, id="w_word_with_digits"), - pytest.param("w", "", False, id="w_empty_string"), - pytest.param("s", "abc123", True, id="s_alphanum"), - pytest.param("s", "ABC99", True, id="s_uppercase_and_digits"), - pytest.param("s", "abc_123", False, id="s_contains_underscore"), - pytest.param("s", "", False, id="s_empty_string"), - pytest.param("d-d", "12-34", True, id="d_dash_d_valid"), - pytest.param("d-d", "12--34", False, id="d_dash_d_double_dash"), - pytest.param("d-d", "12-abc", False, id="d_dash_d_letters_after_dash"), - pytest.param("d-d", "1234", False, id="d_dash_d_missing_dash"), - pytest.param("w.w", "hi.there", True, id="w_dot_w_valid"), - pytest.param("w.w", "hi..there", False, id="w_dot_w_double_dot"), - pytest.param("w.w", "hi1.there", False, id="w_dot_w_digit_in_first_word"), - pytest.param("s.s", "h1i.th32ere", True, id="s_dot_s_valid"), - pytest.param("s.s", "hi4..t2here", False, id="s_dot_s_double_dot"), - pytest.param("d-dw", "12-45abc", True, id="example_valid"), - pytest.param("d-dw", "1-abs", False, id="example_second_part_not_digit"), - pytest.param("d-dw", "1-b123r", False, id="example_letter_after_dash"), - pytest.param("d-dw", "1--123vdg", False, id="example_double_dash"), - pytest.param("d-dw", "123-456XYZ", True, id="d-dw_all_caps"), - pytest.param("d-dw", "0-0a", True, id="d-dw_minimal_valid"), - pytest.param("d@d", "5@7", True, id="d_at_d_valid"), - pytest.param("d@d", "5@@7", False, id="d_at_d_double_at"), - pytest.param("w s", "hi 123", True, id="w_space_s_valid"), - pytest.param("w s", "hi123", False, id="w_space_s_missing_space"), - pytest.param("w s", "hi 123!", False, id="w_space_s_extra_char_in_s"), - pytest.param("", "", True, id="empty_regexp_empty_string"), - pytest.param("", "a", False, id="empty_regexp_non_empty_string"), - pytest.param("d", "", False, id="non_empty_regexp_empty_string"), - pytest.param("d!", "5!", True, id="d_exclam_valid"), - pytest.param("d!", "5", False, id="d_exclam_missing_exclam"), - pytest.param("d!", "5!!", False, id="d_exclam_extra_exclam"), - pytest.param("s", "a1", True, id="s_letter_digit"), - 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.mark.parametrize( + "regexp, s, expected", + [ + pytest.param("d", "123", True, id="d_valid_number"), + pytest.param("d", "0", True, id="d_zero"), + pytest.param("d", "abc", False, id="d_letters_instead_of_digits"), + pytest.param("d", "", False, id="d_empty_string"), + pytest.param("w", "hello", True, id="w_lowercase_word"), + pytest.param("w", "HelloWorld", True, id="w_mixed_case_word"), + pytest.param("w", "hello123", False, id="w_word_with_digits"), + pytest.param("w", "", False, id="w_empty_string"), + pytest.param("s", "abc123", True, id="s_alphanum"), + pytest.param("s", "ABC99", True, id="s_uppercase_and_digits"), + pytest.param("s", "abc_123", False, id="s_contains_underscore"), + pytest.param("s", "", False, id="s_empty_string"), + pytest.param("d-d", "12-34", True, id="d_dash_d_valid"), + pytest.param("d-d", "12--34", False, id="d_dash_d_double_dash"), + pytest.param("d-d", "12-abc", False, id="d_dash_d_letters_after_dash"), + pytest.param("d-d", "1234", False, id="d_dash_d_missing_dash"), + pytest.param("w.w", "hi.there", True, id="w_dot_w_valid"), + pytest.param("w.w", "hi..there", False, id="w_dot_w_double_dot"), + pytest.param("w.w", "hi1.there", False, id="w_dot_w_digit_in_first_word"), + pytest.param("s.s", "h1i.th32ere", True, id="s_dot_s_valid"), + pytest.param("s.s", "hi4..t2here", False, id="s_dot_s_double_dot"), + pytest.param("d-dw", "12-45abc", True, id="example_valid"), + pytest.param("d-dw", "1-abs", False, id="example_second_part_not_digit"), + pytest.param("d-dw", "1-b123r", False, id="example_letter_after_dash"), + pytest.param("d-dw", "1--123vdg", False, id="example_double_dash"), + pytest.param("d-dw", "123-456XYZ", True, id="d-dw_all_caps"), + pytest.param("d-dw", "0-0a", True, id="d-dw_minimal_valid"), + pytest.param("d@d", "5@7", True, id="d_at_d_valid"), + pytest.param("d@d", "5@@7", False, id="d_at_d_double_at"), + pytest.param("w s", "hi 123", True, id="w_space_s_valid"), + pytest.param("w s", "hi123", False, id="w_space_s_missing_space"), + pytest.param("w s", "hi 123!", False, id="w_space_s_extra_char_in_s"), + pytest.param("", "", True, id="empty_regexp_empty_string"), + pytest.param("", "a", False, id="empty_regexp_non_empty_string"), + pytest.param("d", "", False, id="non_empty_regexp_empty_string"), + pytest.param("d!", "5!", True, id="d_exclam_valid"), + pytest.param("d!", "5", False, id="d_exclam_missing_exclam"), + pytest.param("d!", "5!!", False, id="d_exclam_extra_exclam"), + pytest.param("s", "a1", True, id="s_letter_digit"), + 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"), + ], +) 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 707d6609..f2f6a282 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,122 @@ 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 962ba4bd..06f04319 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 d0cd02ef..16f3d70f 100644 --- a/deprecated_tests/sem01/tests/test_lesson11_tasks.py +++ b/deprecated_tests/sem01/tests/test_lesson11_tasks.py @@ -84,13 +84,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.py b/deprecated_tests/sem01/tests_hw/test_hw1.py new file mode 100644 index 00000000..9819410b --- /dev/null +++ b/deprecated_tests/sem01/tests_hw/test_hw1.py @@ -0,0 +1,49 @@ +from typing import Any + +import pytest + +# Импортируем тестируемую функцию и константу +from homeworks.hw1.aggregate_segmentation import ALLOWED_TYPES, aggregate_segmentation + +# сюда тупа скопировать свой файл с 1 заданием +# и потом запустить счерез pytest + + +def test_aggregate_segmentation_with_invalid_type_after_valid_detailed(): + """Тест с дополнительными проверками состояния до и после невалидного сегмента""" + segmentation_data = [ + { + "audio_id": "audio_1", + "segment_id": "segment_1", + "segment_start": 0.0, + "segment_end": 1.0, + "type": "voice_human", + }, + { + "audio_id": "audio_2", # Другой валидный audio_id + "segment_id": "segment_3", + "segment_start": 0.0, + "segment_end": 1.0, + "type": "voice_bot", + }, + { + "audio_id": "audio_1", # Невалидный сегмент + "segment_id": "segment_2", + "segment_start": 1.0, + "segment_end": 2.0, + "type": "invalid_type", + }, + ] + + valid_result, invalid_result = aggregate_segmentation(segmentation_data) + + # audio_1 должен быть в невалидных + assert "audio_1" in invalid_result + # audio_1 не должно быть в валидных + assert "audio_1" not in valid_result + # audio_2 должен остаться валидным + assert "audio_2" in valid_result + # В audio_2 должен быть один сегмент + assert len(valid_result["audio_2"]) == 1 + # Проверяем содержимое сегмента audio_2 + assert valid_result["audio_2"]["segment_3"] == {"start": 0.0, "end": 1.0, "type": "voice_bot"} diff --git a/deprecated_tests/sem01/tests_hw/test_hw1_task1.py b/deprecated_tests/sem01/tests_hw/test_hw1_task1.py new file mode 100644 index 00000000..348ec6f8 --- /dev/null +++ b/deprecated_tests/sem01/tests_hw/test_hw1_task1.py @@ -0,0 +1,387 @@ +from typing import Any + +import pytest + +# Импортируем тестируемую функцию и константу +from homeworks.hw1.aggregate_segmentation import ALLOWED_TYPES, aggregate_segmentation + + +class TestAggregateSegmentation: + """Тесты для функции агрегации сегментации аудио данных.""" + + def test_valid_segments_different_audio_ids(self): + """Тест валидных сегментов с разными audio_id.""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 0.5, + "segment_end": 2.5, + "type": "voice_human", + }, + { + "audio_id": "audio-456", + "segment_id": "seg-2", + "segment_start": 1.0, + "segment_end": 3.0, + "type": "voice_bot", + }, + ] + valid, invalid = aggregate_segmentation(data) + + assert len(invalid) == 0 + assert "audio-123" in valid + assert "audio-456" in valid + assert valid["audio-123"]["seg-1"]["type"] == "voice_human" + assert valid["audio-456"]["seg-2"]["type"] == "voice_bot" + + def test_valid_segments_same_audio_id(self): + """Тест валидных сегментов с одинаковым audio_id.""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 0.5, + "segment_end": 2.5, + "type": "voice_human", + }, + { + "audio_id": "audio-123", + "segment_id": "seg-2", + "segment_start": 3.0, + "segment_end": 5.0, + "type": "spotter_word", + }, + ] + valid, invalid = aggregate_segmentation(data) + + assert len(invalid) == 0 + assert len(valid["audio-123"]) == 2 + assert "seg-1" in valid["audio-123"] + assert "seg-2" in valid["audio-123"] + + def test_segments_without_voice_all_none(self): + """Тест сегментов без голоса (все поля None) - должен создать пустой словарь.""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": None, + "segment_end": None, + "type": None, + }, + { + "audio_id": "audio-123", + "segment_id": "seg-2", + "segment_start": None, + "segment_end": None, + "type": None, + }, + ] + valid, invalid = aggregate_segmentation(data) + + assert len(invalid) == 0 + assert valid["audio-123"] == {} + + def test_mixed_voice_and_no_voice_segments(self): + """Тест смешанных сегментов (с голосом и без) для одного audio_id.""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 0.5, + "segment_end": 2.5, + "type": "voice_human", + }, + { + "audio_id": "audio-123", + "segment_id": "seg-2", + "segment_start": None, + "segment_end": None, + "type": None, + }, + ] + valid, invalid = aggregate_segmentation(data) + + assert len(invalid) == 0 + assert len(valid["audio-123"]) == 1 # Только сегмент с голосом + assert "seg-1" in valid["audio-123"] + assert "seg-2" not in valid["audio-123"] + + def test_duplicate_segments_same_data(self): + """Тест дубликатов сегментов с одинаковыми данными (должны игнорироваться).""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 0.5, + "segment_end": 2.5, + "type": "voice_human", + }, + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 0.5, + "segment_end": 2.5, + "type": "voice_human", + }, + ] + valid, invalid = aggregate_segmentation(data) + + assert len(invalid) == 0 + assert len(valid["audio-123"]) == 1 + + @pytest.mark.parametrize( + "field,value", + [ + ("type", 123), # type не строка + ("segment_start", "not_float"), # start не float + ("segment_end", "not_float"), # end не float + ], + ) + def test_invalid_field_types(self, field: str, value: Any): + """Тест невалидных типов полей.""" + base_segment = { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 0.5, + "segment_end": 2.5, + "type": "voice_human", + } + base_segment[field] = value + data = [base_segment] + + valid, invalid = aggregate_segmentation(data) + + assert "audio-123" in invalid + assert len(valid) == 0 + + @pytest.mark.parametrize( + "segment_start,segment_end,type_val", + [ + (None, 2.5, "voice_human"), # Только start None + (0.5, None, "voice_human"), # Только end None + (0.5, 2.5, None), # Только type None + (None, None, "voice_human"), # Только type не None + (0.5, None, None), # Только start не None + ], + ) + def test_partial_none_values(self, segment_start: Any, segment_end: Any, type_val: Any): + """Тест частичных None значений (должны быть невалидными).""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": segment_start, + "segment_end": segment_end, + "type": type_val, + } + ] + valid, invalid = aggregate_segmentation(data) + + assert "audio-123" in invalid + assert len(valid) == 0 + + def test_type_not_in_allowed_types(self): + """Тест type не из ALLOWED_TYPES.""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 0.5, + "segment_end": 2.5, + "type": "invalid_type", + } + ] + valid, invalid = aggregate_segmentation(data) + + assert "audio-123" in invalid + assert len(valid) == 0 + + def test_duplicate_segments_different_data(self): + """Тест дубликатов сегментов с разными данными (должно быть невалидно).""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 0.5, + "segment_end": 2.5, + "type": "voice_human", + }, + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 1.0, # Другой start + "segment_end": 3.0, + "type": "voice_human", + }, + ] + valid, invalid = aggregate_segmentation(data) + + assert "audio-123" in invalid + # Проверяем, что валидные сегменты не добавлены + assert len(valid.get("audio-123", {})) == 0 + + def test_missing_audio_id(self): + """Тест отсутствующего audio_id (должен игнорироваться).""" + data = [ + { + "audio_id": "", # Пустой ID + "segment_id": "seg-1", + "segment_start": 0.5, + "segment_end": 2.5, + "type": "voice_human", + }, + { + "audio_id": "audio-123", + "segment_id": "seg-2", + "segment_start": 1.0, + "segment_end": 3.0, + "type": "voice_bot", + }, + ] + valid, invalid = aggregate_segmentation(data) + + assert len(invalid) == 0 + assert "audio-123" in valid + assert len(valid["audio-123"]) == 1 + + def test_empty_input(self): + """Тест пустого входного списка.""" + valid, invalid = aggregate_segmentation([]) + + assert len(valid) == 0 + assert len(invalid) == 0 + + def test_multiple_invalid_segments_same_audio_id(self): + """Тест нескольких невалидных сегментов для одного audio_id (в списке должен быть один раз).""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "", # Невалидный + "segment_start": 0.5, + "segment_end": 2.5, + "type": "voice_human", + }, + { + "audio_id": "audio-123", + "segment_id": "seg-2", + "segment_start": None, # Невалидный (частичный None) + "segment_end": 3.0, + "type": "voice_bot", + }, + { + "audio_id": "audio-456", + "segment_id": "seg-3", + "segment_start": 1.0, + "segment_end": 2.0, + "type": "voice_human", + }, + ] + valid, invalid = aggregate_segmentation(data) + + assert "audio-123" in invalid + assert "audio-456" not in invalid + assert invalid.count("audio-123") == 1 # Только один раз + assert len(valid) == 1 + assert "audio-456" in valid + + def test_time_validation_edge_cases(self): + """Тест краевых случаев времени.""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 0.0, # Ноль + "segment_end": 10.0, # Максимум + "type": "voice_human", + }, + { + "audio_id": "audio-456", + "segment_id": "seg-2", + "segment_start": 5.0, + "segment_end": 5.0, # Нулевая длительность + "type": "spotter_word", + }, + ] + valid, invalid = aggregate_segmentation(data) + + assert len(invalid) == 0 + assert len(valid) == 2 + + @pytest.mark.performance + def test_large_dataset(self): + """Производственный тест на большом наборе данных.""" + data = [] + # 100 разных audio_id, каждый с 10 сегментами + for i in range(100): + audio_id = f"audio-{i}" + for j in range(10): + data.append( + { + "audio_id": audio_id, + "segment_id": f"seg-{i}-{j}", + "segment_start": float(j), + "segment_end": float(j + 1), + "type": "voice_human" if j % 2 == 0 else "voice_bot", + } + ) + + valid, invalid = aggregate_segmentation(data) + + assert len(valid) == 100 + assert len(invalid) == 0 + assert all(len(segments) == 10 for segments in valid.values()) + + def test_mixed_allowed_types(self): + """Тест всех разрешенных типов.""" + data = [ + { + "audio_id": f"audio-{i}", + "segment_id": f"seg-{i}", + "segment_start": 0.5, + "segment_end": 2.5, + "type": voice_type, + } + for i, voice_type in enumerate(ALLOWED_TYPES) + ] + valid, invalid = aggregate_segmentation(data) + + assert len(invalid) == 0 + assert len(valid) == len(ALLOWED_TYPES) + + def test_negative_time_values(self): + """Тест отрицательных значений времени (должны быть валидны, так как не проверяются).""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": -1.0, + "segment_end": -0.5, + "type": "voice_human", + } + ] + valid, invalid = aggregate_segmentation(data) + + # В текущей реализации это считается валидным + assert "audio-123" not in invalid + assert "audio-123" in valid + + def test_start_greater_than_end(self): + """Тест когда start > end (должно быть валидно, так как не проверяется).""" + data = [ + { + "audio_id": "audio-123", + "segment_id": "seg-1", + "segment_start": 5.0, + "segment_end": 2.0, + "type": "voice_human", + } + ] + valid, invalid = aggregate_segmentation(data) + + # В текущей реализации это считается валидным + assert "audio-123" not in invalid + assert "audio-123" in valid + assert valid["audio-123"]["seg-1"]["start"] == 5.0 + assert valid["audio-123"]["seg-1"]["end"] == 2.0 diff --git a/deprecated_tests/sem01/tests_hw/test_hw1_task4.py b/deprecated_tests/sem01/tests_hw/test_hw1_task4.py new file mode 100644 index 00000000..b48652af --- /dev/null +++ b/deprecated_tests/sem01/tests_hw/test_hw1_task4.py @@ -0,0 +1,131 @@ +from unittest.mock import Mock + +import pytest + +# Импортируем тестируемую функцию +from homeworks.hw1.cache import lru_cache + +""" + + Списки с аргументами: + + * первый параметр - количество аргументов + * второй параметр - возможные типы + * третий параметр - повторение аргументов + * четвертый параметр - размер + +""" + +ARGS_DICT: dict[str, list[tuple[object]]] = { + "one_int_without_repeating_args_small": [ + (2), + (1), + ], + "one_int_with_repeating_args_small": [ + (2), + (1), + (2), + (1), + (1), + ], + "one_int_with_repeating_args_huge": [ + (1), # c + (2), # c + (2), + (1), + (2), + (1), + (1), + (2), + (1), + (1), + (3), # c + (1), + (1), + (3), + (2), # c + (1), # c + (1), + (1), + (1), + (3), # c + (1), + (3), + (2), # c + (1), # c + (3), # c + (2), # c + (1), # c + (1), + ], + "three_str_with_repeating_args_small": [ + ("first", "second", "third"), # 1 o + ("first", "third", "second"), # 2 o + ("third", "first", "third"), # 3 o + ("first", "second", "third"), # 1 o + ("first", "third", "second"), # 2 o + ("first", "second", "first"), # 4 o + ("third", "first", "third"), # 3 o + ("first", "second", "third"), # 1 o + ], + "two_multi_with_repeating_args_small": [ + (42, "str"), # o #o + (5.6, TypeError), # o #o + (7 + 7j, None), # o #o + (5.6, TypeError), + (7 + 7j, None), + (5.6, TypeError), + (42, "str"), # o + (5.6, TypeError), + (True, False), # o #o + (42, "str"), # o + (7 + 7j, None), # o #o + (True, False), # o + (5.6, TypeError), # o #o + (42, "str"), # o #o + (42, "str"), + (7 + 7j, None), # o #o + (7 + 7j, None), + (42, "str"), + (True, False), # o #o + ], +} + +"""Тесты для декоратора LRU-cache""" + + +@pytest.mark.parametrize( + "capacity, call_count_expected, call_args", + [ + (2, 2, ARGS_DICT["one_int_without_repeating_args_small"]), + (2, 2, ARGS_DICT["one_int_with_repeating_args_small"]), + (2, 11, ARGS_DICT["one_int_with_repeating_args_huge"]), + (2, 8, ARGS_DICT["three_str_with_repeating_args_small"]), + (2, 12, ARGS_DICT["two_multi_with_repeating_args_small"]), + (5, 3, ARGS_DICT["one_int_with_repeating_args_huge"]), + (3, 6, ARGS_DICT["three_str_with_repeating_args_small"]), + (3, 9, ARGS_DICT["two_multi_with_repeating_args_small"]), + ], +) +def test_cache(capacity: int, call_count_expected: int, call_args: list[tuple[object]]) -> None: + 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 + + +def test_exception_value_error() -> None: + capacity: float = 0.4 + mock_func = Mock() + with pytest.raises(ValueError): + lru_cache(capacity=capacity)(mock_func) + + +def test_exception_type_error() -> None: + capacity = None + mock_func = Mock() + with pytest.raises(TypeError): + lru_cache(capacity=capacity)(mock_func) diff --git a/deprecated_tests/sem01/tests_hw/test_hw1_tasks.py b/deprecated_tests/sem01/tests_hw/test_hw1_tasks.py index 0ecf8a10..9b250729 100644 --- a/deprecated_tests/sem01/tests_hw/test_hw1_tasks.py +++ b/deprecated_tests/sem01/tests_hw/test_hw1_tasks.py @@ -1,6 +1,5 @@ -import pytest import uuid -from unittest.mock import MagicMock, patch, Mock +from unittest.mock import MagicMock, Mock, patch from homeworks.sem01.hw1.aggregate_segmentation import aggregate_segmentation, ALLOWED_TYPES from homeworks.sem01.hw1.backoff import backoff @@ -11,7 +10,8 @@ TESTCASE_IDS, ) -NAME_BACKOFF_MODULE = "homeworks.hw1.backoff" # название модуля с backoff +NAME_BACKOFF_MODULE = "homeworks.hw1.backoff" # название модуля с backoff + def test_valid_segments() -> None: """Тест: валидные сегменты.""" @@ -32,53 +32,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 +88,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 +98,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 +109,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 +118,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 +135,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 37d249b7..81312dea 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 aeb37ebc..4cc9188d 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 1cdc176a..839fc120 100644 --- a/homeworks/sem01/hw1/aggregate_segmentation.py +++ b/homeworks/sem01/hw1/aggregate_segmentation.py @@ -5,6 +5,53 @@ } +def check_validation(audio_segment: dict, used_id: list[list[str, str]]) -> list[bool, int]: + """Проверка данных на валидность + Args: + audio_segment: словарь, в котором хранится сегемент который в данный момент находится \ + на проверкеимеет те же поля, что и segmentation_data + used_id : cписок сегментов прошедших проверку хранит внутри массивы в каждом\ + из которых первыйм идет audio_id вторым segment_id + Return: + [True,0] если значение валидно и на всех полях не None + [True,1] если значение валидно и на во всех полях None + [False,0] если значение невалидно + + """ + + required_keys: tuple = ("segment_id", "segment_start", "segment_end", "type") + + if not all(k in audio_segment for k in required_keys): + return [False, 0] + + if not isinstance(audio_segment["segment_id"], str): + return [False, 0] + + start: float = audio_segment["segment_start"] + end: float = audio_segment["segment_end"] + audio_type: str = audio_segment["type"] + + if all(v is None for v in (start, end, audio_type)): + return [True, 1] + + if any(v is None for v in (start, end, audio_type)): + return [False, 0] + + if ( + not isinstance(start, float) + or not isinstance(end, float) + or not isinstance(audio_type, str) + ): + return [False, 0] + + if audio_segment["type"] not in ALLOWED_TYPES: + return [False, 0] + + id_check = [audio_segment["audio_id"], audio_segment["segment_id"]] + + return [id_check not in used_id, 0] + + def aggregate_segmentation( segmentation_data: list[dict[str, str | float | None]], ) -> tuple[dict[str, dict[str, dict[str, str | float]]], list[str]]: @@ -23,6 +70,41 @@ def aggregate_segmentation( Словарь с валидными сегментами, объединёнными по `audio_id`; Список `audio_id` (str), которые требуют переразметки. """ + result: list[dict[str, dict[str, dict[str, str | float]]], list[str]] = [{}, []] + audio_id_set = set(i["audio_id"] for i in segmentation_data) + redo_set: set = set() + used_id: list[list] = [] + + unique_segments: list = [] # удаляем прям одинаковые элементы чтобы потом не проверять + unique_segments_checked: set = set() + for segment in segmentation_data: + key = tuple( + sorted(segment.items()) + ) # делаем tuple чтобы добавлять в множество тк массив нельзя(чтобы не забыть на сдаче) + if key not in unique_segments_checked: + unique_segments_checked.add(key) + unique_segments.append(segment) + segmentation_data = unique_segments - # ваш код - return {}, [] + for audio in audio_id_set: + audio_rn: dict = {} + for segment in segmentation_data: + if segment["audio_id"] == audio: + checker = check_validation(segment, used_id) + if checker[0] and checker[1] == 0: + audio_rn[segment["segment_id"]] = { + "start": segment["segment_start"], + "end": segment["segment_end"], + "type": segment["type"], + } + used_id.append([segment["audio_id"], segment["segment_id"]]) + elif checker[0] and checker[1] == 1: + used_id.append([segment["audio_id"], segment["segment_id"]]) + else: + redo_set.add(audio) + break + if audio in redo_set: + continue + result[0][audio] = audio_rn + result[1] = list(redo_set) + return tuple(result) diff --git a/homeworks/sem01/hw1/backoff.py b/homeworks/sem01/hw1/backoff.py index 696ffa73..0a5194eb 100644 --- a/homeworks/sem01/hw1/backoff.py +++ b/homeworks/sem01/hw1/backoff.py @@ -1,3 +1,4 @@ +from functools import wraps from random import uniform from time import sleep from typing import ( @@ -33,6 +34,25 @@ def backoff( Raises: ValueError, если были переданы невозможные аргументы. """ + if retry_amount <= 0 or timeout_max <= 0 or timeout_start <= 0 or backoff_scale <= 0: + raise ValueError("Detected negative number, use positive numbers for decorator") - # ваш код - pass + def decorator(func: Callable): + @wraps(func) + def wrapper(*args, **kargs): + delay = timeout_start + for i in range(retry_amount + 1): + try: + return func(*args, **kargs) + except backoff_triggers: + if i == retry_amount + 1: + raise + delay_amount = min(timeout_max, delay) + uniform(0, 0.5) + sleep(delay_amount) + delay *= backoff_scale + except Exception: + raise + + return wrapper + + return decorator diff --git a/homeworks/sem01/hw1/cache.py b/homeworks/sem01/hw1/cache.py index 9eb1d5d2..ef50b060 100644 --- a/homeworks/sem01/hw1/cache.py +++ b/homeworks/sem01/hw1/cache.py @@ -1,3 +1,5 @@ +from collections import OrderedDict +from functools import wraps from typing import ( Callable, ParamSpec, @@ -23,5 +25,29 @@ def lru_cache(capacity: int) -> Callable[[Callable[P, R]], Callable[P, R]]: для получения целого числа. ValueError, если после округления capacity - число, меньшее 1. """ - # ваш код - pass + try: + capacity = round(capacity) + except Exception: + raise TypeError + if capacity < 1: + raise ValueError + + def decorator(func: Callable) -> Callable: + cashe = OrderedDict() + + @wraps(func) + def wrapper(*args, **kargs): + key = (args, tuple(sorted(kargs.items()))) + if key in cashe: + cashe.move_to_end(key) + return cashe[key] + res = func(*args, **kargs) + cashe[key] = res + cashe.move_to_end(key) + if len(cashe) > capacity: + cashe.popitem(last=False) + return res + + return wrapper + + return decorator diff --git a/homeworks/sem01/hw1/convert_exception.py b/homeworks/sem01/hw1/convert_exception.py index fe5c770f..68dc0bf2 100644 --- a/homeworks/sem01/hw1/convert_exception.py +++ b/homeworks/sem01/hw1/convert_exception.py @@ -1,3 +1,4 @@ +from functools import wraps from typing import ( Callable, ParamSpec, @@ -24,5 +25,19 @@ def convert_exceptions_to_api_compitable_ones( Декоратор для непосредственного использования. """ - # ваш код - pass + def decorator(func: Callable): + @wraps(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: + if isinstance(exception_to_api_exception[exc_type], type): + raise exception_to_api_exception[exc_type]() + raise exception_to_api_exception[exc_type] + raise + + return wrapper + + return decorator diff --git a/result.png b/result.png new file mode 100644 index 00000000..556c6f78 Binary files /dev/null and b/result.png differ diff --git a/solutions/sem01/lesson02/task1.py b/solutions/sem01/lesson02/task1.py index c782dcd8..f344e470 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(num, 1, -1): + factorial *= i return factorial diff --git a/solutions/sem01/lesson02/task2.py b/solutions/sem01/lesson02/task2.py index b91420c5..e96073ee 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 - # ваш код + for i in range(num, 0, -2): + if i == 0 or i == 1: + break + factorial *= i return factorial diff --git a/solutions/sem01/lesson02/task3.py b/solutions/sem01/lesson02/task3.py index ee2a84ec..280a3be3 100644 --- a/solutions/sem01/lesson02/task3.py +++ b/solutions/sem01/lesson02/task3.py @@ -1,4 +1,11 @@ def get_amount_of_ways_to_climb(stair_amount: int) -> int: step_prev, step_curr = 1, 1 - # ваш код + if stair_amount == 1: + return step_curr + else: + for i in range(2, stair_amount + 1): + temp = step_curr + step_curr = step_curr + step_prev + step_prev = temp + # Stair amount equals to element with index n+1 of fibonacci sequence return step_curr diff --git a/solutions/sem01/lesson02/task4.py b/solutions/sem01/lesson02/task4.py index 45ff4bb4..7bbe6132 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 -= 1 + continue + multiplications_amount += 1 + num //= 2 return multiplications_amount diff --git a/solutions/sem01/lesson02/task5.py b/solutions/sem01/lesson02/task5.py index 8fb9a048..f4cb43c6 100644 --- a/solutions/sem01/lesson02/task5.py +++ b/solutions/sem01/lesson02/task5.py @@ -1,3 +1,7 @@ def get_gcd(num1: int, num2: int) -> int: - # ваш код - return num1 + while max(num1, num2) % min(num1, num2) != 0: + if num1 > num2: + num1 = num1 % num2 + else: + num2 = num2 % num1 + return min(num1, num2) diff --git a/solutions/sem01/lesson02/task6.py b/solutions/sem01/lesson02/task6.py index bec4b6cd..1896ca12 100644 --- a/solutions/sem01/lesson02/task6.py +++ b/solutions/sem01/lesson02/task6.py @@ -1,4 +1,13 @@ def get_sum_of_prime_divisors(num: int) -> int: + n = num + if n == 1: + return 0 sum_of_divisors = 0 - # ваш код + for i in range(2, int(num**0.5) + 1): + if num % i == 0: + sum_of_divisors += i + while num % i == 0: + num //= i + if sum_of_divisors == 0: + return n return sum_of_divisors diff --git a/solutions/sem01/lesson02/task7.py b/solutions/sem01/lesson02/task7.py index 4b2d73be..d97d936d 100644 --- a/solutions/sem01/lesson02/task7.py +++ b/solutions/sem01/lesson02/task7.py @@ -1,5 +1,12 @@ def is_palindrome(num: int) -> bool: + if num < 0: + return False num_reversed = 0 - num_origin = num - # ваш код - return num_origin == num_reversed + num_reversed += num % 10 + num_current = num + num_current //= 10 + while num_current > 0: + num_reversed *= 10 + num_reversed += num_current % 10 + num_current //= 10 + return num == num_reversed diff --git a/solutions/sem01/lesson03/task1.py b/solutions/sem01/lesson03/task1.py index f1d8fe26..a403cb56 100644 --- a/solutions/sem01/lesson03/task1.py +++ b/solutions/sem01/lesson03/task1.py @@ -1,3 +1,27 @@ def flip_bits_in_range(num: int, left_bit: int, right_bit: int) -> int: - # ваш код - return num \ No newline at end of file + answer = 0 + position = 1 + curr_bit = 1 + while num > 0: + if curr_bit >= left_bit and curr_bit <= right_bit: + if num % 2 == 1: + answer = answer + position * 0 + else: + answer = answer + position * 1 + else: + answer = answer + position * (num % 2) + position *= 10 + num //= 2 + curr_bit += 1 + while curr_bit <= right_bit: + answer = answer + position * 1 + position *= 10 + curr_bit += 1 + num = 0 + power = 0 + while answer > 0: + digit = answer % 10 + num += digit * (2**power) + answer //= 10 + power += 1 + return num diff --git a/solutions/sem01/lesson03/task2.py b/solutions/sem01/lesson03/task2.py index a3a738c2..b9d835d5 100644 --- a/solutions/sem01/lesson03/task2.py +++ b/solutions/sem01/lesson03/task2.py @@ -1,3 +1,23 @@ def get_cube_root(n: float, eps: float) -> float: - # ваш код - return n \ No newline at end of file + if n < 0: + return -get_cube_root(-n, eps) + if n >= 1: + low_border, high_border = 0, n + else: + low_border, high_border = 0, 1 + while ( + abs( + ((low_border + high_border) / 2) + * ((low_border + high_border) / 2) + * ((low_border + high_border) / 2) + - n + ) + >= eps + ): + mid = (low_border + high_border) / 2 + mid_cube = mid * mid * mid + if mid_cube < n: + low_border = mid + else: + high_border = mid + return (low_border + high_border) / 2 diff --git a/solutions/sem01/lesson03/task3.py b/solutions/sem01/lesson03/task3.py index 5e91a6ac..95f70473 100644 --- a/solutions/sem01/lesson03/task3.py +++ b/solutions/sem01/lesson03/task3.py @@ -1,3 +1,12 @@ def get_nth_digit(num: int) -> int: - # ваш код - return 0 + kolv_cifr = 0 + digit_sum = 5 + if num <= digit_sum: + return (num - 1) * 2 + while num > digit_sum: + digit_sum += 45 * (10**kolv_cifr) * (kolv_cifr + 2) + kolv_cifr += 1 + k = num - (digit_sum - 45 * (10 ** (kolv_cifr - 1)) * (kolv_cifr + 1)) - 1 + k1 = k // (kolv_cifr + 1) + finall_humber = 10**kolv_cifr + k1 * 2 + return (finall_humber // (10 ** ((kolv_cifr) - (k % (kolv_cifr + 1))))) % 10 diff --git a/solutions/sem01/lesson04/task1.py b/solutions/sem01/lesson04/task1.py index 47384423..075af3a5 100644 --- a/solutions/sem01/lesson04/task1.py +++ b/solutions/sem01/lesson04/task1.py @@ -1,3 +1,12 @@ def is_arithmetic_progression(lst: list[list[int]]) -> bool: - # ваш код - return False \ No newline at end of file + lst.sort() + if len(lst) in [0, 1]: + return True + flag = True + change = lst[1] - lst[0] + i = 1 + while flag and i < len(lst): + if lst[i] - lst[i - 1] != change: + flag = False + i += 1 + return flag diff --git a/solutions/sem01/lesson04/task2.py b/solutions/sem01/lesson04/task2.py index 4591d0a3..0a552647 100644 --- a/solutions/sem01/lesson04/task2.py +++ b/solutions/sem01/lesson04/task2.py @@ -1,3 +1,21 @@ def merge_intervals(intervals: list[list[int, int]]) -> list[list[int, int]]: - # ваш код - return [[0,0]] \ No newline at end of file + intervals.sort(key=lambda x: x[0]) + if len(intervals) == 0: + return [] + newintervals = [] + start, finish = intervals[0][0], intervals[0][1] + flag1 = True + for i in intervals: + if flag1: + flag1 = False + continue # скип первого элемента(костыль) + if start < i[0] and finish > i[1]: + continue + elif finish >= i[0] and start <= i[0]: + finish = i[1] + else: + newintervals.append([start, finish]) + start = i[0] + finish = i[1] + newintervals.append([start, finish]) + return newintervals diff --git a/solutions/sem01/lesson04/task3.py b/solutions/sem01/lesson04/task3.py index 7253f6cb..68802acc 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 + result = 0 + for num in nums: + result ^= num + return result diff --git a/solutions/sem01/lesson04/task4.py b/solutions/sem01/lesson04/task4.py index b21bc5a3..d22c3694 100644 --- a/solutions/sem01/lesson04/task4.py +++ b/solutions/sem01/lesson04/task4.py @@ -1,3 +1,9 @@ def move_zeros_to_end(nums: list[int]) -> list[int]: - # ваш код - return 0 \ No newline at end of file + index = 0 + for i in range(len(nums)): + if nums[i] != 0: + nums[index] = nums[i] + index += 1 + for i in range(index, len(nums)): + nums[i] = 0 + return index diff --git a/solutions/sem01/lesson04/task5.py b/solutions/sem01/lesson04/task5.py index 02d7742b..85c40eec 100644 --- a/solutions/sem01/lesson04/task5.py +++ b/solutions/sem01/lesson04/task5.py @@ -1,3 +1,13 @@ def find_row_with_most_ones(matrix: list[list[int]]) -> int: - # ваш код - return 0 \ No newline at end of file + if not matrix or not matrix[0]: + return 0 + row = 0 + col = len(matrix[0]) - 1 + result_index = 0 + while row < len(matrix) and col >= 0: + if matrix[row][col] == 1: + result_index = row + col -= 1 + else: + row += 1 + return result_index diff --git a/solutions/sem01/lesson04/task6.py b/solutions/sem01/lesson04/task6.py index 16df27ca..00c5d5ad 100644 --- a/solutions/sem01/lesson04/task6.py +++ b/solutions/sem01/lesson04/task6.py @@ -1,3 +1,13 @@ -def count_cycles(arr: list[int]) -> int: - # ваш код - return 0 \ No newline at end of file +def count_cycles(arr: list[int]) -> int: + if not arr: + return 0 + visited = [False] * len(arr) + cycle_count = 0 + for i in range(len(arr)): + if not visited[i]: + cycle_count += 1 + current = i + while not visited[current]: + visited[current] = True + current = arr[current] + return cycle_count diff --git a/solutions/sem01/lesson05/task1.py b/solutions/sem01/lesson05/task1.py index 9a17211e..8d94d0ac 100644 --- a/solutions/sem01/lesson05/task1.py +++ b/solutions/sem01/lesson05/task1.py @@ -1,3 +1,3 @@ def is_palindrome(text: str) -> bool: - # ваш код - return False \ No newline at end of file + text = text.lower() + return text == text[::-1] diff --git a/solutions/sem01/lesson05/task2.py b/solutions/sem01/lesson05/task2.py index 36750380..eded933a 100644 --- a/solutions/sem01/lesson05/task2.py +++ b/solutions/sem01/lesson05/task2.py @@ -1,3 +1,11 @@ def are_anagrams(word1: str, word2: str) -> bool: - # ваш код - return False \ No newline at end of file + if len(word1) != len(word2): + return False + char_index = [0] * 128 + for i in word1: + char_index[ord(i)] += 1 + for i in word2: + char_index[ord(i)] -= 1 + if char_index[ord(i)] < 0: + return False + return True diff --git a/solutions/sem01/lesson05/task3.py b/solutions/sem01/lesson05/task3.py index e368e2f4..8352c22d 100644 --- a/solutions/sem01/lesson05/task3.py +++ b/solutions/sem01/lesson05/task3.py @@ -1,3 +1,7 @@ def is_punctuation(text: str) -> bool: - # ваш код - return False + if not text: + return False + for i in text: + if i not in "!#$%&'()*+,-./:;<=>?@[\]^_{|}`\"~": + return False + return True diff --git a/solutions/sem01/lesson05/task4.py b/solutions/sem01/lesson05/task4.py index 4c4e9086..fd1c8bd7 100644 --- a/solutions/sem01/lesson05/task4.py +++ b/solutions/sem01/lesson05/task4.py @@ -1,3 +1,9 @@ def unzip(compress_text: str) -> str: - # ваш код - return compress_text \ No newline at end of file + result = "" + compress_text = compress_text.split(" ") + for i in compress_text: + if "*" not in i: + result += i + else: + result += i[: i.find("*")] * int(i[i.find("*") + 1 :]) + return result diff --git a/solutions/sem01/lesson05/task5.py b/solutions/sem01/lesson05/task5.py index 076c5bb6..44b40704 100644 --- a/solutions/sem01/lesson05/task5.py +++ b/solutions/sem01/lesson05/task5.py @@ -1,3 +1,27 @@ -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 + text = text.lower() + while i < len(reg_expr) and j < len(text): + symbol = reg_expr[i] + if symbol == "d": + if not text[j].isdigit(): + return False + while j < len(text) and text[j].isdigit(): + j += 1 + elif symbol == "w": + if not text[j].isalpha(): + return False + while j < len(text) and text[j].isalpha(): + j += 1 + elif symbol == "s": + if not (text[j].isalpha() or text[j].isdigit()): + return False + while j < len(text) and (text[j].isalpha() or text[j].isdigit()): + j += 1 + else: + if text[j] != symbol: + 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 1b914ada..6513d768 100644 --- a/solutions/sem01/lesson05/task6.py +++ b/solutions/sem01/lesson05/task6.py @@ -1,3 +1,16 @@ def simplify_path(path: str) -> str: - # ваш код - return path \ No newline at end of file + path = path.split("/") + queue = [] + for dir in path: + if dir == "" or dir == ".": + continue + elif dir == "..": + if queue: + queue.pop() + else: + return "" + else: + queue.append(dir) + final_path = "/" + "/".join(queue) + + return final_path diff --git a/solutions/sem01/lesson06/task1.py b/solutions/sem01/lesson06/task1.py index 2d1e30e9..af4c66fb 100644 --- a/solutions/sem01/lesson06/task1.py +++ b/solutions/sem01/lesson06/task1.py @@ -1,3 +1,41 @@ def int_to_roman(num: int) -> str: - # ваш код - return "" \ No newline at end of file + roman_numbers = {1000: "M", 500: "D", 100: "C", 50: "L", 10: "X", 5: "V", 1: "I"} + roman_digits = [1000, 500, 100, 50, 10, 5, 1] + index = 0 + result = "" + flag_close = False + while index < len(roman_digits) and num > 0: + if not flag_close and (num - roman_digits[index]) < 0: + flag_close = True + elif not flag_close: + result += roman_numbers[roman_digits[index]] + num -= roman_digits[index] + elif flag_close: + if (index == 0 or index == 2 or index == 4) and ( + num - (roman_digits[index] - 10 ** ((str(roman_digits[index]).count("0")) - 1)) + ) >= 0: + num -= roman_digits[index] - 10 ** ((str(roman_digits[index]).count("0")) - 1) + result += ( + roman_numbers[10 ** ((str(roman_digits[index]).count("0")) - 1)] + + roman_numbers[roman_digits[index]] + ) + flag_close = False + index += 1 + elif ( + index != 2 + and index != 0 + and index != 4 + and (num - (roman_digits[index] - 10 ** str(roman_digits[index]).count("0"))) >= 0 + ): + print(10 ** str(roman_digits[index]).count("0")) + result += ( + roman_numbers[10 ** str(roman_digits[index]).count("0")] + + roman_numbers[roman_digits[index]] + ) + num -= roman_digits[index] - 10 ** str(roman_digits[index]).count("0") + flag_close = False + index += 1 + else: + flag_close = False + index += 1 + return result diff --git a/solutions/sem01/lesson06/task2.py b/solutions/sem01/lesson06/task2.py index f535b5a0..be64a537 100644 --- a/solutions/sem01/lesson06/task2.py +++ b/solutions/sem01/lesson06/task2.py @@ -1,3 +1,13 @@ def get_len_of_longest_substring(text: str) -> int: - # ваш код - return 0 \ No newline at end of file + start = 0 + maxlen = 0 + while start < len(text): + substr = "" + for i in range(start, len(text)): + if text[i] not in substr: + substr += text[i] + else: + break + maxlen = max(maxlen, len(substr)) + start += 1 + return maxlen diff --git a/solutions/sem01/lesson06/task3.py b/solutions/sem01/lesson06/task3.py index 7449a1e7..1451f188 100644 --- a/solutions/sem01/lesson06/task3.py +++ b/solutions/sem01/lesson06/task3.py @@ -1,7 +1,19 @@ -def is_there_any_good_subarray( - nums: list[int], - k: int, -) -> bool: - - # ваш код +def is_there_any_good_subarray(nums: list[int], k: int) -> bool: + if len(nums) < 2: + return False + elif len(nums) == 2: + sum = 0 + for subarr in nums: + sum += subarr + if sum % k == 0: + return True + else: + return False + for i in range(0, len(nums) - 1): + for j in range(i + 2, len(nums) + 1): + sum = 0 + for subarr in nums[i:j]: + sum += subarr + if sum % k == 0: + return True return False diff --git a/solutions/sem01/lesson06/task4.py b/solutions/sem01/lesson06/task4.py index 5b75a110..161c4b44 100644 --- a/solutions/sem01/lesson06/task4.py +++ b/solutions/sem01/lesson06/task4.py @@ -1,3 +1,12 @@ +import string + + def count_unique_words(text: str) -> int: - # ваш код - return 0 \ No newline at end of file + text = text.lower() + words = text.split(" ") + unique_words = set() + for i in range(len(words)): + word = words[i].strip(string.punctuation) + if word or any(letter.isalnum() for letter in word): + unique_words.add(word) + return len(unique_words) diff --git a/solutions/sem01/lesson08/task1.py b/solutions/sem01/lesson08/task1.py index 4390f6c8..5dffe2c5 100644 --- a/solutions/sem01/lesson08/task1.py +++ b/solutions/sem01/lesson08/task1.py @@ -1,5 +1,15 @@ -from typing import Callable +import typing -def make_averager(accumulation_period: int) -> Callable[[float], float]: - # ваш код - pass \ No newline at end of file + +def make_averager(accumulation_period: int) -> typing.Callable[[float], float]: + sum_change = [] + + def get_avg(value: float): + nonlocal sum_change + sum_change.append(value) + if len(sum_change) > accumulation_period: + sum_change.pop(0) + avg = sum(sum_change) / len(sum_change) + return avg + + return get_avg diff --git a/solutions/sem01/lesson08/task2.py b/solutions/sem01/lesson08/task2.py index 6e4af870..86367abe 100644 --- a/solutions/sem01/lesson08/task2.py +++ b/solutions/sem01/lesson08/task2.py @@ -1,10 +1,25 @@ +import time +from functools import wraps from typing import Callable, TypeVar T = TypeVar("T") -def collect_statistic( - statistics: dict[str, list[float, int]] -) -> Callable[[T], T]: - - # ваш код - pass \ No newline at end of file + +def collect_statistic(statistics: dict[str, list[float, int]]) -> Callable[[T], T]: + def checker(func: Callable): + @wraps(func) + def wrapper(*args, **kwargs): + start = time.time() + result = func(*args, **kwargs) + end = time.time() + time_length = end - start + if func.__name__ not in statistics: + statistics[func.__name__] = [0.0, 0] + old_avg, old_count = statistics[func.__name__] + new_avg = (old_avg * old_count + time_length) / (old_count + 1) + statistics[func.__name__] = [new_avg, old_count + 1] + return result + + return wrapper + + return checker diff --git a/solutions/sem01/lesson11/task1.py b/solutions/sem01/lesson11/task1.py index 6a15f31f..a59737a3 100644 --- a/solutions/sem01/lesson11/task1.py +++ b/solutions/sem01/lesson11/task1.py @@ -1,10 +1,114 @@ +from math import acos, isclose + + class Vector2D: - def conj(self) -> "Vector2D": - # ваш код - return Vector2D() + _abscissa: float + _ordinate: float + + def __init__(self, abscissa: float = 0.0, ordinate: float = 0.0): + self._abscissa = abscissa + self._ordinate = ordinate + + def __repr__(self): + return f"Vector2D(abscissa={self._abscissa}, ordinate={self._ordinate})" + + @property + def abscissa(self): + return self._abscissa + + @property + def ordinate(self): + return self._ordinate + + def __ne__(self, other: "Vector2D"): + return not (self == other) + + def __eq__(self, other): + if not isinstance(other, Vector2D): + return NotImplemented + return isclose(self.abscissa, other.abscissa) and isclose(self.ordinate, other.ordinate) + + def __lt__(self, other): + if not isinstance(other, Vector2D): + return NotImplemented + return ( + self.abscissa < other.abscissa and not (isclose(self.abscissa, other.abscissa)) + ) or ( + isclose(self.abscissa, other.abscissa) + and self.ordinate < other.ordinate + and not (isclose(self.ordinate, other.ordinate)) + ) + + def __le__(self, other): + return self == other or self < other + + def __gt__(self, other): + return not (self <= other) + + def __ge__(self, other): + return not (self < other) + + def __abs__(self): + return (self.abscissa**2 + self.ordinate**2) ** 0.5 + + def __bool__(self): + return not (isclose(abs(self), 0, abs_tol=1e-12)) + + def __mul__(self, other): + if isinstance(other, (int, float)): + return Vector2D(self.abscissa * other, self.ordinate * other) + return NotImplemented + + def __rmul__(self, other): + return self * other + + def __truediv__(self, other): + if isinstance(other, (int, float)): + return Vector2D(self.abscissa / other, self.ordinate / other) + return NotImplemented + + def __add__(self, other): + if isinstance(other, Vector2D): + return Vector2D(self.abscissa + other.abscissa, self.ordinate + other.ordinate) + if isinstance(other, (int, float)): + return Vector2D(self.abscissa + other, self.ordinate + other) + return NotImplemented + + def __radd__(self, other): + return self + other + + def __sub__(self, other): + if isinstance(other, Vector2D): + return Vector2D(self.abscissa - other.abscissa, self.ordinate - other.ordinate) + if isinstance(other, (int, float)): + return Vector2D(self.abscissa - other, self.ordinate - other) + return NotImplemented + + def __neg__(self): + return self * -1 + + def __float__(self): + return abs(self) + + def __int__(self): + return int(abs(self)) + + def __complex__(self): + return complex(self.abscissa, self.ordinate) + + def __matmul__(self, other: "Vector2D"): + if not isinstance(other, Vector2D): + return NotImplemented + return self.abscissa * other.abscissa + self.ordinate * other.ordinate def get_angle(self, other: "Vector2D") -> float: - # ваш код - return 0 + if not isinstance(other, Vector2D): + raise TypeError("Other must be Vector2D") + if isclose(abs(other), 0) or isclose(abs(self), 0): + raise ValueError("You cannot get angle in between given vector and a zero vector") + return acos((self @ other) / (abs(self) * abs(other))) + + def conj(self): + return Vector2D(self.abscissa, self.ordinate * -1) # ваш код diff --git a/solutions/sem01/lesson12/task1.py b/solutions/sem01/lesson12/task1.py index d1bb828c..15c0f22f 100644 --- a/solutions/sem01/lesson12/task1.py +++ b/solutions/sem01/lesson12/task1.py @@ -2,5 +2,11 @@ def chunked(iterable: Iterable, size: int) -> Generator[tuple[Any], None, None]: - # ваш код - ... + chunk = [] + for i in iterable: + chunk.append(i) + if len(chunk) == size: + yield tuple(chunk) + chunk = [] + if len(chunk) != 0: + yield tuple(chunk) diff --git a/solutions/sem01/lesson12/task2.py b/solutions/sem01/lesson12/task2.py index 3ad802ee..d9977ad5 100644 --- a/solutions/sem01/lesson12/task2.py +++ b/solutions/sem01/lesson12/task2.py @@ -2,5 +2,10 @@ def circle(iterable: Iterable) -> Generator[Any, None, None]: - # ваш код - ... + saved = [] + for item in iterable: + yield item + saved.append(item) + while saved: + for item in saved: + yield item diff --git a/solutions/sem01/lesson12/task3.py b/solutions/sem01/lesson12/task3.py index 64c112cc..b3bf3342 100644 --- a/solutions/sem01/lesson12/task3.py +++ b/solutions/sem01/lesson12/task3.py @@ -1,12 +1,25 @@ import sys +from typing import Any class FileOut: + old_std_out: str = "" + def __init__( self, path_to_file: str, ) -> None: - # ваш код - ... + self.path_to_file = path_to_file + + def __enter__(self): + self.old_std_out = sys.stdout + self.file = open(self.path_to_file, "w") + sys.stdout = self.file + return self + + def __exit__(self, *_: Any): + sys.stdout = self.old_std_out + self.file.close() + return False # ваш код diff --git a/solutions/sem02/lesson03/task1.py b/solutions/sem02/lesson03/task1.py index 2c3fc0b5..0c6d3738 100644 --- a/solutions/sem02/lesson03/task1.py +++ b/solutions/sem02/lesson03/task1.py @@ -8,13 +8,21 @@ class ShapeMismatchError(Exception): def sum_arrays_vectorized( lhs: np.ndarray, rhs: np.ndarray, -) -> np.ndarray: ... +) -> np.ndarray: + if np.size(lhs) != np.size(rhs): + raise ShapeMismatchError + return lhs + rhs -def compute_poly_vectorized(abscissa: np.ndarray) -> np.ndarray: ... +def compute_poly_vectorized(abscissa: np.ndarray) -> np.ndarray: + return 3 * (abscissa**2) + 2 * abscissa + 1 def get_mutual_l2_distances_vectorized( lhs: np.ndarray, rhs: np.ndarray, -) -> np.ndarray: ... +) -> np.ndarray: + if np.size(lhs, 1) != np.size(rhs, 1): + raise ShapeMismatchError + dist = lhs[:, np.newaxis, :] - rhs[np.newaxis, :, :] + return np.sqrt(np.sum(dist**2, 2)) diff --git a/solutions/sem02/lesson03/task2.py b/solutions/sem02/lesson03/task2.py index fc823c1d..ad523136 100644 --- a/solutions/sem02/lesson03/task2.py +++ b/solutions/sem02/lesson03/task2.py @@ -9,11 +9,26 @@ 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 (np.shape(distances) == np.shape(azimuth) == np.shape(inclination)): + raise ShapeMismatchError + x = distances * np.cos(azimuth) * np.sin(inclination) + y = distances * np.sin(azimuth) * np.sin(inclination) + 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 (np.shape(abscissa) == np.shape(ordinates) == np.shape(applicates)): + raise ShapeMismatchError + distance = np.sqrt(abscissa**2 + ordinates**2 + applicates**2) + azimuth = np.arctan2(ordinates, abscissa) + inciclination = np.zeros_like(distance) + compare_mask = distance != 0.0 + + inciclination[compare_mask] = np.arccos(applicates[compare_mask] / distance[compare_mask]) + return distance, azimuth, inciclination diff --git a/solutions/sem02/lesson03/task3.py b/solutions/sem02/lesson03/task3.py index 477acd0c..a39234c4 100644 --- a/solutions/sem02/lesson03/task3.py +++ b/solutions/sem02/lesson03/task3.py @@ -3,4 +3,15 @@ def get_extremum_indices( ordinates: np.ndarray, -) -> tuple[np.ndarray, np.ndarray]: ... +) -> tuple[np.ndarray, np.ndarray]: + if (np.size(ordinates)) < 3: + raise ValueError + + all_numbers = np.arange(1, len(ordinates) - 1) + + moved_left = ordinates[:-2] + moved_right = ordinates[2:] + check_area = ordinates[1:-1] + max_mask = (check_area > moved_left) & (check_area > moved_right) + min_mask = (check_area < moved_left) & (check_area < moved_right) + return (all_numbers[min_mask], all_numbers[max_mask]) diff --git a/solutions/sem02/lesson04/task1.py b/solutions/sem02/lesson04/task1.py index 1b5526c1..06a1f3cd 100644 --- a/solutions/sem02/lesson04/task1.py +++ b/solutions/sem02/lesson04/task1.py @@ -2,16 +2,40 @@ def pad_image(image: np.ndarray, pad_size: int) -> np.ndarray: - # ваш код - return image + if pad_size < 1: + raise ValueError + if np.ndim(image) == 2: + hieght, length = image.shape + new_height, new_length = hieght + pad_size * 2, length + pad_size * 2 + padded_image = np.zeros((new_height, new_length), dtype=image.dtype) + padded_image[pad_size : pad_size + hieght, pad_size : pad_size + length] = image + else: + hieght, length, depth = image.shape + new_height, new_length = hieght + pad_size * 2, length + pad_size * 2 + padded_image = np.zeros((new_height, new_length, depth), dtype=image.dtype) + padded_image[pad_size : pad_size + hieght, pad_size : pad_size + length, ...] = image + return padded_image def blur_image( image: np.ndarray, kernel_size: int, ) -> np.ndarray: - # ваш код - return image + if kernel_size < 1 or kernel_size % 2 == 0: + raise ValueError + if kernel_size == 1: + return image + pad = kernel_size // 2 + padded_image = pad_image(image, pad) + shifted = [ + padded_image[i : i + image.shape[0], j : j + image.shape[1], ...] + for i in range(kernel_size) + for j in range(kernel_size) + ] + # сверху сам массив а в глубину уходят элементы вокруг и потом мы просто ищем среднее вглубь + blurred = np.mean(shifted, axis=0) + + return blurred.astype(image.dtype) if __name__ == "__main__": diff --git a/solutions/sem02/lesson04/task2.py b/solutions/sem02/lesson04/task2.py index be9a2288..6e5599dd 100644 --- a/solutions/sem02/lesson04/task2.py +++ b/solutions/sem02/lesson04/task2.py @@ -5,6 +5,26 @@ 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 + pixels = image.flatten() + counts = np.zeros(256, dtype=np.int64) + for color in range(256): + mask = pixels == color + counts[color] = np.sum(mask) + + max_pixels = 0 + best_color = 0 + for current_color in range(256): + if counts[current_color] != 0: + low = max(0, current_color - (threshold - 1)) + high = min(255, current_color + (threshold - 1)) + current_sum = np.sum(counts[low : high + 1]) + + if current_sum > max_pixels: + max_pixels = current_sum + best_color = current_color + + percentage = (max_pixels / pixels.size) * 100 + return np.uint8(best_color), float(percentage) diff --git a/solutions/sem02/lesson04/utils/__init__.py b/solutions/sem02/lesson04/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/solutions/sem02/lesson05/task1.py b/solutions/sem02/lesson05/task1.py index e9c7c3c5..413da76b 100644 --- a/solutions/sem02/lesson05/task1.py +++ b/solutions/sem02/lesson05/task1.py @@ -9,4 +9,9 @@ def can_satisfy_demand( costs: np.ndarray, resource_amounts: np.ndarray, demand_expected: np.ndarray, -) -> bool: ... +) -> bool: + if resource_amounts.shape[0] != costs.shape[0] or demand_expected.shape[0] != costs.shape[1]: + raise ShapeMismatchError + total = costs @ demand_expected + check = total <= resource_amounts + return all(check) diff --git a/solutions/sem02/lesson05/task2.py b/solutions/sem02/lesson05/task2.py index be1fb9d2..cedbded6 100644 --- a/solutions/sem02/lesson05/task2.py +++ b/solutions/sem02/lesson05/task2.py @@ -8,4 +8,18 @@ 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.size: + raise ShapeMismatchError + if np.linalg.det(matrix) == 0: + return (None, None) + + scalar_mult = matrix @ vector + + length = np.sum(matrix**2, axis=1) + + keff = (scalar_mult / length)[:, np.newaxis] + + projections = keff * matrix + + return (projections, vector - projections) diff --git a/solutions/sem02/lesson05/task3.py b/solutions/sem02/lesson05/task3.py index 0c66906c..8ee68bf5 100644 --- a/solutions/sem02/lesson05/task3.py +++ b/solutions/sem02/lesson05/task3.py @@ -9,4 +9,12 @@ def adaptive_filter( Vs: np.ndarray, Vj: np.ndarray, diag_A: np.ndarray, -) -> np.ndarray: ... +) -> np.ndarray: + if Vs.shape[0] != Vj.shape[0] or Vj.shape[1] != diag_A.size: + raise ShapeMismatchError + + Vj_h = Vj.real - 1j * Vj.imag + Vj_h = np.moveaxis(Vj_h, 0, 1) + A = np.diag(diag_A) + R = Vs - Vj @ np.linalg.inv(np.eye(Vj.shape[1]) + Vj_h @ Vj @ A) @ (Vj_h @ Vs) + return R diff --git a/solutions/sem02/lesson07/task1.py b/solutions/sem02/lesson07/task1.py index 3a505d89..1d68b3d1 100644 --- a/solutions/sem02/lesson07/task1.py +++ b/solutions/sem02/lesson07/task1.py @@ -13,8 +13,56 @@ def visualize_diagrams( ordinates: np.ndarray, diagram_type: Any, ) -> None: - # ваш код - pass + if abscissa.shape[0] != ordinates.shape[0] or diagram_type not in ["hist", "box", "violin"]: + raise ShapeMismatchError + figure = plt.figure(figsize=(8, 8)) + grid = plt.GridSpec(4, 4, wspace=0.2, hspace=0.2) + scat_graph = figure.add_subplot(grid[0:-1, 1:]) + ord_vert_graph = figure.add_subplot(grid[0:-1, 0], sharey=scat_graph) + abs_hor_graph = figure.add_subplot(grid[-1, 1:], sharex=scat_graph) + scat_graph.scatter(abscissa, ordinates, color="red", alpha=0.5) + if diagram_type == "box": + ord_vert_graph.boxplot( + ordinates, + patch_artist=True, + boxprops={"facecolor": "red", "linewidth": 2}, + medianprops={"color": "black"}, + ) + abs_hor_graph.boxplot( + abscissa, + vert=False, + patch_artist=True, + boxprops={"facecolor": "red", "linewidth": 2}, + medianprops={"color": "black"}, + ) + if diagram_type == "hist": + ord_vert_graph.hist( + ordinates, orientation="horizontal", bins=50, color="red", alpha=0.5, edgecolor="black" + ) + abs_hor_graph.hist(abscissa, bins=50, color="red", alpha=0.5, edgecolor="black") + ord_vert_graph.invert_xaxis() + abs_hor_graph.invert_yaxis() + + if diagram_type == "violin": + viol_vert = ord_vert_graph.violinplot( + ordinates, + showmedians=True, + ) + for body in viol_vert["bodies"]: + body.set_facecolor("red") + body.set_edgecolor("black") + for parts in viol_vert: + if parts == "bodies": + continue + viol_vert[parts].set_edgecolor("black") + viol_hor = abs_hor_graph.violinplot(abscissa, vert=False, showmedians=True) + for body in viol_hor["bodies"]: + body.set_facecolor("red") + body.set_edgecolor("black") + for parts in viol_hor: + if parts == "bodies": + continue + viol_hor[parts].set_edgecolor("black") if __name__ == "__main__": diff --git a/solutions/sem02/lesson07/task2.py b/solutions/sem02/lesson07/task2.py index decd607e..9c29919a 100644 --- a/solutions/sem02/lesson07/task2.py +++ b/solutions/sem02/lesson07/task2.py @@ -1 +1,43 @@ # ваш код (используйте функции или классы для решения данной задачи) +import json + +import matplotlib.pyplot as plt +import numpy as np + + +def get_counts(tier_list, stages_order): + arr = np.array(tier_list) + return np.array([np.sum(arr == stage) for stage in stages_order]) + + +def solution(): + plt.style.use("ggplot") + with open("solutions\sem02\lesson07\data\medic_data.json") as f: + data = json.load(f) + + stages_order = ["I", "II", "III", "IV"] + + before_count = get_counts(data["before"], stages_order) + after_count = get_counts(data["after"], stages_order) + + fig, ax = plt.subplots(figsize=(12, 7)) + x = np.arange(len(stages_order)) + width = 0.35 + + ax.bar(x - width / 2, before_count, width, label="До установки", color="red", edgecolor="black") + ax.bar( + x + width / 2, after_count, width, label="После установки", color="green", edgecolor="black" + ) + ax.set_title("Стадии митральной недостаточности") + ax.set_ylabel("Кол-во людей") + ax.set_xticks(x) + ax.set_xticklabels(stages_order) + ax.legend() + fig.tight_layout() + + plt.savefig("result.png") + plt.show() + + +if __name__ == "__main__": + solution()