let cache = ref []
let cap = 3

let get k =
  let rec find = function
    | [] -> None
    | (k', v) :: _ when k' = k -> Some v
    | _ :: rest -> find rest
  in
  match find !cache with
  | None -> -1
  | Some v ->
    let rec remove = function
      | [] -> []
      | (k', _) :: rest when k' = k -> rest
      | h :: rest -> h :: remove rest
    in
    cache := (k, v) :: remove !cache;
    v

let put k v =
  let rec remove = function
    | [] -> []
    | (k', _) :: rest when k' = k -> rest
    | h :: rest -> h :: remove rest
  in
  let cleaned = remove !cache in
  let trimmed =
    if List.length cleaned >= cap then
      let rec take n lst = match n, lst with
        | 0, _ -> []
        | _, [] -> []
        | _, h :: r -> h :: take (n - 1) r
      in
      take (cap - 1) cleaned
    else cleaned
  in
  cache := (k, v) :: trimmed

;;

put 1 100;
put 2 200;
put 3 300;
let a = get 1 in
put 4 400;
let b = get 2 in
let c = get 3 in
let d = get 1 in
a + b + c + d
