【问题标题】:Haskell generating pre-filtered permutationsHaskell 生成预过滤排列
【发布时间】:2019-02-07 00:17:03
【问题描述】:

有没有办法生成预过滤排列,而不是这样做:

filter condition $ permutations list

置换函数可以短路。例如:

perms [] = [[]]
perms xs = [ i:j | i <- xs, j <- perms $ delete i xs]

我尝试了一些明显的方法,例如:

perms xs = [ i:j | i <- xs, j <- filter condition $ perms $ delete i xs]

我认为会发生什么会引发一个链,该链最终会在 [] 处结束,然后继续工作,但会一路过滤。然而,当给它一个长长的列表时,从而加快了这个过程。这似乎没有发生,因为它在尝试对 20 项列表进行排列时陷入困境(ghci),而该列表实际上只有很少的过滤排列。

【问题讨论】:

  • 您的“短路”版本与简单版本不匹配。 condition 在“短路”版本中递归应用。
  • 你到底想做什么?听起来你有一个谓词,如果它对列表的某个尾部为假,那么它对整个列表都是假的,所以你的目标是编写一个算法,避免生成和检查一堆具有相同坏尾的排列,出于性能原因。对吗?
  • @jberryman 是的,没错。
  • 如果not (condition [])你想要什么?

标签: haskell recursion filtering permutation recursive-backtracking


【解决方案1】:

do 符号用递归编码它非常简单。

foo :: ([a] -> Bool) -> [a] -> [[a]]
foo p xs = bar ([],xs)
   where
   bar (acc,[]) = return acc
   bar (acc,xs) = do
                   (x,ys) <- picks xs      -- shrink the domain (ys)
                   if ( p (x:acc) )        -- test soon
                     then bar (x:acc,ys)   -- loop
                     else mzero            -- fail early

picks [] = []
picks (x : xs) = (x, xs) : [(y, x : ys) | (y, ys) <- picks xs]

picks 来自this answer

测试:

> foo (const True) [1..3]
[[3,2,1],[2,3,1],[3,1,2],[1,3,2],[2,1,3],[1,2,3]]

> foo (\(x:xs) -> not(null xs) || x > 1) [1..3]
[[3,1,2],[1,3,2],[2,1,3],[1,2,3]]

最后一个也立即开始为[1..20][1..300] 等生成输出。

我相信这可以用更高层次的东西巧妙地表达出来。

【讨论】:

    猜你喜欢
    • 2020-05-20
    • 2014-11-27
    • 2016-06-14
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多