diff --git a/03/README.md b/03/README.md new file mode 100644 index 0000000..e04227f --- /dev/null +++ b/03/README.md @@ -0,0 +1,21 @@ +### Что здесь лежит? +- в директории `merge` -- типизированный код с реализацией +сортировки слиянием; +- в директории `tests` -- соответственно, тесты; + +### Как запускать? + +Желательно установить [mypy](https://github.com/python/mypy) или даже +[pyright](https://github.com/microsoft/pyright) и проверять типизацию +ими перед запусками: +```sh +$ mypy --install-types --show-error-codes --pretty . +``` + +_*Выясните самостоятельно:*_ +что делают флаги `--install-types`, `--show-error-codes`, `--pretty`? + +Для запуска тестов: +```sh +$ python -m unittest discover -v tests/ +``` diff --git a/03/merge/__init__.py b/03/merge/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/03/merge/imlementation.py b/03/merge/imlementation.py new file mode 100644 index 0000000..8e77dbc --- /dev/null +++ b/03/merge/imlementation.py @@ -0,0 +1,47 @@ +from collections import deque +from typing import List, Deque + + +def merge( + els1: List[int], + els2: List[int], +) -> List[int]: + """ + Merges two sorted lists into one, keeps order. + >>> merge([1, 2, 3], [3, 4, 5]) + [1, 2, 3, 3, 4, 5] + """ + result = [] + i, j = 0, 0 + while i < len(els1) and j < len(els2): + if els1[i] < els2[j]: + result.append(els1[i]) + i += 1 + else: + result.append(els2[j]) + j += 1 + + result.extend(els1[i:]) + result.extend(els2[j:]) + return result + + +def mergesort(elements: List[int]) -> List[int]: + """ + Sorts a given list. + """ + # -> if len(elements) == 0: + # if not elements: + if len(elements) <= 1: + return elements + + buffer: Deque[List[int]] = deque() + for el in elements: + buffer.append([el]) + + while len(buffer) > 1: + h1: List[int] = buffer.popleft() + h2: List[int] = buffer.popleft() + buffer.append(merge(h1, h2)) + + return buffer.pop() diff --git a/03/tests/__init__.py b/03/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/03/tests/test_merge.py b/03/tests/test_merge.py new file mode 100644 index 0000000..2d0000e --- /dev/null +++ b/03/tests/test_merge.py @@ -0,0 +1,61 @@ +import unittest + +from merge.imlementation import merge, mergesort + +from typing import List + + +class MergeTestCase(unittest.TestCase): + def test_merge_minimal(self): + self.assertEqual( + merge([], []), + [], + ) + + def test_merge_one(self): + self.assertEqual(merge([301], []), [301]) + self.assertEqual(merge([-301], []), [-301]) + self.assertEqual(merge([], [-31]), [-31]) + self.assertEqual(merge([], [31]), [31]) + + def test_merge_two(self): + self.assertEqual(merge([301], [1]), [1, 301]) + self.assertEqual(merge([1], [301]), [1, 301]) + self.assertEqual(merge([-301, 1], []), [-301, 1]) + self.assertEqual(merge([], [-301, 1]), [-301, 1]) + + def test_mergesort_minimal(self): + self.assertEqual( + mergesort([]), + [], + ) + + def test_mergesort_one(self): + self.assertEqual(mergesort([3]), [3]) + self.assertEqual(mergesort([-3]), [-3]) + + def test_mergesort_two(self): + self.assertEqual(mergesort([1, 3]), [1, 3]) + self.assertEqual(mergesort([3, 1]), [1, 3]) + self.assertEqual( + mergesort([3, 3]), + [3, 3], + ) + + def test_small(self): + self.assertEqual( + mergesort([3, 3, 1, 2, 4, 6, 2, 4]), + [1, 2, 2, 3, 3, 4, 4, 6], + ) + + def test_small2(self): + self.assertEqual( + mergesort([3, -3, 1, 2, 4, -6, 2, 4]), + [-6, -3, 1, 2, 2, 3, 4, 4], + ) + + # def test_forbidden(self): + # self.assertEqual( + # mergesort(["a", "b", 3]), + # ["a", "b", 3], + # )