Created
May 20, 2019 03:06
-
-
Save Shuumatsu/5debc628c1c65c0b781cf3aa2f997d0c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open Base | |
module Make (Comparable : Comparable.S) = struct | |
let sort_into_piles list = | |
let piles = Array.create ~len:(List.length list) [] in | |
let bsearch len elem = | |
let rec aux lo hi = | |
if lo > hi then lo | |
else | |
let mid = (lo + hi) / 2 in | |
if Comparable.compare elem (List.hd_exn piles.(mid)) <= 0 then | |
aux lo (mid-1) | |
else aux (mid + 1) hi | |
in | |
aux 0 (len - 1) | |
in | |
let len = | |
List.fold ~init:0 | |
~f:(fun len elem -> | |
let idx = bsearch len elem in | |
piles.(idx) <- elem :: piles.(idx) ; | |
if idx = len then len + 1 else len ) | |
list | |
in | |
List.init len ~f:(fun idx -> piles.(idx)) | |
let rec merge_piles piles = | |
let rec two_way_merge accu lista listb = | |
match (lista, listb) with | |
| (_ as rest), [] | [], (_ as rest) -> | |
List.rev accu @ rest | |
| x :: xs, y :: ys -> | |
if Comparable.compare x y <= 0 then two_way_merge (x :: accu) xs listb | |
else two_way_merge (y :: accu) lista ys | |
in | |
match piles with | |
| [] -> | |
[] | |
| [pile] -> | |
pile | |
| la :: lb :: rest -> | |
two_way_merge [] (two_way_merge [] la lb) (merge_piles rest) | |
let patience_sort list = merge_piles (sort_into_piles list) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment