#+TITLE: 99 Ocaml Problems #+Author: Joseph Ferano https://ocaml.org/problems *** #1 Tail of a list Write a function ~last : 'a list -> 'a option~ that returns the last element of a list #+begin_src ocaml # last ["a" ; "b" ; "c" ; "d"];; - : string option = Some "d" # last [];; - : 'a option = None #+end_src **** Solution #+begin_src ocaml let rec last = function | [] -> None | [x] -> Some x | _::xs -> last xs #+end_src *** #2 Last two elements of a list Find the last but one (last and penultimate) elements of a list. #+begin_src ocaml # last_two ["a"; "b"; "c"; "d"];; - : (string * string) option = Some ("c", "d") # last_two ["a"];; - : (string * string) option = None #+end_src **** Solution #+begin_src ocaml let rec last_two = function | [] | [_] -> None | [x;y] -> Some (x,y) | _::xs -> last_two xs #+end_src *** #3 N'th element of a list Find the N'th element of a list. REMARK: OCaml has List.nth which numbers elements from 0 and raises an exception if the index is out of bounds. #+begin_src ocaml # List.nth ["a"; "b"; "c"; "d"; "e"] 2;; - : string = "c" # List.nth ["a"] 2;; Exception: Failure "nth". #+end_src **** Solution #+begin_src ocaml let rec nth index = function | [] -> failwith "nth" | x::xs -> if index = 0 then x else nth (index - 1) xs #+end_src *** #4 Find the number of elements of a list. OCaml standard library has List.length but we ask that you reimplement it. Bonus for a tail recursive solution. #+begin_src ocaml # length ["a"; "b"; "c"];; - : int = 3 # length [];; - : int = 0 #+end_src **** Solution #+begin_src ocaml let length list = let rec length_rec acc = function | [] -> acc | _::xs -> length_rec (acc + 1) xs in length_rec 0 list #+end_src *** #5 Reverse a list. OCaml standard library has List.rev but we ask that you reimplement it. #+begin_src ocaml # rev ["a"; "b"; "c"];; - : string list = ["c"; "b"; "a"] #+end_src **** Solution #+begin_src ocaml let rev (list: int list) = let rec rev acc = function | [] -> acc | x::xs -> rev (x::acc) xs in rev [] list #+end_src *** #6 Palindrome Find out whether a list is a palindrome. HINT: a palindrome is its own reverse. #+begin_src ocaml # is_palindrome ["x"; "a"; "m"; "a"; "x"];; - : bool = true # not (is_palindrome ["a"; "b"]);; - : bool = true #+end_src **** Solution #+begin_src ocaml let is_palindrome list = list = List.rev list #+end_src *** #7 Flatten a list Flatten a nested list structure. #+begin_src ocaml type 'a node = | One of 'a | Many of 'a node list # flatten [One "a"; Many [One "b"; Many [One "c" ;One "d"]; One "e"]];; - : string list = ["a"; "b"; "c"; "d"; "e"] #+end_src **** Solution #+begin_src ocaml let flatten nodes = let rec f = function | One x -> [x] | Many xs -> List.concat_map f xs in nodes |> List.concat_map f (* Or without List.concat_map *) let flatten2 nodes = let rec f acc = function | [] -> acc | One n::ns -> f (n::acc) ns | Many ns::rest -> f (f acc ns) rest in f [] nodes |> List.rev #+end_src