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

Recursion 递归函数停止处理条件分支,recursion,ocaml,Recursion,Ocaml,我有一个函数可以获得来证明字符串init是否可以在以下条件下转换为字符串target: 字符串init和target仅由字母“X”和/或“Y”组成(如“XY”、“XXX”、“YYXY”、“Y”等) 字符串target比init 到达目标的选项有 将“X”连接到init或 将“Y”反转并连接到init 这里是函数,为了简洁起见,删除了一些琐碎的操作,如包含和反向 let can_obtain init target = let final = let rec reduce

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

  • 字符串
    init
    target
    仅由字母“X”和/或“Y”组成(如“XY”、“XXX”、“YYXY”、“Y”等)
  • 字符串
    target
    init
  • 到达
    目标的选项有
    
    • 将“X”连接到
      init
    • 将“Y”反转并连接到
      init
这里是函数,为了简洁起见,删除了一些琐碎的操作,如
包含
反向

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 *)

我知道我只遗漏了一小部分,代码看起来也很混乱。我非常感谢您的帮助。

看看您的代码,明显的问题是N可能同时包含branchX和branchY。在这种情况下(在我看来),你想追求两种可能性,但你只追求第一种

更新


另一个观察结果是,如果N包含分支或其反向,则您可能希望跟踪该分支。您的一个操作会反转字符串,据您所知,此操作可能会应用奇数次。

仅查看您的代码,明显的问题是N可能同时包含branchX和branchY。在这种情况下(在我看来),你想追求两种可能性,但你只追求第一种

更新


另一个观察结果是,如果N包含分支或其反向,则您可能希望跟踪该分支。您的一个操作会反转字符串,并且据您所知,此操作可能会应用奇数次。

可以获得
是一个递归函数-因此,让我们首先定义停止条件:

停止条件:

  • 如果n=i,则这是一个成功
  • 如果长度i>长度n,则失败
如果不满足停止条件,那么我们必须进一步尝试两种假设:
(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)

can_获得
是一个递归函数-因此,让我们首先定义停止条件:

停止条件:

  • 如果n=i,则这是一个成功
  • 如果长度i>长度n,则失败
如果不满足停止条件,那么我们必须进一步尝试两种假设:
(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)

您的代码不是有效的OCaml程序。我在哪里出错的@Camlspottera参数的最小大写字母…@PierreG。我不认为这是无效的,也许只是丑陋而已。但仍需编辑。以大写字母开头仅限于构造函数:类型t1=Int of(Int,string);;Int是一个构造函数。请参阅。您的代码不是有效的OCaml程序。我在哪里出错的@Camlspottera参数的最小大写字母…@PierreG。我不认为这是无效的,也许只是丑陋而已。但仍需编辑。以大写字母开头仅限于构造函数:类型t1=Int of(Int,string);;Int是一个构造函数。看,蛮力的方法是使用回溯。当无法进一步进展时,返回故障指示。当你看到追求branchX可能性的失败时,你想看看branchY可能性是否有效。暴力的方法是使用回溯。当无法进一步进展时,返回故障指示。当你看到追求branchX可能性的失败时,你想看看branchY可能性是否有效。你的意思是使用
可以获得
?另外,如果i>=String.length目标,则文本已经是停止递归的基本情况,是吗?如果i>=String.length。。。是停止递归的基础:是的,正确。您的意思是使用
可以获得
?另外,如果i>=String.length目标,则文本已经是停止递归的基本情况,是吗?如果i>=String.length。。。是停止递归的基础:是,正确。