https://github.com/xi-business/infsat
Raw File
Tip revision: 31552cff3d6d4239fcf05c9c201e9c2fa3678b7a authored by Jan Wroblewski on 10 February 2022, 12:43:54 UTC
Removed unusable benchmark and renamed the other g45 one.
Tip revision: 31552cf
sortedList.ml
module type SL = sig
  type elt
  type t = L of elt list

  val empty : t
  val singleton : elt -> t
  val of_list : elt list -> t
  val to_list : t -> elt list
  val to_ilist : t -> (int * elt) list
  val init : (int -> elt) -> int -> t
  
  val mem : elt -> t -> bool
  val hd : t -> elt
  val hd_option : t -> elt option
  val hd_tl_option : t -> (elt * t) option
  val tl : t -> t
  val length : t -> int
  val is_empty : t -> bool
  val sublist : t -> t -> bool
  
  val partition : (elt -> bool) -> t -> t * t
  val filter : (elt -> bool) -> t -> t
  val uniq : t -> t
  val intersect_custom : (elt -> elt -> elt) -> t -> t -> t
  val merge_custom : (elt -> elt -> elt) -> t -> t -> t
  val merge : t -> t -> t
  val merge_duplicates : (elt -> elt -> elt) -> t -> t
  val for_all : (elt -> bool) -> t -> bool
  val exists : (elt -> bool) -> t -> bool

  val remove_duplicates : t -> t
  val fold_left : ('a -> elt -> 'a) -> 'a -> t -> 'a
  val fold_left_short_circuit : 'a -> t -> 'a -> ('a -> elt -> 'a) -> 'a
  val fold_right : (elt -> 'a -> 'a) -> t -> 'a -> 'a
  val filter_map : (elt -> 'a option) -> t -> 'a list
  val map : (elt -> 'a) -> t -> 'a list
  val map_monotonic : (elt -> elt) -> t -> t
  val rev_map : (elt -> 'a) -> t -> 'a list
  val iter : (elt -> unit) -> t -> unit
  val compare_custom : (elt -> elt -> int) -> t -> t -> int
  val compare : t -> t -> int
  val equal_custom : (elt -> elt -> int) -> t -> t -> bool
  val equal : t -> t -> bool
  val hash : (elt -> int) -> t -> int

  val to_string : (elt -> string) -> t -> string
end

module Make (Ord : Set.OrderedType) =
struct
  type elt = Ord.t
  type t = L of elt list

  (* construction *)
        
  let empty = L []
      
  let singleton x = L [x]

  let of_list l = L (List.sort Ord.compare l)

  let of_sorted_list l =
    assert (Utilities.is_sorted Ord.compare l);
    L l

  let to_list (L l) = l

  let to_ilist (L l) = List.mapi (fun i x -> (i, x)) l

  let init f n =
    let rec init_list i acc =
      if i = 0 then
        acc
      else
        init_list (i - 1) (f (i - 1) :: acc)
    in
    L (List.sort Ord.compare (init_list n []))

  (* basic operations *)
  
  let mem x (L l) =
    List.exists (fun y -> Ord.compare x y = 0) l

  let hd (L l) = List.hd l

  let hd_option (L l) =
    match l with
    | [] -> None
    | h :: l' -> Some h

  let hd_tl_option (L l) =
    match l with
    | [] -> None
    | h :: l' -> Some (h, L l')

  let tl (L l) = L (List.tl l)
  
  let length (L l) = List.length l

  let is_empty (L l) = l = []

  let sublist (L outer) (L inner) =
    let rec sublist_list outer inner =
      match outer, inner with
      | [], [] -> true
      | _, [] -> true
      | [], _ -> false
      | oh :: outer', ih :: inner' ->
        let c = Ord.compare oh ih in
        if c = 0 then
          sublist_list outer' inner'
        else if c < 0 then
          sublist_list outer' inner
        else
          false
    in
    sublist_list outer inner

  (* splitting, filtering, and joining *)

  let partition f (L l) =
    let a, b = List.partition f l in
    (L a, L b)

  let filter f (L l) = L (List.filter f l)

  let uniq (L l) =
    let rec uniq_list l acc =
      match l with
      | x :: (y :: _ as l') ->
        if Ord.compare x y = 0 then
          uniq_list l' acc
        else
          uniq_list l' (x :: acc)
      | [x] ->
        uniq_list [] (x :: acc)
      | [] -> List.rev acc
    in
    L (uniq_list l [])

  let intersect_custom intersect_fun (L l1) (L l2) =
    let rec intersect_lists l1 l2 =
      match l1, l2 with
      | _, [] -> []
      | [], _ -> []
      | x :: l1', y :: l2' -> 
        let c = Ord.compare x y in
        if c = 0 then
          (intersect_fun x y) :: (intersect_lists l1' l2')
        else if c < 0 then
          intersect_lists l1' l2
        else
          intersect_lists l1 l2'
    in
    L (intersect_lists l1 l2)
  
  (** Merge two sorted lists with special merge function for equal values. *)
  let merge_custom merge_fun (L l1) (L l2) =
    let rec merge_lists l1 l2 =
      match l1, l2 with
      | _, [] -> l1
      | [], _ -> l2
      | x :: l1', y :: l2' -> 
        let c = Ord.compare x y in
        if c = 0 then
          (merge_fun x y) :: (merge_lists l1' l2')
        else if c < 0 then
          x :: (merge_lists l1' l2)
        else
          y :: (merge_lists l1 l2')
    in
    L (merge_lists l1 l2)

  (** Merge two sorted lists idempodently, resulting in sorted list with unique values. *)
  let merge sl1 sl2 =
    merge_custom (fun x _ -> x) sl1 sl2

  (** Merges consecutive duplicates. merge_fun x y must be equal to y according to given
      ordering. *)
  let merge_duplicates merge_fun (L l) =
    let rec merge_duplicates_aux acc = function
      | [] -> []
      | ([x] as l') -> List.rev_append acc l'
      | x :: (y :: l' as yl) ->
        if Ord.compare x y = 0 then
          merge_duplicates_aux acc @@ (merge_fun x y) :: l'
        else
          merge_duplicates_aux (x :: acc) yl
    in
    L (merge_duplicates_aux [] l)

  let for_all f (L l) = List.for_all f l
  
  let exists f (L l) = List.exists f l

  (* iteration *)

  (** Returns the same list without duplicates. *)
  let remove_duplicates (L l) =
    L (Utilities.delete_consecutive_duplicates Ord.compare l)
  
  let fold_left f acc (L l) = List.fold_left f acc l

  let fold_left_short_circuit acc (L l) bottom f = Utilities.fold_left_short_circuit acc l bottom f

  let fold_right f (L l) acc = List.fold_right f l acc

  let filter_map f (L l) = List.filter_map f l
  
  let map f (L l) = List.map f l

  let map_monotonic f (L l) = L (List.map f l)
      
  let rev_map f (L l) = List.rev_map f l

  let iter f (L l) = List.iter f l

  let compare_custom compare_elt (L l1) (L l2) =
    let rec compare_lists l1 l2 =
      match l1, l2 with
      | x1 :: l1', x2 :: l2' ->
        let res = compare_elt x1 x2 in
        if res = 0 then
          compare_lists l1' l2'
        else
          res
      | [], [] -> 0
      | [], _ -> -1
      | _, [] -> 1
    in
    compare_lists l1 l2

  let compare l1 l2 =
    compare_custom Ord.compare l1 l2

  let equal_custom compare_elt l1 l2 = compare_custom compare_elt l1 l2 = 0

  let equal = equal_custom Ord.compare

  let hash h l =
    fold_left (fun acc x ->
        acc lxor (acc lsl 1) lxor h x
      ) 0 l

  (* pretty printing *)

  let to_string p (L l) =
    Utilities.string_of_list p l
end
back to top