[back]

Allocating Memory

type mem_status =
  | Free
  | Occupied

type memory = (mem_status * int) list

You'll be working with a very simple model of (unlimited) memory. In this model, memory is represented as a list of pairs, each representing a chunk of memory. The first entry of the pair determines whether the chunk is Free or Occupied, and the second determines how many units of memory the chunk occupies. Furthermore, we require that memory has the following properties:

For example, the list:

[(Free, 3); (Occupied, 1); (Occupied, 3); (Free, 2); (Occupied, 1)]

represents the following layout.

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───
│ F │ F │ F │ O │ O │ O │ O │ F │ F │ O │ F │ F │ ...
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───
 0   1   2   3   4   5   6   7   8   9   10  11   ...

In this problem, you'll be implementing a simple allocator for this model.

type alloc_result =
  | Success of int * memory
  | Invalid_size

Implement the function

val allocate : int -> memory -> alloc_result

so that allocate size mem is an alloc_result according to the following allocation strategy:

It's possible to allocate a chunk of memory at position i of size size if the positions i through i + size - 1 are Free. After allocation, these positions become Occupied. In the above example, it should be possible to allocate a chunk of memory of size 2 at position 0, giving us the list:

[(Occupied, 2); (Free, 1); (Occupied, 1); (Occupied, 3); (Free, 2); (Occupied, 1)]

which represents the following layout.

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───
│ O │ O │ F │ O │ O │ O │ O │ F │ F │ O │ F │ F │ ...
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───
 0   1   2   3   4   5   6   7   8   9   10  11   ...

The leftmost place to allocate a chunk of memory of size 5 is at position 10, giving us the list:

[(Free, 3); (Occupied, 1); (Occupied, 3); (Free, 2); (Occupied, 1); (Occupied, 5)]

which represents the following layout.

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───
│ F │ F │ F │ O │ O │ O │ O │ F │ F │ O │ O │ O │ O │ O │ O │ F │ F │ ...
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───
 0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16   ...

Examples

let m0 = [(Free, 3); (Occupied, 1); (Occupied, 3); (Free, 2); (Occupied, 1)]

let _ = assert (allocate 0 m0 = Invalid_size)
let _ = assert (allocate (-1) m0 = Invalid_size)
let _ = assert (allocate 2 m0 =
                 Success (0, [(Occupied, 2); (Free, 1); (Occupied, 1);
                              (Occupied, 3); (Free, 2); (Occupied, 1)]))
let _ = assert (allocate 5 m0 =
                 Success (10, [(Free, 3); (Occupied, 1); (Occupied, 3);
                               (Free, 2); (Occupied, 1); (Occupied, 5)]))