-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patha9.ml
More file actions
105 lines (88 loc) · 2.8 KB
/
a9.ml
File metadata and controls
105 lines (88 loc) · 2.8 KB
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
(* group node: {, , , , , ,} *)
(* garbage : <....> *)
(* garbage character cancel: !x *)
(* Task: Transform Expression -> Tree structure *)
type tree =
| Group of tree list
| Garbage of string;;
exception ParseError of string;;
(* Instructions *)
(* "<>", empty garbage. *)
(* "<random characters>", garbage containing random characters. *)
(* "<<<<>", because the extra < are ignored. *)
(* "<{!>}>", because the first > is canceled. *)
(* "<!!>", because the second ! is canceled *)
(* "<!!!>>", because the second ! and the first > are canceled. *)
(* Pseudo-Code *)
(* rec parseTree seq parent *)
(* match head seq with *)
(* } -> return parent *)
(* { -> return TreeNode(parseTree(tail seq, this)) *)
(* , -> return TreeNode(this.children :: parseTree(tail seq, this)) *)
(* < -> return parseGarbage(tail seq, Garbage "") *)
(* rec parseJunk seq garbage *)
(* match head seq with *)
(* ! -> parseJunk(tail tail seq, garbage) *)
(* > -> garbage *)
(* x -> parseJunk(tail seq, garbage::x) *)
(*let explode s = String.to_list s |> List.map ~f:Char.to_string;;*)
let cl2s cl = String.concat "" (List.map (Printf.sprintf "%c") cl);;
let explode s =
let rec exp i l =
if i < 0 then l else exp (i - 1) (s.[i] :: l) in
exp (String.length s - 1) [];;
let rec parseGarbage seq garbage = match seq with
| '!' :: _ :: t -> parseGarbage t garbage
| '>' :: _ -> garbage
| x :: t -> parseGarbage t (garbage @ [x])
| [] -> raise (ParseError "garbage not terminating");;
let parseTree seq =
let rec aux seq parent = match (seq, parent) with
| ( [] , p ) -> p
| ( '}'::t , Group p ) -> print_endline "}";Group (p @ [aux t parent])
| ( '{'::t , _ ) -> let this = Group [] in Group [aux t this]
| ( ','::t , Group p ) -> print_endline "komma";parent
| ( '<'::t, _ ) -> Garbage (cl2s (parseGarbage t []))
| ( _ :: _, _ ) -> raise (ParseError "tree parse error: invalid token") in
let Group result = aux seq (Group []) in
List.hd result;;
#trace parseTree
let rec traverseTree tree leafHandler nodeHandler = match tree with
| Group children ->
List.iter
(fun subTree -> traverseTree subTree leafHandler nodeHandler)
children
| Garbage leaf -> leafHandler leaf;;
let tests1 = [
"<>";
"<random characters>";
"<<<<>";
"<{!>}>";
"<!!>";
"<!!!>>";
];;
let tests2 = [
"{}";
"{{{}}}";
"{{},{}}";
"{{{},{},{{}}}}";
"{<a>,<a>,<a>,<a>}";
"{{<ab>},{<ab>},{<ab>},{<ab>}}";
"{{<!!>},{<!!>},{<!!>},{<!!>}}";
"{{<a!>},{<a!>},{<a!>},{<ab>}}";
];;
let test3 = [
"{{},{}}";
];;
let countGroups tree =
let counter = ref 0 in
traverseTree
tree
(fun garbage -> print_endline garbage)
(fun node -> counter := !counter + 1);
!counter;;
test3 |> List.iter (
fun test ->
test |> explode |> parseTree |> countGroups |>
Printf.printf "count : %d\n"
);;