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 -> if List.mem b la then aux la lb else false 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 = unique (la @ lb) (* 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 (* 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) = match n with | 0 -> ([], l) | n -> match l with | [] -> ([], []) | i::ls -> let (t1, t2) = (take (n - 1) ls) in ((i :: t1), (t2)) (* returns the list without the last element *) let drop_last_element_list = function | [] -> [] | l -> l |> List.rev |> List.tl |> List.rev let drop_first_element_list = function | [] -> [] | _::l -> l (* Complicated way to drop the last element and add a new option element to the beginning *) let prev l a = match l with | [] -> [a] | _ -> a :: (List.map (fun x -> Some x) (drop_last_element_list l)) let pad l a n = let l = List.map (fun i -> Some i) l in if List.length l < n then l @ (List.init (n - List.length l) (fun _ -> a)) else l let pad_opt l a n = if List.length l < n then l @ (List.init (n - List.length l) (fun _ -> a)) else l let combine la lb = List.map2 (fun a b -> match b with None -> None | Some b -> Some (a, b) ) la lb let rec last_list l = match l with [] -> failwith "Utility.last_list, not enough items" | [a] -> a | _::ll -> last_list ll let add_to_last_list (la: 'a list list) (a: 'a) : 'a list list = let rec aux la a = match la with [] -> [[a]] | [l] -> [a :: l] | l::la -> l :: (aux la a) in aux la a let rec combine_twice la lb = match (la, lb) with | [], [] -> [] | [a], [b] -> [a, b] | a::la, b::lb -> (a, b) :: (combine_twice la lb) | _ -> [] let rec combine_thrice la lb lc = match (la, lb, lc) with | [], [], [] -> [] | [a], [b], [c] -> [a, b, c] | a::la, b::lb, c::lc -> (a, b, c) :: (combine_thrice la lb lc) | _ -> []