我写了一个解决方案:
let rec replace_subtree' start_index tree replacement_index replacement
: (int * 'a tree) =
(* Returns (max_index, new_tree), where max_index = start_index + number of
nodes in new_tree - 1, and where the replacement is counted as a single
node. *)
if start_index = replacement_index then
(start_index, replacement)
else
match tree with
| Function (name, args) ->
(* (start_index + 1) to account for this function node itself. *)
let (max_index, new_args) = replace_subtree_args (start_index + 1)
args
replacement_index
replacement in
(max_index, Function (name, new_args))
| Terminal _ ->
(start_index, tree)
and replace_subtree_args arg_index args replacement_index replacement
: (int * 'a tree list) =
(* `arg_index` is the index of the first item in `args` (note that `args`
could be empty, however).
Returns (max_index, replaced_args), where max_index = arg_index +
number of nodes in all transformed args - 1, and where the replacement is
counted as a single node. *)
let rec f arg_index args acc =
match args with
| [] -> (arg_index - 1, List.rev acc)
| arg::rest_args ->
let (max_index, arg_result) = replace_subtree' arg_index
arg
replacement_index
replacement in
f (max_index + 1) rest_args (arg_result::acc)
in
f arg_index args []
let replace_subtree = replace_subtree' 0
示例用法:
let string_of_terminal = function
| Int x -> string_of_int x
| Bool b -> string_of_bool b
let rec string_of_tree = function
| Function (name, args) ->
"(" ^
String.concat " " (name::(List.map string_of_tree args)) ^
")"
| Terminal x -> string_of_terminal x
let () =
List.iter (fun n ->
let (max_index, new_tree) = replace_subtree t1 n t2 in
print_string ("Index " ^ (string_of_int n) ^ ": ");
print_endline (string_of_tree new_tree))
(List.init 8 Fun.id)
结果:
Index 0: (- 4 2)
Index 1: (+ (- 4 2) (sqrt 3))
Index 2: (+ (* (- 4 2) 6) (sqrt 3))
Index 3: (+ (* 5 (- 4 2)) (sqrt 3))
Index 4: (+ (* 5 6) (- 4 2)) ; <- Here.
Index 5: (+ (* 5 6) (sqrt (- 4 2)))
Index 6: (+ (* 5 6) (sqrt 3))
Index 7: (+ (* 5 6) (sqrt 3))
更好的解决方案是最受欢迎的。