如何解决这个 Ocaml 字典问题?

Posted

技术标签:

【中文标题】如何解决这个 Ocaml 字典问题?【英文标题】:How can I solve this Ocaml dictionary problem? 【发布时间】:2020-11-08 13:59:56 【问题描述】:

我必须编写一个以字典和字符为参数的函数。字典是字符串到字符串的,你应该把它看作一个函数。例如 f("a")="b" in ("a", "b")。该函数返回一个定义了 f^number(character) 的最大数字,如果 f(character) 在无穷大处循环,则返回一个异常。

所以如果我有例如这本字典 [("a", "b");("b", "c");("d", "e");("e", "f" );("f", "e")] 我的函数用这本字典上诉,字符“a”将给出结果 2(a 进入 b,b 进入 c 并停止);对于“x”,它将给出 0,因为没有这样的密钥;对于“b”,结果将为 1(b 进入 c 并停止);对于“d”,它将引发异常(d 进入 e,e 进入 f,f 进入 e 并在 e 中返回,因此无限循环); 'e' 或 'f' 的相同例外

模块 MS = Map.Make(String);; 让 d = MS.add "a" "b" (MS.add "b" "c" (MS.add "d" "e" (MS.add "e" "f" (MS.add "f" " e" MS.empty))));; 让 f d c =

我刚刚创建了字典,因为我不知道如何实现这个问题,但我认为我需要 MS.Fold 函数来浏览字典。

【问题讨论】:

【参考方案1】:

折叠的目的是“访问”结构的所有元素,同时积累一些期望的结果。您的目标不是访问字典中的所有元素(秘密地是一个图表)。所以弃牌可能不是你想要的。

我想说您的主要问题是检测周期,以便您可以引发异常。为此,您需要跟踪您去过的地方。然后当你第二次来到某个地方时引发异常。

否则,我会说这是一个标准的图遍历问题。您可以使用访问节点(即在字典中查找字符串)的递归函数来解决它,直到它得到解决。解析是一个不在字典中的字符串,或者是对已经访问过的字符串的访问。

更新

好的,我将编写一些代码来说明如何在字典中移动。此函数返回一个字符串,它是它遇到的前 10 个字符串的串联。如果它在 10 点之前到达死胡同,它会返回到目前为止所看到的内容。它使用您的模块MS

 let what_i_saw dict str =
     let rec look sofar n s =
         if n <= 0 then
             sofar
         else
             match MS.find_opt s dict with
             | None -> sofar
             | Some s2 -> look (sofar ^ s2) (n - 1) s2
     in
     look str 9 str

这是调用函数时的样子:

# what_i_saw d "d";;
- : MS.key = "defefefefe"
# what_i_saw d "a";;
- : MS.key = "abc"

顺便说一句,你说你的函数需要一个字符,但你的字典有字符串键。 OCaml 中的字符串和字符不是一回事。在这个例子中,我到处都使用字符串。

【讨论】:

是的,但这就像我希望看到的那样;一段真正有效的代码(也许不是全部,只是一个小想法),因为从理论上讲,我明白我必须做什么,但我们没有学习图表或树,所以我只能使用字典库、集合或也许列表。(ty) 对于它的价值,如果你能理解这个作业,那么我会说你对图表有足够的了解来解决它。即,您会看到从一个单词到下一个单词的含义以及找到一个循环的含义。 我试图针对我的问题更新 yr 函数,但它一直失败。我很难理解你所有的代码,尤其是匹配部分,因为我是 ocaml 的新手。我尝试在 in 之后添加一些条件以在第一个周期停止。如果你能告诉我如何解决这个问题,我会非常感激。 恕我直言,如果你想完成这个任务,你需要对 OCaml 有足够的了解才能理解我的代码。如果你有具体的问题,你可以问他们。如果您显示失败的代码,人们可以帮助解决问题。但是要求 SO 为您编写代码通常是行不通的(因为它不应该)。 感谢您的指点。我设法解决了与您的方法略有不同的问题。这是我编写的并且有效的函数:module S = Set.Make(String);; let depth dict s = let rec depth1 s dict num m=if(S.mem s m) then failwith "loop" else if (MS.mem s dict) then depth1 (MS.find s dict) dict (num+1) ( S.add s m) else num in depth1 s dict 0 S.empty;;

以上是关于如何解决这个 Ocaml 字典问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何在用户输入时中断 ocaml 程序

如何在 OCaml 中删除字符串的所有字符

如何从 OCaml 中的字符串中去除空格?

这个 ocaml 递归函数是如何工作的?

RuntimeError:字典迭代过程中改变大小 - 如何解决?

在 ocaml 中定义树 + 指向其子树的指针