【问题标题】:Ocaml: Sorting a list into equivalence classesOcaml:将列表排序为等价类
【发布时间】:2020-06-03 04:08:41
【问题描述】:

我最近开始学习 ocaml,但无法解决问题。

目标:

给定一个整数列表和一个函数,根据给定函数将整数排序为等价类,作为另一个列表中的列表。等价列表的顺序必须与原始列表中给出的顺序相同。

更新:我决定尝试让它在没有库功能的情况下工作。

到目前为止,这是我的代码。它编译但不运行。任何有关语法的帮助将不胜感激。

let buckets f lst =
  let rec helpfunction f lst newlist = 
     match lst with
      | [] ->newlist
      | h::t -> match newlist with
             | [] -> helpfunction f lst [h]@newlist
             | [a]::_ -> if f h a 
                  then helpfunction f t [a::h]@newlist
                  else helpfunction f t ([a]::[h]@mylist

重要提示:这是一个家庭作业问题,所以我不是在寻找为我粘贴的代码。我试图在我的家中通过它对整体思维过程和语法有所帮助。一旦我得到它的工作,我会努力提高它的效率

【问题讨论】:

  • 您尚未提出具体问题。您是否正在寻求帮助以编译您的代码(我看到一些错误)?或者你想知道你提出的方法是否可行?
  • 一点点A,一点点B。第一步是让我的代码工作,然后我会专注于效率

标签: recursion functional-programming ocaml equivalence-classes


【解决方案1】:

您正在尝试获取输入中的每个元素,然后将其插入到列表结果列表中的某个位置。让我提出一种不同的方法。

您从一个“输入列表”和一个空的“您构建的结果列表”开始。

如果输入为空,则您的结果是完整的,您将其返回。

否则将输入分成头部和尾部(模式匹配已经这样做了)。接下来将输入列表划分为与头等效的项目和不等效的项目。将第二个列表作为新输入进行递归,将(第一个列表 :: 结果)作为新结果进行递归。

【讨论】:

  • 注:可以使用let helper results = function [] -> results | (head::_) as input -> ....
  • 感谢您的回复。我正在尝试根据您的建议实施并进行更改。我有点卡住的部分是对列表进行分区。你认为嵌套匹配语句是最好的方法吗?\
  • 我想我现在已经掌握了逻辑,尽管我对高阶函数的语法有所了解。我在上面添加了我的新代码。
  • 通常我会说 List.partition。但是您可以自己实现它作为学习体验的辅助函数。
【解决方案2】:

好吧,让我们尝试在不实际执行的情况下解决任务:)

大致来说,算法如下:

  1. 从源列表中取出整数x

  2. 如果列表的目标列表(每个列表都包含相同等价类的整数)包含相应等价类的列表,请将x 添加到此列表中

  3. 否则,创建一个包含单个值 ([x]) 的新等价类列表并将其添加到目标列表中

  4. 对目标列表中的其他整数重复 1-3。

(1)、(3) 和 (4) 似乎很容易实现。

挑战在于如何实施 (2) 以及如何有效地实施:)

“目标列表包含...的列表”可以改写为“在目标列表中存在一个列表lst,例如...” - 这给了我们一个强烈的暗示,List.exists 可以以某种方式在这里使用。要测试的内容也或多或少很清楚:同一个等价类列表的每个成员在定义上都是等价的,所以我们可以只取头部并使用p 将其与x 进行比较。

问题是如何将整数添加到另一个列表中的列表中。列表是不可变的,所以我们不能把它放在那里……但是我们可以获取目标列表并进行转换,或者将其折叠到另一个列表中。我敢打赌你得到了提示:List.fold_left 是另一个谜题。

所以,总结这一切,我们可以得出以下“更精确”的算法

  1. 从空目标列表res开始

  2. 从源列表l中取一个整数x

  3. 使用List.exists检查res中是否有一个列表lst,比如它的头部hp x h = true

  4. 如果是,则使用List.fold_left 将当前的res 转换为新的lst 替换为x::lst 并且所有其他等价类列表都照原样复制

    李>
  5. 如果否,则引入新的等价类(将[x] 添加到res

  6. 对源列表中的下一个整数重复 2-5,直到它为空。

(几乎)字面上遵循该算法的实现相对简单。但这不会很有效,因为existsfold 将在同一个列表上迭代两次,执行相同的检查。通过一些调整,应该可以在一次运行中完成它,但是这个低效率的应该足以作为起点......

【讨论】:

  • 循环遍历类列表两次。最好一次性完成存在并折叠。检查类列表是否为空(为当前项目创建一个新类)。否则检查头类是否等同于当前项(添加并返回 new_class::tail)。否则在尾部递归。
  • 我的想法是首先从“愚蠢”和直接的解决方案开始,这种解决方案更容易用简单的语言逐步解释,无需代码。但我同意你的看法……
  • 感谢您的回复。我的源列表只是一个基本列表,而不是列表列表。您认为最好立即开始将列表排序为列表列表,其中每个内部列表仅包含一项?
  • @KonstantinStrukov 我想我现在掌握了逻辑。我在上面的新代码中的语法看起来正确吗?
  • “我的源列表只是一个基本列表,而不是列表列表”@LostinRecursion 肯定是。 int list list 将是目标列表的类型,而不是源列表。抱歉,如果我不清楚 - 我也是 OCaml 的新手,没有代码我很难解释解决方案 :)
猜你喜欢
  • 1970-01-01
  • 2017-03-27
  • 2014-12-05
  • 1970-01-01
  • 2011-11-29
  • 2021-02-12
  • 1970-01-01
  • 2015-01-01
  • 1970-01-01
相关资源
最近更新 更多