diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000000..2f0a9172a5
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,25 @@
+name: Run tests
+
+on: [push]
+
+jobs:
+ test:
+ runs-on: ${{matrix.runner}}
+
+ strategy:
+ matrix:
+ runner: [ubuntu-latest, windows-latest]
+ file: [circle.py, rectangle.py, square.py, triangle.py]
+ python-version: ["3.12.6"]
+
+ fail-fast: false
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: ${{matrix.python-version}}
+
+ - name: Run ${{matrix.file}} tests
+ run: python -m unittest ${{matrix.file}}
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000000..26d33521af
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000000..1805227d44
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+circle.py
\ No newline at end of file
diff --git a/.idea/geometric_lib.iml b/.idea/geometric_lib.iml
new file mode 100644
index 0000000000..8b8c395472
--- /dev/null
+++ b/.idea/geometric_lib.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000000..105ce2da2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000..db8786c06e
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000000..5c0675083d
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000..35eb1ddfbb
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/circle.py b/circle.py
index c3eb8647c9..7f84114928 100644
--- a/circle.py
+++ b/circle.py
@@ -1,10 +1,73 @@
import math
-
+from unittest import TestCase
def area(r):
+ '''Возвращает площадь круга с радиусом r.
+ Параметры:
+ r (int): радиус круга
+ Возвращаемое значение:
+ pi * r * r (float): площадь круга с радиусом r
+ Пример вызова area(3):
+ Входные данные: 3
+ Вывод: 28.2743338823'''
+
+ if not (isinstance(r, int) or isinstance(r, float)):
+ raise TypeError("Argument must be int or float")
+
+ if r <= 0:
+ raise ValueError("Argument must be positive")
+
return math.pi * r * r
def perimeter(r):
+ '''Возвращает периметр круга с радиусом r.
+ Параметры:
+ r (int): радиус круга
+ Возвращаемое значение:
+ 2 * pi * r (float): периметр круга с радиусом r
+ Пример вызова perimetr(3):
+ Входные данные: 3
+ Вывод: 18.8495559215'''
+
+ if not (isinstance(r, int) or isinstance(r, float)):
+ raise TypeError("Argument must be int or float")
+
+ if r <= 0:
+ raise ValueError("Argument must be positive")
+
return 2 * math.pi * r
+
+
+
+class CircleTestCase(TestCase):
+ def test_area_with_integer_radius(self):
+ self.assertEqual(area(5), 78.53981633974483)
+
+ def test_area_with_float_radius(self):
+ self.assertEqual(area(2.5), 19.634954084936208)
+
+ def test_area_with_incorrect_type_radius(self):
+ self.assertRaises(TypeError, area, [])
+
+ def test_area_with_negative_radius(self):
+ self.assertRaises(ValueError, area, -1)
+
+ def test_area_with_zero_radius(self):
+ self.assertRaises(ValueError, area, 0)
+
+ def test_perimeter_with_integer_radius(self):
+ self.assertEqual(perimeter(4), 25.132741228718345)
+
+ def test_perimeter_with_float_radius(self):
+ self.assertEqual(perimeter(3.5), 21.991148575128552)
+
+ def test_perimeter_with_incorrect_type_radius(self):
+ self.assertRaises(TypeError, perimeter, [])
+
+ def test_perimeter_with_negative_radius(self):
+ self.assertRaises(ValueError, perimeter, -2)
+
+ def test_perimeter_with_zero_radius(self):
+ self.assertRaises(ValueError, perimeter, 0)
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
index 63f8727939..89fd7ecb8b 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -7,4 +7,108 @@
## Perimeter
- Circle: P = 2πR
- Rectangle: P = 2a + 2b
-- Square: P = 4a
\ No newline at end of file
+- Square: P = 4a
+
+# Документация
+## Общее описание решения
+Этот проект предоставляет набор модулей для вычисления площади и периметра различных геометрических фигур: круга, прямоугольника, квадрата и треугольника. Каждый модуль реализует функции для работы с соответствующей фигурой.
+### Структура проекта
+- circle.py: Модуль для работы с кругами.
+- rectangle.py: Модуль для работы с прямоугольниками.
+- square.py: Модуль для работы с квадратами.
+- triangle.py: Модуль для работы с треугольниками.
+## Использование
+### [circle.py](../blob/new_features_467568/circle.py)
+Модуль `circle.py` предоставляет функции для вычисления площади и периметра круга.
+#### Функции
+- `area(r)`
+ Возвращает площадь круга с радиусом `r`
+ **Параметры:**
+ `r`: радиус круга
+ **Возвращаемое значение:**
+ `pi * r * r`: площадь круга с радиусом r
+ **Пример вызова `area(3)`:**
+ Входные данные: `3`
+ Вывод: `28.2743338823`
+- `perimeter(r)`
+ Возвращает периметр круга с радиусом `r`
+ **Параметры:**
+ `r`: радиус круга
+ **Возвращаемое значение:**
+ `2 * pi * r`: периметр круга с радиусом r
+ **Пример вызова `perimeter(3)`:**
+ Входные данные: `3`
+ Вывод: `18.8495559215`
+
+### [rectangle.py](../blob/new_features_467568/rectangle.py)
+Модуль `rectangle.py` предоставляет функции для вычисления площади и периметра прямоугольника.
+#### Функции
+- `area(a, b)`
+ Возвращает площадь прямоугольника со сторонами `a` и `b`
+ **Параметры:**
+ `a`, `b`: стороны прямоугольника
+ **Возвращаемое значение:**
+ `a * b`: площадь прямоугольника
+ **Пример вызова `area(3, 2)`:**
+ Входные данные: `3 2`
+ Вывод: `6`
+- `perimeter(a, b)`
+ Возвращает периметр прямоугольника со сторонами `a` и `b`
+ **Параметры:**
+ `a`, `b`: стороны прямоугольника
+ **Возвращаемое значение:**
+ `(a + b) * 2`: периметр прямоугольника
+ **Пример вызова `perimeter(3, 2)`:**
+ Входные данные: `3 2`
+ Вывод: `10`
+
+### [square.py](../blob/new_features_467568/square.py)
+Модуль `square.py` предоставляет функции для вычисления площади и периметра квадрата.
+#### Функции
+- `area(a)`
+ Возвращает площадь квадрата со стороной `a`
+ **Параметры:**
+ `a`: сторона квадрата
+ **Возвращаемое значение:**
+ `a * a`: площадь квадрата
+ **Пример вызова `area(3)`:**
+ Входные данные: `3`
+ Вывод: `9`
+- `perimeter(a)`
+ Возвращает периметр квадрата со стороной `a`
+ **Параметры:**
+ `a`: сторона квадрата
+ **Возвращаемое значение:**
+ `a * 4`: периметр квадрата
+ **Пример вызова `perimeter(3)`:**
+ Входные данные: `3`
+ Вывод: `12`
+
+### [triangle.py](../blob/new_features_467568/triangle.py)
+Модуль `triangle.py` предоставляет функции для вычисления площади и периметра треугольника.
+#### Функции
+- `area(a, h)`
+ Возвращает площадь треугольника со стороной `a` и высотой `h`
+ **Параметры:**
+ `a`: сторона треугольника
+ `h`: высота треугольника
+ **Возвращаемое значение:**
+ `0.5 * a * h`: площадь треугольника
+ **Пример вызова `area(3, 2)`:**
+ Входные данные: `3 2`
+ Вывод: `3`
+- `perimeter(a, b, c)`
+ Возвращает периметр треугольника со сторонами `a`, `b` и `c`
+ **Параметры:**
+ `a`, `b`, `c`: стороны треугольника
+ **Возвращаемое значение:**
+ `a + b + c`: периметр треугольника
+ **Пример вызова `perimeter(3, 2, 1)`:**
+ Входные данные: `3 2 1`
+ Вывод: `6`
+
+# Изменения
+- `8ba9aeb3cea847b63a91ac378a2a6db758682460` Circle and square added
+- `d078c8d9ee6155f3cb0e577d28d337b791de28e2` Docs added
+- `8f4a7dd8b959ebff7b402e683390fc08c7e0c65f` added rectangle function
+- `d3dfeaa4a9e2b6ece28dbc2da97ee90793f45031` fixed rectangle function
diff --git a/rectangle.py b/rectangle.py
new file mode 100644
index 0000000000..2c6ebe957c
--- /dev/null
+++ b/rectangle.py
@@ -0,0 +1,74 @@
+from unittest import TestCase
+
+def area(a, b):
+ '''Возвращает площадь прямоугольника со сторонами a и b
+ Параметры:
+ a, b: стороны прямоугольника
+ Возвращаемое значение:
+ a * b: площадь прямоугольника
+ Пример вызова area(3, 2):
+ Входные данные: 3 2
+ Вывод: 6'''
+
+ if not (isinstance(a, int) or isinstance(a, float)) or not (isinstance(b, int) or isinstance(b, float)):
+ raise TypeError("Argument must be int or float")
+
+ if a <= 0 or b <= 0:
+ raise ValueError("Argument must be positive")
+
+ return a * b
+
+def perimeter(a, b):
+ '''Возвращает периметр прямоугольника со сторонами a и b
+ Параметры:
+ a, b: стороны прямоугольника
+ Возвращаемое значение:
+ (a + b) * 2: периметр прямоугольника
+ Пример вызова perimetr(3, 2)`:
+ Входные данные: 3 2
+ Вывод: 10'''
+
+ if not (isinstance(a, int) or isinstance(a, float)) or not (isinstance(b, int) or isinstance(b, float)):
+ raise TypeError("Argument must be int or float")
+
+ if a <= 0 or b <= 0:
+ raise ValueError("Argument must be positive")
+
+ return (a + b) * 2
+
+class RectangleTestCase(TestCase):
+ def test_area_with_integer_dimensions(self):
+ self.assertEqual(area(3, 4), 12)
+
+ def test_area_with_float_dimensions(self):
+ self.assertEqual(area(2.5, 1.5), 3.75)
+
+ def test_area_with_mixed_types(self):
+ self.assertEqual(area(2, 2.0), 4.0)
+
+ def test_area_with_incorrect_type(self):
+ self.assertRaises(TypeError, area, [], 1)
+
+ def test_area_with_negative_value(self):
+ self.assertRaises(ValueError, area, 2, -3)
+
+ def test_area_with_zero_value(self):
+ self.assertRaises(ValueError, area, 0, 1)
+
+ def test_perimeter_with_integer_dimensions(self):
+ self.assertEqual(perimeter(3, 4), 14)
+
+ def test_perimeter_with_float_dimensions(self):
+ self.assertEqual(perimeter(2.5, 1.5), 8.0)
+
+ def test_perimeter_with_mixed_types(self):
+ self.assertEqual(perimeter(2.0, 3), 10)
+
+ def test_perimeter_with_incorrect_type(self):
+ self.assertRaises(TypeError, perimeter, [], [])
+
+ def test_perimeter_with_negative_value(self):
+ self.assertRaises(ValueError, perimeter, -2, 3)
+
+ def test_perimeter_with_zero_value(self):
+ self.assertRaises(ValueError, perimeter, 1, 0)
\ No newline at end of file
diff --git a/square.py b/square.py
index 0f98724205..a20291712e 100644
--- a/square.py
+++ b/square.py
@@ -1,7 +1,69 @@
+from unittest import TestCase
def area(a):
+ '''Возвращает площадь квадрата со стороной a
+ Параметры:
+ a: сторона квадрата
+ Возвращаемое значение:
+ a * a: площадь квадрата
+ Пример вызова area(3):
+ Входные данные: 3
+ Вывод: 9'''
+
+ if not (isinstance(a, int) or isinstance(a, float)):
+ raise TypeError("Argument must be int or float")
+
+ if a <= 0:
+ raise ValueError("Argument must be positive")
+
return a * a
def perimeter(a):
+ '''Возвращает периметр квадрата со стороной a
+ Параметры:
+ a: сторона квадрата
+ Возвращаемое значение:
+ a * 4: периметр квадрата
+ Пример вызова perimetr(3):
+ Входные данные: 3
+ Вывод: 12'''
+
+ if not (isinstance(a, int) or isinstance(a, float)):
+ raise TypeError("Argument must be int or float")
+
+ if a <= 0:
+ raise ValueError("Argument must be positive")
+
return 4 * a
+
+class SquareTestCase(TestCase):
+ def test_area_with_integer_dimension(self):
+ self.assertEqual(area(3), 9)
+
+ def test_area_with_float_dimension(self):
+ self.assertEqual(area(2.5), 6.25)
+
+ def test_area_with_incorrect_type(self):
+ self.assertRaises(TypeError, area, [])
+
+ def test_area_with_negative_value(self):
+ self.assertRaises(ValueError, area, -1)
+
+ def test_area_with_zero_value(self):
+ self.assertRaises(ValueError, area, 0)
+
+ def test_perimeter_with_integer_dimension(self):
+ self.assertEqual(perimeter(3), 12)
+
+ def test_perimeter_with_float_dimension(self):
+ self.assertEqual(perimeter(2.5), 10.0)
+
+ def test_perimeter_with_incorrect_type(self):
+ self.assertRaises(TypeError, perimeter, [])
+
+ def test_perimeter_with_negative_value(self):
+ self.assertRaises(ValueError, perimeter, -1)
+
+ def test_perimeter_with_zero_value(self):
+ self.assertRaises(ValueError, perimeter, 0)
diff --git a/triangle.py b/triangle.py
new file mode 100644
index 0000000000..d66efd2abc
--- /dev/null
+++ b/triangle.py
@@ -0,0 +1,79 @@
+from unittest import TestCase
+
+def area(a, h):
+ '''
+ Возвращает площадь треугольника со стороной a и высотой h
+ Параметры:
+ a: сторона треугольника
+ h: высота треугольника
+ Возвращаемое значение:
+ a * a: площадь треугольника
+ Пример вызова area(3, 2):
+ Входные данные: 3, 2
+ Вывод: 3
+ '''
+
+ if not (isinstance(a, int) or isinstance(a, float)) or not (isinstance(h, int) or isinstance(h, float)):
+ raise TypeError("Argument must be int or float")
+
+ if a <= 0 or h <= 0:
+ raise ValueError("Argument must be positive")
+
+ return a * h / 2
+
+
+def perimeter(a, b, c):
+ '''Возвращает периметр треугольника со сторонами a, b и c
+ Параметры:
+ a, b, c: стороны треугольника
+ h: высота треугольника
+ Возвращаемое значение:
+ a + b + c: периметр треугольника
+ Пример вызова perimetr(3, 2, 1):
+ Входные данные: 3 2 1
+ Вывод: 6'''
+
+ if not (isinstance(a, int) or isinstance(a, float)) or not (isinstance(b, int) or isinstance(b, float)) or not (isinstance(c, int) or isinstance(c, float)):
+ raise TypeError("Argument must be int or float")
+
+ if a <= 0 or b <= 0 or c <= 0:
+ raise ValueError("Argument must be positive")
+
+ return a + b + c
+
+class TriangleTestCase(TestCase):
+ def test_area_with_integer_base_and_height(self):
+ self.assertEqual(area(2, 3), 3)
+
+ def test_area_with_float_base_and_height(self):
+ self.assertEqual(area(1.5, 4.0), 3.0)
+
+ def test_area_with_mixed_types(self):
+ self.assertEqual(area(1.5, 4), 3.0)
+
+ def test_area_with_invalid_type(self):
+ self.assertRaises(TypeError, area, [], [])
+
+ def test_area_with_negative_base(self):
+ self.assertRaises(ValueError, area, -3, 2)
+
+ def test_area_with_zero_height(self):
+ self.assertRaises(ValueError, area, 1, 0)
+
+ def test_perimeter_with_integer_sides(self):
+ self.assertEqual(perimeter(1, 2, 3), 6)
+
+ def test_perimeter_with_float_sides(self):
+ self.assertEqual(perimeter(1.5, 1.0, 2.5), 5.0)
+
+ def test_perimeter_with_mixed_types(self):
+ self.assertEqual(perimeter(1.5, 1, 2.5), 5.0)
+
+ def test_perimeter_with_invalid_type(self):
+ self.assertRaises(TypeError, perimeter, [], [], [])
+
+ def test_perimeter_with_negative_side(self):
+ self.assertRaises(ValueError, perimeter, -3, 2, 1)
+
+ def test_perimeter_with_zero_side(self):
+ self.assertRaises(ValueError, perimeter, 0, 3, 2)
\ No newline at end of file