#+TITLE: Notes & Exercises: Grokking Algorithms #+AUTHOR: Joseph Ferano #+OPTIONS: ^:{} * Algorithms from the book ** Recursive sum *** OCaml #+begin_src ocaml let rec sum_rec = function | [] -> 0 | n::ns -> n + sum_rec ns;; sum_rec [2;3;4;2;1];; #+end_src #+RESULTS: : 12 #+begin_src ocaml let sum_rec_tail list = let rec f acc = function | [] -> 0 | n::ns -> sum_rec (acc + n) ns in f 0 list;; sum_rec [2;3;4;2;1];; #+end_src #+RESULTS: : 12 *** Python #+begin_src python :results output def sum_rec(arr): if not arr: return 0 else: return arr[0] + sum_rec(arr[1:]) print(sum_rec([1,2,3])) #+end_src #+RESULTS: : 6 ** Binary Search *** OCaml #+begin_src ocaml let binary_search items target = let rec f low high = match (high - low) / 2 + low with | mid when target = items.(mid) -> Some items.(mid) | mid when target < items.(mid) -> f low mid | mid when target > items.(mid) -> f mid high | _ -> None in f 0 (Array.length items);; binary_search [|1;2;3;4;5|] 3;; #+end_src ** Selection Sort Runtime O(n^{2}) *** Python #+begin_src python def selection_sort(arr): sorted_list = [] for i in range(len(arr)): max = arr[0] for count, value in enumerate(arr): if value > max: max = value sorted_list.append(max) arr.remove(max) return sorted_list selection_sort([2,1,5,3,4]) #+end_src *** OCaml Really reinventing the wheel on this one... #+begin_src ocaml let max_element = function | [] -> invalid_arg "empty list" | x::xs -> let rec f acc = function | [] -> acc | x::xs -> f (if x > acc then x else acc) xs in f x xs let remove item list = let rec f acc item = function | [] -> List.rev acc | x::xs -> if item = x then (List.rev acc) @ xs else f (x::acc) item xs in f [] item list let selection_sort list = let rec f acc = function | [] -> acc | xs -> let m = max xs in f (m::acc) (remove m xs) in f [] list #+end_src ** Quicksort *** Python #+begin_src python import random def quicksort(arr): if len(arr) < 2: return arr elif len(arr) == 2: if arr[0] > arr[1]: temp = arr[1] arr[1] = arr[0] arr[0] = temp return arr else: # Pick a random pivot index = random.randrange(0, len(arr)) pivot = arr.pop(index) left = [x for x in arr if x <= pivot] right = [x for x in arr if x > pivot] return quicksort(left) + [pivot] + quicksort(right) #+end_src