SHOW:
|
|
- or go back to the newest paste.
1 | - | type pure = |
1 | + | module Op = struct |
2 | - | | Binary of expression * Ops.t * expression |
2 | + | type t = |
3 | - | | Atom of int |
3 | + | | Plus |
4 | - | and bracketed = pure |
4 | + | | Minus |
5 | - | and expression = |
5 | + | | Mult |
6 | - | | Bracketed of bracketed |
6 | + | | Div |
7 | - | | Pure of pure |
7 | + | [@@deriving enumerate] |
8 | end | |
9 | ;; | |
10 | - | type pure = Binary of expression * Ops.t * expression | Atom of int |
10 | + | |
11 | - | and bracketed = pure |
11 | + | type node = |
12 | - | and expression = Bracketed of bracketed | Pure of pure |
12 | + | { left : expression |
13 | ; right : expression | |
14 | - | let rec enum' i = |
14 | + | ; op : Op.t |
15 | - | if i = 0 then [(Atom 0)] |
15 | + | ; is_bracketed : bool |
16 | - | else ( |
16 | + | } |
17 | - | let children = enum (i - 1) in |
17 | + | and expression = |
18 | - | List.cartesian_product children children |> List.map ~f:(fun (child1, child2) -> |
18 | + | | Node of node |
19 | - | List.concat_map Ops.all ~f:(fun op -> |
19 | + | | Leaf of int |
20 | - | [(Binary (child1, op, child2))] |
20 | + | |
21 | - | ))) |> List.concat |
21 | + | |
22 | - | and enum i = let children = enum' i in |
22 | + | (* enum functions to generate all possible expression of depth i *) |
23 | - | [List.map children ~f:(fun child -> Pure(child)); |
23 | + | let rec enum i = |
24 | - | List.map children ~f:(fun child -> Bracketed(child)) |
24 | + | if i = 0 then [(Leaf 0)] |
25 | - | ] |> List.concat |
25 | + | else ( |
26 | let possible_children = enum (i - 1) in | |
27 | - | let ops_to_str = function |
27 | + | List.bind possible_children ~f:(fun left -> |
28 | - | | Ops.Plus -> "+" |
28 | + | List.bind possible_children ~f:(fun right -> |
29 | - | | Minus -> "-" |
29 | + | List.bind Op.all ~f:(fun op -> |
30 | - | | Mult -> "*" |
30 | + | List.bind Bool.all ~f:(fun is_bracketed -> |
31 | - | | Div -> "/" |
31 | + | [Node { left; right; op; is_bracketed }]))))) |
32 | ;; | |
33 | - | let rec pure_to_str = function |
33 | + | |
34 | - | | Binary (e1, op, e2) -> (expr_to_str e1) ^ (ops_to_str op) ^ (expr_to_str e2) |
34 | + | (* to_str functions *) |
35 | - | | Atom x -> Int.to_string x |
35 | + | let op_to_str = function |
36 | - | and bracket_to_str e = "(" ^ (pure_to_str e) ^ ")" |
36 | + | | Op.Plus -> "+" |
37 | - | and expr_to_str = function |
37 | + | | Minus -> "-" |
38 | - | | Bracketed x-> bracket_to_str x |
38 | + | | Mult -> "*" |
39 | - | | Pure x -> pure_to_str x |
39 | + | | Div -> "/" |
40 | ;; | |
41 | - | enum 2 |> List.map ~f:expr_to_str;; |
41 | + | |
42 | let rec expression_to_str = function | |
43 | - | ["0+0+0+0"; "0+0-0+0"; "0+0*0+0"; "0+0/0+0"; "0+0+0-0"; "0+0-0-0"; "0+0*0-0"; |
43 | + | | Leaf x -> Int.to_string x |
44 | - | "0+0/0-0"; "0+0+0*0"; "0+0-0*0"; "0+0*0*0"; "0+0/0*0"; "0+0+0/0"; "0+0-0/0"; |
44 | + | | Node { left; right; op; is_bracketed } -> |
45 | - | "0+0*0/0"; "0+0/0/0"; "0+0+0+(0)"; "0+0-0+(0)"; "0+0*0+(0)"; "0+0/0+(0)"; ... |
45 | + | let inside = (expression_to_str left) ^ (op_to_str op) ^ (expression_to_str right) in |
46 | if is_bracketed then | |
47 | "(" ^ inside ^ ")" | |
48 | else inside | |
49 | ;; | |
50 | ||
51 | (* finally running *) | |
52 | utop # enum 2 |> List.map ~f:expression_to_str;; | |
53 | - : string list = | |
54 | ["0+0+0+0"; "(0+0+0+0)"; "0+0-0+0"; "(0+0-0+0)"; "0+0*0+0"; "(0+0*0+0)"; | |
55 | "0+0/0+0"; "(0+0/0+0)"; "0+0+(0+0)"; "(0+0+(0+0))"; "0+0-(0+0)"; | |
56 | "(0+0-(0+0))"; "0+0*(0+0)"; "(0+0*(0+0))"; "0+0/(0+0)"; "(0+0/(0+0))"; | |
57 | "0+0+0-0"; "(0+0+0-0)"; "0+0-0-0"; "(0+0-0-0)"; "0+0*0-0"; "(0+0*0-0)"; | |
58 | "0+0/0-0"; "(0+0/0-0)"; "0+0+(0-0)"; "(0+0+(0-0))"; "0+0-(0-0)"; | |
59 | "(0+0-(0-0))"; "0+0*(0-0)"; "(0+0*(0-0))"; "0+0/(0-0)"; "(0+0/(0-0))"; | |
60 | "0+0+0*0"; "(0+0+0*0)"; "0+0-0*0"; "(0+0-0*0)"; "0+0*0*0"; "(0+0*0*0)"; | |
61 | "0+0/0*0"; "(0+0/0*0)"; "0+0+(0*0)"; "(0+0+(0*0))"; "0+0-(0*0)"; ... |