open List

(* Sort a list l using the quicksort algorithm *)
let rec quickSort (l : int list) =
    match l with
    ([] | [_]) -> l
    | pivot::rest ->
        let cmp x = x < pivot in
        let low, high = partition cmp rest in
        quickSort low @ pivot :: quickSort high

(* Sort a list l using the merge sort algorithm *)
let rec mergeSort (l : int list) =
    match l with
    (* If the list is of length 0 or 1, then it is already sorted *)
    ([] | [_]) -> l
    | _ ->
        let rec merge a b =
            match a with
            [] -> b
            | ha::ta -> match b with
                [] -> a
                | hb::tb -> if ha < hb then ha::(merge ta b)
                                       else hb::(merge a tb)
        in
        let rec split left right =
            if (length left) - (length right) <= 1 then
                (* List lengths differ at most 1 element, split is complete *)
                (left, right)
            else
                match left with
                [] -> (left, right)
                (* Put one element of left into right list *)
                | h::t -> split t (h::right)
        in
        let left, right = split l [] in
        merge (mergeSort left) (mergeSort right)
