递归函数停止处理条件分支

时间:2017-09-15 21:54:14

标签: recursion ocaml

我有一个函数can_obtain来证明字符串init是否可以使用以下条件转换为字符串target

  • 字符串inittarget只包含字母“X”和/或“Y”(如“XY”,“XXX”,“YYXY”,“Y”等)< / LI>
  • 字符串target超过init
  • 到达target的选项是
    • 将“X”连接到init
    • 反向并将“Y”连接到init

这是一个功能,删除了containsreverse之类的简单操作。

let can_obtain init target = 
  let final = 
    let rec reduce i text =
      if i >= String.length target then text
      else 
        let next = 
          let branchX = text ^ "X" in
          let branchY = (reverse text) ^ "Y" in
          if contains target branchX then branchX
          else if contains target branchY then branchY
          else text
        in 
          reduce (i+1) next
     in
       reduce (String.length init) init
   in
     final = target
;;

问题在于这些转换返回true,这是正确的

(* concat "X" only *)
(* "XY" -> "XYX" -> "XYXX" *)
can_obtain "XY" "XYXX";;

(* reverse and concat "Y" only *)
(* "XY" -> "YXY" -> "YXYY" -> "YXYYY" *)
can_obtain "XY" "YXYYY";;

(* reverse and concat "Y", then concat "X" lastly *)
(* "XY" -> "YXY" -> "YXYY" -> "YYXYY" -> "YYXYYX" *)
can_obtain "XY" "YYXYYX";;

但是,如果在过渡“X”的某个时刻连接,该函数将拒绝切换到反向分支并返回false

(* concat "X", then tries to reverse then concat "Y" *)
(* "XY" -> "XYX" -> "XYXY" *)
can_obtain "XY" "XYXY";;  (* false *)

我知道我在这里只缺少一小块,代码看起来也非常混乱。我真的很感激一些帮助。

2 个答案:

答案 0 :(得分:2)

can_obtain是一个递归函数 - 所以让我们先定义停止条件:

停止条件:

  • 如果n = i那么这是成功的
  • 如果长度为i>长度n然后失败

如果不符合停止条件,那么我们必须进一步尝试使用2假设:(init ^ "X")((reverse init) ^ "Y")

所以代码导致:

let rec can_obtain init target = 
  if init = target then
    true
  else if String.length init >= String.length target then
    false 
  else
    (can_obtain (init ^ "X") target) || (can_obtain ((reverse init) ^ "Y") target)

答案 1 :(得分:1)

只是查看代码,显而易见的问题是N可能包含branchX和branchY。在那种情况下(在我看来)你想要追求两种可能性,但你只追求第一种。

<强>更新

另一个观察是,如果N包含分支或其反转,您可能想要追求分支。您的其中一个操作会反转字符串,对于您所知道的,此操作可能会应用奇数次。