Design a new type rect for representing rectangles. Treat squares as a special case.

type rect =
  | Rectangle of int * int
  | Square of int
;;

Now write a function of type rect -> int to calculate the area of a given rect.

let area figure =
  match figure with
  | Rectangle (w, h) -> w * h
  | Square s -> s * s
;;

Write a function which rotates a rect such that it is at least as tall as it is wide.

let rotate r =
  match r with
  | Rectangle (w, h) ->
    if w > h then Rectangle (h, w) else r
  | _ -> r
;;

Use this function to write one which, given a rect list, returns another such list which has the smallest total width and whose members are sorted narrowest first.

(* this requires quite a lot of boilerplate code! *)
let rec take n xs =
  match n, xs with
  | 0, _ | _, [] -> []
  | n', x :: xs' -> x :: take (n' - 1) xs'
;;

let rec drop n xs =
  match n, xs with
  | _, [] -> []
  | 0, xs' -> xs'
  | n', x :: xs' -> drop (n' - 1) xs'
;;

(* i tried to write merge_sort from scratch again, yeesh *)
let rec merge cmp xs ys =
  match xs, ys with
  | [], l | l, [] -> l
  | x :: xs', y :: ys' ->
    if cmp x y
      then x :: merge cmp xs' (y :: ys')
      else y :: merge cmp (x :: xs') ys'
;;

let rec merge_sort cmp xs =
  match xs with
  | [] -> []
  | [x] -> [x]
  | xs' ->
    let pivot = (List.length xs) / 2 in
      let left = take pivot xs in
        let right = drop pivot xs in
          merge cmp (merge_sort cmp left) (merge_sort cmp right)
;;

let compare rect_a rect_b =
  let width r =
    match r with
    | Rectangle (w, _) -> w
    | Square s -> s
  in
    width rect_a < width rect_b
;;

let sort_rectangles rects =
  merge_sort compare (List.map rotate rects)
;;

Write take, drop, and map functions for the sequence type.

(* sequence type, for reference *)
type 'a sequence = Nil | Cons of 'a * 'a sequence;;

let rec take n seq =
  match n, seq with
  | 0, _ | _, Nil -> Nil
  | n', Cons (head, tail) -> Cons (head, take (n' - 1) tail)
;;

let rec drop n seq =
  match n, seq with
  | _, Nil -> Nil
  | 0, seq' -> seq'
  | n', Cons (head, tail) -> drop (n' - 1) tail
;;

let rec map f seq =
  match seq with
  | Nil -> Nil
  | Cons (head, tail) -> Cons (f head, map f tail)
;;

Extend the expr type and the evaluate function to allow raising a number to a power.

(* previous expr and evaluate, for reference *)
type expr =
  | Num of int
  | Add of expr * expr
  | Subtract of expr * expr
  | Multiply of expr * expr
  | Divide of expr * expr
  (* Added *)
  | Power of expr * expr
;;

let rec power x n =
  match n with
  | 0 -> 1
  | 1 -> x
  | _ -> x * power x (n - 1)
;;

let rec evaluate e = match e with
  | Num x -> x
  | Add (e, e') -> evaluate e + evaluate e'
  | Subtract (e, e') -> evaluate e - evaluate e'
  | Multiply (e, e') -> evaluate e * evaluate e'
  | Divide (e, e') -> evaluate e / evaluate e'
  (* Added *)
  | Power (e, e') -> power (evaluate e) (evaluate e')
;;

Use the option type to deal with the problem that Division_by_zero may be raised from the evaluate function.

let safe_evaluate e =
  try
    Some (evaluate e)
  with
    Division_by_zero -> None
;;

results matching ""

    No results matching ""