packages feed

egison-4.1.0: lib/core/order.egi

--
--
-- Order
--
--

def ordering :=
  algebraicDataMatcher
    | less
    | equal
    | greater

def compare m n :=
  if isCollection m
    then compareC m n
    else if m < n then Less else if m = n then Equal else Greater

def compareC c1 c2 :=
  match (c1, c2) as (list something, list something) with
    | ([], []) -> Equal
    | ([], _) -> Less
    | (_, []) -> Greater
    | ($x :: $xs, #x :: $ys) -> compareC xs ys
    | ($x :: _, $y :: _) -> compare x y

def min $x $y := if x < y then x else y
def max $x $y := if x > y then x else y

def min/fn f $xs := foldl1 2#(if f %1 %2 = Less then %1 else %2) xs
def max/fn f $xs := foldl1 2#(if f %1 %2 = Greater then %1 else %2) xs

def minimum $xs := foldl1 min xs
def maximum $xs := foldl1 max xs

def splitByOrdering := splitByOrdering/fn compare

def splitByOrdering/fn f p xs :=
  match xs as list something with
    | [] -> ([], [], [])
    | $x :: $rs ->
      let (ys1, ys2, ys3) := splitByOrdering/fn f p rs
       in match f x p as ordering with
            | less -> (x :: ys1, ys2, ys3)
            | equal -> (ys1, x :: ys2, ys3)
            | greater -> (ys1, ys2, x :: ys3)

def sort := sort/fn compare

def sort/fn f xs :=
  match xs as list something with
    | [] -> []
    | $x :: [] -> [x]
    | _ ->
      let n := length xs
          p := nth (quotient n 2) xs
          (ys1, ys2, ys3) := splitByOrdering/fn f p xs
       in sort/fn f ys1 ++ ys2 ++ sort/fn f ys3

def sortStrings xs :=
  sort/fn 2#(compareC (map ctoi (unpack %1)) (map ctoi (unpack %2))) xs

def merge xs ys :=
  match (xs, ys) as (list something, list something) with
    | ([], _) -> ys
    | (_, []) -> xs
    | ($x :: $txs, ?(>= x) :: _) -> x :: merge txs ys
    | (_, $y :: $tys) -> y :: merge xs tys

def merge/fn f xs ys :=
  match (xs, ys) as (list something, list something) with
    | ([], _) -> ys
    | (_, []) -> xs
    | ($x :: $txs, ?1#(f %1 x = Greater) :: _) -> x :: merge txs ys
    | (_, $y :: $tys) -> y :: merge xs tys

def minimize f xs :=
  foldl1 2#(if compare (f %1) (f %2) = Less then %1 else %2) xs

def maximize f xs :=
  foldl1 2#(if compare (f %1) (f %2) = Greater then %1 else %2) xs