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
仅由字母“X”和/或“Y”组成(如“XY”、“XXX”、“YYXY”、“Y”等)target
- 字符串
比target
init
- 到达
目标的选项有
- 将“X”连接到
或init
- 将“Y”反转并连接到
init
- 将“X”连接到
包含和反向
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。。。是停止递归的基础:是,正确。