1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
open Core
type t = Tile.t list [@@deriving yojson { exn = true }]
let empty = []
let is_empty = List.is_empty
let length = List.length
let ( @ ) rack tiles = rack @ tiles
let nth_exn = List.nth_exn
let exists = List.exists
let of_tile_list tiles = tiles
let rec remove_once eq item (from : t) =
match from with
| [] -> None
| x :: xs when eq item x -> Some xs
| x :: xs -> (
match remove_once eq item xs with
| None -> None
| Some rest -> Some (x :: rest))
let rec remove_all from items =
match items with
| [] -> Some from
| t :: rest -> (
match remove_once Tile.equal t from with
| None -> None
| Some smaller -> remove_all smaller rest)
let get_total_points rack =
rack |> List.fold ~init:0 ~f:(fun sum tile -> sum + Tile.get_points tile)
let has_required_tiles rack placed =
let rec consume rack (tiles : Placed_tile.t list) =
match tiles with
| [] -> Some rack
| { tile = needed; _ } :: rest ->
let rec take acc = function
| [] -> None
| t :: ts when Tile.equal_with_expansion t needed ->
consume (List.rev acc @ ts) rest
| t :: ts -> take (t :: acc) ts
in
take [] rack
in
match consume rack placed with None -> false | Some _ -> true