Haskell-尽早结束递归调用的一部分

时间:2018-07-31 00:43:19

标签: haskell

我正在尝试编写一个函数,该函数返回可以从字符串中绘制的动物的可能列表(无重复)

即给予

agent.parameters

应该给予

time.original

我希望输出只是每种情况下可从字符串中提取的最大动物数:

到目前为止,我的代码是:

dict=["dog","cat","bat","cock","cow","pig","fox",
      "ant","bird","lion","wolf","deer","bear","frog",
      "hen","mole","duck","goat"]

但这给出了:

λ= fnd dict "gtcoaode"
[["dog","cat"],["goat"]]

处理重案的最佳方法是什么

1 个答案:

答案 0 :(得分:0)

一种方法是将找到的每个元素插入到Data.List.Ordered或集合中,而不是将其附加到列表的末尾。这样可以保证唯一性。您也可以将要生成的集合作为累积参数传递,并使函数本身为尾递归或折叠。

更新

由于听起来您想自己解决这个特定问题,所以这是一个人为问题的解决方案,效率不是很高:给定一个字符串,对每对连续字母进行排序,没有重复。

main :: IO ()
main = (print . myNub . digraphs) "banana"

insertSet :: Ord a => a -> [a] -> [a]
{- Inserts an element into a set, represented as a sorted list in ascending
 - order.  If an element in the set is already equal to x, x replaces the
 - first such element.
 -}
insertSet x [] = [x]
insertSet x (y:ys) | x == y    = x:ys
                   | x < y     = x:y:ys
                   | otherwise = y:(insertSet x ys)

myNub :: Ord a => [a] -> [a]
{- A naïve insertion sort of the input list that removes duplicates (and equiv-
 - alents).
 -}
myNub xs = go [] xs where
  go acc [] = acc
  go acc (y:ys) = go (insertSet y acc) ys

digraphs :: String -> [String]
{- Returns the list of all consecutive pairs of letters in the string.
 -}
digraphs [] = []
digraphs [_] = []
digraphs (x1:x2:xs) = [x1,x2]:(digraphs (x2:xs))

您可以执行一些基本的优化操作:以O(n log n)时间对列表进行排序,然后以O(n)时间对列表进行扫描;使acc的{​​{1}}参数严格;使用insertSet高阶函数;使用foldl'中的函数。

不过,最好还是使用其他数据结构。在这种情况下,由于通过计数字母的出现可以包含或排除少量可能的结果(Data.List.Ordered["cat"]["dog"]等),因此您可以只需计算每个字母一次通过的次数即可。