【问题标题】:SML: Look and Say FunctionSML:看和说功能
【发布时间】:2015-08-16 09:04:57
【问题描述】:

我在递归编写外观和说功能时遇到了麻烦。它应该获取一个整数列表并评估为一个“读起来像口语”的整数列表。例如,

look_and_say([1, 2, 2]) = "一二二" = [1, 1, 2, 2]

look_and_say([2, 2, 2]) = “三个二” = [3, 2]

在我的递归调用过程中,我很难弄清楚如何将元素添加到列表中(并跟踪该列表)。

这是我写的一个辅助函数,应该很有用:

fun helper(current : int, count : int, remainingList : int list) : int list =
    if (current = hd remainingList) then
        helper(current, count + 1, tl remainingList)
    else
        (* add count number of current to list *)
        helper(hd remainingList, 1, tl remainingList);

这是我的主要功能的粗略轮廓:

fun look_and_say(x::y : int list) : int list =
    if x = nil then
    (* print *)
    else
        helper(x, 1, y);

想法?

【问题讨论】:

  • 输入列表是否按照您的两个示例进行排序?如果不是 - 您可能希望先将其作为 sort 运行。
  • @JohnColeman 没有像这些示例中那样排序,但我希望我的辅助函数能够解决这个问题(即不需要对其进行排序即可正常工作)
  • 但如果它被排序,那肯定是一个非常简单的问题
  • @JohnColeman mm,不知道为什么
  • 没关系——我误解并认为目标是将 1 组合在一起,2 组合在一起等等,并计算每个不同数字之前出现的次数

标签: functional-programming sml


【解决方案1】:

您的想法似乎是正确的,尽管您的助手似乎永远不会终止。这是一种在没有帮助器的情况下实现它的方法。

fun look_and_say [] = []
  | look_and_say (x::xs) =
      case look_and_say xs of
        [] => [1,x]
      | a::b::L => if x=b then (a+1)::b::L 
                   else 1::x::a::b::L

这是一种使用助手实现它的方法。

fun helper(current, count, remainingList) =
  if remainingList = [] then
    [count, current]
  else if current = hd remainingList then
    helper(current, count + 1, tl remainingList)
  else count::current::look_and_say(remainingList)
and look_and_say [] = []
  | look_and_say (x::y) = helper(x, 1, y)

【讨论】:

  • 第二个实际上对我来说更有意义,但为什么 case 语句“case look_and_say xs of ...”...应该是“case xs of ...”?鉴于 look_and_say 使用帮助器但反之则不然,您还需要连接两者的“和”吗?
  • 没错,只是解决问题的方式不同而已。在第二种解决方案中,我们一个一个地检查每个列表元素,如果我们看到匹配的连续元素,则增加一个计数器。在第一个解决方案中,我们检查列表尾部的look_and_say,如果结果至少有两个元素,那么我们知道第一个元素是第二个元素的计数器。这样我们就不需要助手来跟踪计数器了。