在SML中查找int列表的模式以及在没有库函数的情况下它发生的位置

问题描述 投票:0回答:1

我正在尝试找到最常出现的模式或值。我想要一个像这样的功能:

mode:' 'a list -> (''a * int) list

它返回模式及其发生的位置,除非有一个平局然后返回所有出现的事情,如下所示:

mode([1,1,2,3,5,8]) ===> [(1,2)]
mode([1,3,5,2,3,5]) ===> [(3,2),(5,2)]
mode([true,false,true,true]) ====>[(true,3)]

我试图在SML中没有库函数的情况下这样做。

到目前为止我得到了:

fun mode(L)=
if null L then nil
else if hd L= hd (tl L) then 1+mode(hd(tl L))
else mode(tl L);

我知道这不对,我想我很好奇你们如何保持模式发生的位置和模式的索引,并将它们作为元组返回列表中。

recursion sml smlnj ml statistical-mode
1个回答
0
投票

你试图通过几个简单的练习来解决很多部分的练习。根据您目前的进展情况,您是否考虑过解决一些非常类似的练习,以达到最终目标?在解决编程问题时,这通常是一个很好的建议:将当前问题减少到更简单的问题并解决问题。

我先尝试解决这个问题

  • 在列表的元素上构建histogram : ''a list -> (''a * int) listfun histogram [] = ... | histogram (x::xs) = ... 通过将每个x及其count插入直方图来完成此操作。 fun insert (x, []) = ... | insert (x, (y, count) :: hist) = ... 并编写一些可以偶尔执行的测试。
  • 找到列表的mode : ''a list -> ''afun mode xs = ... (histogram xs) 通过查找具有最大计数的直方图中的元素来执行此操作: fun findMax [] = ... (* what if the list/histogram is empty? *) | findMax [(x, count)] = ... | findMax ((x, count) :: (y, count) :: hist) = ...

and eventually try and solve this problem

  • 当你很好地掌握递归表示和导航常规直方图时,你可以创建一个带注释的histogram : (''a * int * int list) list,它不仅包含每个元素的频率,还包含它们在输入列表中的位置: fun histogram_helper ([], _) = ... | histogram_helper (x::xs, i) = ... histogram_helper (xs, i+1) ... 通过插入每个x及其count并将i与之前找到的位置is一起插入直方图来执行此操作: fun insert (x, i, []) = ... | insert (x, i, (y, count, is) :: hist) = ...
  • 找到列表的(可能是多个)mode : ''a list -> (''a * int list) listfun mode xs = ... (histogram xs) 通过查找具有最大计数的直方图中的(可能是多个)元素来执行此操作: fun findMax ([], countMax, tmpModes) = ... | findMax ((x, count, is) :: hist, countMax, tmpModes) = ... countMax : int是在tmpModes : (''a * int * int list) list重复的频率。这里countMaxtmpModes正在累积结果参数。这样做是通过确定(x, count, is)是否应该被抛弃以支持所有tmpModes,或者它应该被添加到tmpModes,或者应该选择有利于所有tmpNodes 我很好奇你们如何保持模式发生的位置和模式的索引,并将它们作为元组返回列表中。 是的,这不是微不足道的。使用我建议的划分为子问题,回答这取决于我们是在histogram函数还是findMax函数: 在histogram中,您可以将索引存储为包含元素和频率的元组的一部分。在findMax,由于你可能收集多个结果,你需要跟踪哪个频率最高(countMax)和临时选择的模式(tmpModes);在稍后的递归电话中被替换或添加。 所以回答你的问题:在一个累积的参数。

以及对您的代码段的一些反馈

fun mode(L)=
if null L then nil
else if hd L= hd (tl L) then 1+mode(hd(tl L))
else mode(tl L);

使用模式匹配而不是nullhdtl

fun count_4s [] = 0
  | count_4s (x::xs) = (if x = 4 then 1 else 0) + count_4s xs

fun count_ns ([],    _) = 0
  | count_ns (x::xs, n) = (if x = n then 1 else 0) + count_ns (xs, n)

fun count_12 ([], ones, twos) = (ones, twos)
  | count_12 (x::xs, ones, twos) =
      if x = 1 then count_12 (xs, ones+1, twos) else
      if x = 2 then count_12 (xs, ones, twos+1) else
      count_12 (xs, ones, twos)

fun count_abc ([], result) = result
  | count_abc (x::xs, ((a, ca), (b, cb), (c, cc))) =
      count_abc (xs, if x = a then ((a, ca+1), (b, cb), (c, cc)) else
                     if x = b then ((a, ca), (b, cb+1), (c, cc)) else
                     if x = c then ((a, ca), (b, cb), (c, cc+1)) else
                     ((a, ca), (b, cb), (c, cc)))

构建直方图是对此的扩展,而不是像4这样的固定值,或者像onestwos这样的固定值,你有一个完整的列表,你必须动态地寻找你的那个得到,x,并确定是否需要将其添加到直方图或在直方图中递增。

最好的方法是在辅助函数中执行此操作,例如,如果count_abc是使用辅助函数创建的,

fun insert_abc (x, ((a, ca), (b, cb), (c, cc))) =
    if x = a then ((a, ca+1), (b, cb), (c, cc)) else
    if x = b then ((a, ca), (b, cb+1), (c, cc)) else
    if x = c then ((a, ca), (b, cb), (c, cc+1)) else
    ((a, ca), (b, cb), (c, cc)))

fun count_abc ([], result) = result
  | count_abc (x::xs, result) =
      count_abc (xs, insert (x, result))

只代替直方图表示

(''a * int) * (''a * int) * (''a * int)

你要

(''a * int) list

insert应该是递归的,而不是insert_abc是如何重复的。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.