diff --git a/tp9/merge_sort.py b/tp9/merge_sort.py new file mode 100644 index 0000000000000000000000000000000000000000..4da108338ae8f5e192c33db3e0d0043eac3533f5 --- /dev/null +++ b/tp9/merge_sort.py @@ -0,0 +1,197 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`recursive sorts` +:author: `FIL - FST - Univ. Lille.fr <http://portail.fil.univ-lille1.fr>`_ +:date: 2016, september. Last revised: 2018, september + +Some recursive sorting algorithms: + +- quicksort +- mergesort + +""" +from typing import Callable, TypeVar +from aplst import ApLst + + +T = TypeVar('T') + + +def compare(a: T, b: T) -> int: + """ + return: + - -1 if a < b + - 1 if a > b + - 0 if a = b + precondition: a and b must be comparable with < + exemples: + + $$$ compare(0, 1) + -1 + $$$ compare('a', 'a') + 0 + $$$ compare((2, 1), (1, 2)) + 1 + """ + if a < b: + return -1 + elif a > b: + return 1 + else: + return 0 + + +def length(li: ApLst) -> int: + """ + return the length of li. + + precondition: none + + examples: + + $$$ length(ApLst()) + 0 + $$$ length(ApLst(3, ApLst(1, ApLst(4, ApLst())))) + 3 + """ + leng = 0 + while not li.is_empty(): + li = li.tail() + leng += 1 + return leng + + + +def native_to_list(li: list[T]) -> ApLst: + """ + return a recursive list containing the same element of li. + + precondition: none + + examples: + + $$$ native_to_list([]).is_empty() + True + $$$ rec_lst = native_to_list([3, 1, 4, 1, 5]) + $$$ length(rec_lst) + 5 + $$$ rec_lst.head() + 3 + $$$ l = rec_lst.tail() + $$$ l.head() + 1 + $$$ l = l.tail() + $$$ l.head() + 4 + """ + l = ApLst() + for i in range(1, len(li)+1): + l = ApLst(li[-i], l) + return l + + +def list_to_native(li: ApLst) -> list[T]: + """ + return a native python list containing the same element of li. + + precondition: none + + examples: + + $$$ list_to_native(ApLst()) + [] + $$$ list_to_native(ApLst(3, ApLst(1, ApLst(4, ApLst(1, ApLst(5, ApLst())))))) + [3, 1, 4, 1, 5] + """ + l = [] + while not li.is_empty(): + l.append(li.head()) + li = li.tail() + return l + + +def is_sorted(l: ApLst, comp: Callable[[T, T], int]=compare) -> bool: + """ + return True if list l is sorted by ascending order + and False otherwise. + + precondition: elements of l must be comparable + exemples: + + $$$ is_sorted(native_to_list([1, 2, 3, 4])) + True + $$$ is_sorted(native_to_list([1, 2, 4, 3])) + False + """ + res = True + for i in range(length(l)-1): + a = l.head() + l = l.tail() + if a > l.head(): + res = False + return res + + +def split(l: ApLst) -> tuple[ApLst, ApLst]: + """ + return a couple (l1,l2) of lists of equal length + + exemples: + + $$$ l = [3, 1, 4, 1, 5, 9, 2] + $$$ l1, l2 = split(native_to_list(l)) + $$$ abs(length(l1) - length(l2)) <= 1 + True + $$$ l3 = list_to_native(l1) + list_to_native(l2) + $$$ len(l3) == len(l) + True + $$$ all(k in l for k in l3) + True + """ + + + +def merge(l1: ApLst, l2: ApLst, + comp: Callable[[T, T], int]=compare) -> ApLst: + """ + return a list containing all elements de l1 and l2. + If l1 and l2 are sorted, so is the returned list. + + precondition: elements of l1 and l2 are comparable + exemples: + + $$$ list_to_native(merge(native_to_list([1, 3, 4, 9]), native_to_list([1, 2, 5]))) + [1, 1, 2, 3, 4, 5, 9] + """ + ... + + +def mergesort(l: ApLst, comp: Callable[[T, T], int]=compare) -> ApLst: + """ + return a new list containing elements of l sorted by ascending order. + + precondition: elements of l are comparable + exemples: + + $$$ list_to_native(mergesort(native_to_list([3, 1, 4, 1, 5, 9, 2]))) + [1, 1, 2, 3, 4, 5, 9] + $$$ import random + $$$ n = random.randrange(20) + $$$ l = native_to_list([random.randrange(20) for k in range(n)]) + $$$ l1 = mergesort(l) + $$$ length(l1) == length(l) + True + $$$ is_sorted(l1) + True + """ + ... + + +if (__name__ == '__main__'): + import apl1test + apl1test.testmod("merge_sort.py") + + +