let rec pow a = function | 0 -> 1 | 1 -> a | n -> let b = pow a (n / 2) in b * b * (if n mod 2 = 0 then 1 else a) let rec powmod a d = function | 0 -> 1 | 1 -> a mod d | n -> let b = (powmod a d (n / 2)) mod d in (((b * b) mod d) * (if n mod 2 = 0 then 1 else a)) mod d let int_and a b = match (a>0, b>0) with true, true -> 1 | _, _ -> 0 let int_or a b = match (a>0, b>0) with false, false -> 0 | _, _ -> 1 let int_eq a b = if a = b then 1 else 0 let int_less a b = if a < b then 1 else 0 let int_less_eq a b = if a <= b then 1 else 0 let int_more a b = if a > b then 1 else 0 let int_more_eq a b = if a >= b then 1 else 0 let int_not a = if a > 0 then 0 else 1 (* converts an integer to a list of chars such that it is pretty and linear *) (* let rec fromIntToString (alphabet: string) (x: int) : string = *) (* let base = String.length alphabet in *) (* if x < 0 then *) (* "" *) (* else if x < base then *) (* String.get alphabet x |> String.make 1 *) (* else *) (* (fromIntToString (alphabet) (x/base - 1)) ^ *) (* (String.get alphabet (x mod base) |> String.make 1) *) (* true if every element of la is in lb *) let inclusion la lb = let rec aux la = function [] -> true | b::lb -> List.mem b la && aux la lb in aux lb la (* true if lb includes la and la includes lb *) let equality la lb = inclusion la lb && inclusion lb la (* computes the result of la \setminus lb *) let subtraction la lb = let rec aux la = function [] -> la | b::lb -> aux (List.filter ((<>) b) la) lb in aux la lb (* returns only the unique elements of l *) let unique l = let rec aux l acc = match l with | [] -> List.rev acc | h :: t -> if List.mem h acc then aux t acc else aux t (h :: acc) in aux l [] (* returns the unique elements of the concat of the lists *) let unique_union la lb = la @ lb |> unique (* returns all elements both in la and in lb *) let unique_intersection la lb = let rec aux la acc = match la with [] -> acc | a::la -> if List.mem a lb then aux la (a::acc) else aux la acc in aux la [] |> unique (* given two lists of associations combines them and if an item is the same, a provided function is applied to the associated values to create the new association *) let unique_union_assoc f l1 l2 = let rec aux l acc = match l with | [] -> acc | (h1, h2) :: t -> ( match List.find_opt (fun (a, _) -> a = h1) acc with | None -> aux t ((h1, h2) :: acc) | Some (_h1, h3) -> aux t ((h1, f h1 h2 h3) :: (List.remove_assoc h1 acc)) ) in aux l2 (aux l1 []) (* returns a list with at most n items and the rest in the second *) let rec take (n: int) (l: 'a list) : ('a list * 'a list) = if n = 0 then ([], l) else match l with | [] -> ([], []) | i::ls -> let (t1, t2) = (take (n - 1) ls) in ((i :: t1), (t2)) (* takes a list and returns the same list without the first element; different from List.tl since returns the empty list if there are not enough items*) let drop_first_element_list = function | [] -> [] | _::l -> l (* retuns the last element of a list *) let rec last_list l = match l with [] -> failwith "Utility.last_list, not enough items" | [a] -> a | _::ll -> last_list ll (* combines two lists into a list of tuples; different from List.combine since lengths do not need to be equal, the functions return a list with length equal to the minimum of the input lists *) let rec combine_twice la lb = match (la, lb) with | [], [] -> [] | [a], [b] -> [a, b] | a::la, b::lb -> (a, b) :: (combine_twice la lb) | _ -> []